forked from freifunk/icvpn-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkbgp
executable file
·113 lines (93 loc) · 4.08 KB
/
mkbgp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python
from collections import defaultdict
from textwrap import dedent
from optparse import OptionParser
from socket import AF_INET, AF_INET6, inet_pton
from formatter import Formatter
from filereader import get_communities_data
class BirdFormatter(Formatter):
"Formatter for bind9 using type forward"
def add_data(self, asn, name, template, peer):
self.config.append(dedent("""
protocol bgp %s from %s {
neighbor %s as %s;
}
""" % (name, template, peer, asn)))
class QuaggaFormatter(Formatter):
"Formatter for quagga"
def add_comment(self, comment):
self.config.append("! " + "\n! ".join(comment.split("\n")))
def add_data(self, asn, name, template, peer):
self.config.append(dedent("""
neighbor %(peer)s remote-as %(asn)s
neighbor %(peer)s description %(name)s
neighbor %(peer)s peer-group %(template)s
""" % {"peer": peer, "asn": asn, "name": name, "template": template}))
def create_config(srcdir, exclude, prefix, defaulttemplate, templates, family,
fmtclass):
"""
Generates a configuration using all files in srcdir
(non-recursively) excluding communities from 'exclude'.
The files are read in lexicographic order to produce deterministic
results.
"""
formatter = fmtclass()
template = defaultdict(lambda: defaulttemplate)
template.update(dict(map(lambda s: s.split(":"), templates)))
for community, data in get_communities_data(srcdir, exclude):
try:
bgp = data["bgp"]
asn = data["asn"]
except (TypeError, KeyError):
continue
for host in sorted(bgp.keys()):
d = bgp[host]
if family not in d:
continue
peer = d[family]
formatter.add_data(asn, prefix + host,
template[community], peer)
print(formatter.finalize())
if __name__ == "__main__":
formatters = {
"bird": BirdFormatter,
"quagga": QuaggaFormatter,
}
parser = OptionParser()
parser.add_option("-f", "--format", dest="fmt",
help="""Create config in format FMT.
Possible values: %s. Default: dnsmasq""" %
", ".join(formatters.keys()),
metavar="FMT",
choices=list(formatters.keys()),
default="bird")
parser.add_option("-4", dest="family", action="store_const", const="ipv4",
help="Generate IPv4 config")
parser.add_option("-6", dest="family", action="store_const", const="ipv6",
help="Generate IPv6 config")
parser.add_option("-s", "--sourcedir", dest="src",
help="""Use files in DIR as input files.
Default: data/""", metavar="DIR",
default="data")
parser.add_option("-x", "--exclude", dest="exclude", action="append",
help="Exclude the comma-separated list of COMMUNITIES",
metavar="COMMUNITIES",
default=[])
parser.add_option("-p", "--prefix", dest="prefix",
help="Prefix, e.g. bgp_icvpn_",
metavar="PREFIX",
default="")
parser.add_option("-d", "--default", dest="defaulttemplate",
help="Default template/peer-group to use",
metavar="TEMPLATE",
default=None)
parser.add_option("-t", "--template", dest="templates", action="append",
help="Use different template/peer-group for some " +
"communities",
metavar="COMMUNITY:TEMPLATE",
default=[])
parser.set_defaults(family="ipv6")
(options, args) = parser.parse_args()
create_config(options.src, set(options.exclude), options.prefix,
options.defaulttemplate, options.templates,
options.family, formatters[options.fmt])