% vim set ft=prolog :- module(bgp, [ warning/1, create_firewall/0, neighbor/2, bgp_config/2, bird_config/1, remote_network/2, remote_networks/2]). :- use_module(hosts, [ host/1, host_config/2, router_link/3, attached_network/2]). :- use_module(firewall, [ fw_rule/2, retract_all_from/1]). %host(H) :- router_link(H, _, _). %host(H) :- router_link(_, H, _). % host(H). router(R) :- host(R), hosts:host_config(R, _). routers(Routers) :- setof(router(R), router(R), Routers). neighbor(H, R) :- router(H), router(R), router_link(H, _, R), router_link(R, _, H). warning(Msg) :- host(H), host(R), router_link(H, _, R), \+ router_link(R, _, H), format(string(Msg), "Missing router_link from '~w' to '~w'", [R, H]). neighbors(H, Cs) :- findall(neighbor(H, Name), neighbor(H, Name), Cs). bgp_config(H, Connections) :- neighbor(H, Connections). % bgp_config(H)? bird_protocol_bgp(Router, Neighbor, Address, AllowedNetworks) :- router_link(Router, _, Neighbor), router_link(Neighbor, Address, Router), AllowedNetworks = []. % edge(a, b). edge(b, c). edge(c, d). edge(d, a). % path(X, Y) :- edge(X, Y). % path(X, Y) :- edge(X, Z), path(Z, Y). attached_networks(Router, Ns) :- findall(N, attached_network(Router, N), Ns). remote_network(Router, N) :- router_link(Router, _, Remote), attached_network(Remote, N). remote_networks(Router, Ns) :- router_link(Router, _, Remote), attached_networks(Remote, Ns). % doesn't recurse % available_networks(R, Ns) :- % attached_networks(R, Attached), % setof(N, remote_network(R, N), Remote), % union(Attached, Remote, Xs), router_path(X, Y) :- router_path(X, Y, []). router_path(X, Y, _) :- router_link(X, _, Y). router_path(X, Y, V) :- \+ member(X, V), router_link(X, _, Z), router_path(Z, Y, [X|V]). %to_yaml(neighbor(H, Remote), Dict) :- Dict = yaml(router(H), remote(Remote)). %to_json(neighbor(H, Remote), Dict) :- Dict = json(router(H), remote(Remote)). to_dict(router(R), Dict) :- neighbors(R, Neighbors), maplist(to_dict(), Neighbors, NeighborDicts), Dict = R-_{ neighbors: NeighborDicts }. to_dict(neighbor(_, Remote), Dict) :- host_config(Remote, RC), Dict = neighbor{ neighbor:_{ name: Remote, hostname: RC.ip } }. bird_config(BirdConfig) :- routers(Routers), maplist(to_dict(), Routers, RouterDicts), dict_pairs(BirdConfig, bird_config, RouterDicts). create_firewall() :- firewall:retract_all_from(bgp), findall(fw(Host, Attrs), fw(Host, Attrs), Goals), maplist(assert_fw, Goals). assert_fw(fw(Host, Attrs)) :- R = firewall:fw_rule(Host, Attrs.put(_{from:bgp})), writeln(R), assert(R). fw(Host, attrs{src:Src, dst:Dst, family:ip6}) :- hosts:router_link(Host, _, Remote), hosts:host_config(Host, HostConfig), hosts:host_config(Remote, RemoteConfig), Src = RemoteConfig.ip, Dst = HostConfig.ip.