blob: ab8c1dd1f151f9c8c9c4aec6d66c0196ddb3a91b [file] [log] [blame]
Vince Lehmanb8b18062015-07-14 13:07:22 -05001# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -05003# Copyright (C) 2015-2017, The University of Memphis,
Vince Lehman5d5a5662015-12-02 12:33:12 -06004# Arizona Board of Regents,
5# Regents of the University of California.
Vince Lehmanb8b18062015-07-14 13:07:22 -05006#
7# This file is part of Mini-NDN.
8# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
9#
10# Mini-NDN is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# Mini-NDN is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with Mini-NDN, e.g., in COPYING.md file.
22# If not, see <http://www.gnu.org/licenses/>.
23
Vince Lehman5d5a5662015-12-02 12:33:12 -060024from mininet.clean import sh
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050025from mininet.examples.cluster import RemoteMixin
Vince Lehman5d5a5662015-12-02 12:33:12 -060026
Ashlesh Gawande792c6aa2015-07-10 12:18:36 -050027from ndn.ndn_application import NdnApplication
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050028from ndn.util import ssh, scp
ashuef3490b2015-02-17 11:01:04 -060029
Vince Lehman5d5a5662015-12-02 12:33:12 -060030import shutil
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050031import os
Vince Lehman5d5a5662015-12-02 12:33:12 -060032import textwrap
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050033from subprocess import call
Vince Lehman5d5a5662015-12-02 12:33:12 -060034
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -060035NETWORK="/ndn/"
36
Ashlesh Gawande792c6aa2015-07-10 12:18:36 -050037class Nlsr(NdnApplication):
ashuef3490b2015-02-17 11:01:04 -060038 def __init__(self, node):
Ashlesh Gawande792c6aa2015-07-10 12:18:36 -050039 NdnApplication.__init__(self, node)
ashuef3490b2015-02-17 11:01:04 -060040 self.routerName = "/%sC1.Router/cs/%s" % ('%', node.name)
Ashlesh Gawande1b663692015-10-14 16:38:10 -050041 self.confFile = "%s/nlsr.conf" % node.homeFolder
ashuef3490b2015-02-17 11:01:04 -060042
43 # Make directory for log file
Ashlesh Gawande1b663692015-10-14 16:38:10 -050044 self.logDir = "%s/log" % node.homeFolder
ashuef3490b2015-02-17 11:01:04 -060045 node.cmd("mkdir %s" % self.logDir)
46
ashuef3490b2015-02-17 11:01:04 -060047 def start(self):
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -060048 # Removed & at the end, was giving key not found error
49 # This way NLSR is daemonized fully before continuing
Ashlesh Gawande5518f712016-11-28 13:06:38 -060050 NdnApplication.start(self, "nlsr -d -f {}".format(self.confFile))
ashuef3490b2015-02-17 11:01:04 -060051
Vince Lehman5d5a5662015-12-02 12:33:12 -060052 @staticmethod
53 def createKey(host, name, outputFile):
54 host.cmd("ndnsec-keygen {} > {}".format(name, outputFile))
55
56 @staticmethod
57 def createCertificate(host, name, prefix, keyFile, outputFile, signer=None):
58 if signer is None:
59 host.cmd("ndnsec-certgen -N {} -p {} {} > {}".format(name, prefix, keyFile, outputFile))
60 else:
61 host.cmd("ndnsec-certgen -N {} -p {} -s {} {} > {}".format(name, prefix, signer, keyFile, outputFile))
62
63 @staticmethod
64 def createKeysAndCertificates(net, workDir):
65 securityDir = "{}/security".format(workDir)
66
67 if not os.path.exists(securityDir):
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050068 os.mkdir(securityDir)
Vince Lehman5d5a5662015-12-02 12:33:12 -060069
70 # Create root certificate
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -060071 rootName = NETWORK
Vince Lehman5d5a5662015-12-02 12:33:12 -060072 sh("ndnsec-keygen {} > {}/root.keys".format(rootName, securityDir))
73 sh("ndnsec-certgen -N {} -p {} {}/root.keys > {}/root.cert".format(rootName, rootName, securityDir, securityDir))
74
75 # Create necessary certificates for each site
76 for host in net.hosts:
77 nodeSecurityFolder = "{}/security".format(host.homeFolder)
78
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050079 host.cmd("mkdir -p %s" % nodeSecurityFolder)
80
81 # Create temp folders for remote nodes on this machine (localhost) to store site.key file
82 # from RemoteNodes
83 if not os.path.exists(nodeSecurityFolder) and isinstance(host, RemoteMixin) and host.isRemote:
84 os.makedirs(nodeSecurityFolder)
Vince Lehman5d5a5662015-12-02 12:33:12 -060085
86 shutil.copyfile("{}/root.cert".format(securityDir), "{}/root.cert".format(nodeSecurityFolder))
87
88 # Create site certificate
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -060089 siteName = "{}{}-site".format(NETWORK, host.name)
Vince Lehman5d5a5662015-12-02 12:33:12 -060090 siteKeyFile = "{}/site.keys".format(nodeSecurityFolder)
91 siteCertFile = "{}/site.cert".format(nodeSecurityFolder)
92 Nlsr.createKey(host, siteName, siteKeyFile)
93
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050094 # Copy siteKeyFile from remote for ndnsec-certgen
95 if isinstance(host, RemoteMixin) and host.isRemote:
96 login = "mininet@{}".format(host.server)
97 src = "{}:{}".format(login, siteKeyFile)
98 dst = siteKeyFile
99 scp(src, dst)
100
Vince Lehman5d5a5662015-12-02 12:33:12 -0600101 # Root key is in root namespace, must sign site key and then install on host
102 sh("ndnsec-certgen -N {} -s {} -p {} {} > {}".format(siteName, rootName, siteName, siteKeyFile, siteCertFile))
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500103
104 # Copy root.cert and site.cert from localhost to remote host
105 if isinstance(host, RemoteMixin) and host.isRemote:
106 login = "mininet@{}".format(host.server)
107 src = "{}/site.cert".format(nodeSecurityFolder)
108 src2 = "{}/root.cert".format(nodeSecurityFolder)
109 dst = "{}:/tmp/".format(login)
110 scp(src, src2, dst)
111 host.cmd("mv /tmp/*.cert {}".format(nodeSecurityFolder))
112
Vince Lehman5d5a5662015-12-02 12:33:12 -0600113 host.cmd("ndnsec-cert-install -f {}".format(siteCertFile))
114
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600115 # Create and install operator certificate
Vince Lehman5d5a5662015-12-02 12:33:12 -0600116 opName = "{}/%C1.Operator/op".format(siteName)
117 opKeyFile = "{}/op.keys".format(nodeSecurityFolder)
118 opCertFile = "{}/op.cert".format(nodeSecurityFolder)
119 Nlsr.createKey(host, opName, opKeyFile)
120 Nlsr.createCertificate(host, opName, opName, opKeyFile, opCertFile, signer=siteName)
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600121 host.cmd("ndnsec-cert-install -f {}".format(opCertFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -0600122
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600123 # Create and install router certificate
Vince Lehman5d5a5662015-12-02 12:33:12 -0600124 routerName = "{}/%C1.Router/cs/{}".format(siteName, host.name)
125 routerKeyFile = "{}/router.keys".format(nodeSecurityFolder)
126 routerCertFile = "{}/router.cert".format(nodeSecurityFolder)
127 Nlsr.createKey(host, routerName, routerKeyFile)
128 Nlsr.createCertificate(host, routerName, routerName, routerKeyFile, routerCertFile, signer=opName)
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600129 host.cmd("ndnsec-cert-install -f {}".format(routerCertFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -0600130
ashuef3490b2015-02-17 11:01:04 -0600131class NlsrConfigGenerator:
132
133 ROUTING_LINK_STATE = "ls"
134 ROUTING_HYPERBOLIC = "hr"
135
Vince Lehman5d5a5662015-12-02 12:33:12 -0600136 def __init__(self, node, isSecurityEnabled):
ashuef3490b2015-02-17 11:01:04 -0600137 self.node = node
Vince Lehman5d5a5662015-12-02 12:33:12 -0600138 self.isSecurityEnabled = isSecurityEnabled
ashuef3490b2015-02-17 11:01:04 -0600139
140 parameters = node.nlsrParameters
141
142 self.nFaces = parameters.get("max-faces-per-prefix", 3)
143 self.hyperbolicState = parameters.get("hyperbolic-state", "off")
144 self.hyperRadius = parameters.get("radius", 0.0)
145 self.hyperAngle = parameters.get("angle", 0.0)
Ashlesh Gawandec3ed2b92015-07-01 12:58:08 -0500146 self.logLevel = parameters.get("nlsr-log-level", "DEBUG")
ashuef3490b2015-02-17 11:01:04 -0600147
148 def createConfigFile(self):
149
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500150 tmp_conf = "/tmp/nlsr.conf"
ashuef3490b2015-02-17 11:01:04 -0600151
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500152 configFile = open(tmp_conf, 'w')
153 configFile.write(self.__getConfig())
ashuef3490b2015-02-17 11:01:04 -0600154 configFile.close()
155
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500156 # If this node is a remote node scp the nlsr.conf file to its /tmp/nlsr.conf
157 if isinstance(self.node, RemoteMixin) and self.node.isRemote:
158 login = "mininet@%s" % self.node.server
159 src = tmp_conf
160 dst = "%s:%s" % (login, tmp_conf)
161 scp(src, dst)
ashuef3490b2015-02-17 11:01:04 -0600162
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500163 # Copy nlsr.conf to home folder
164 self.node.cmd("mv %s nlsr.conf" % tmp_conf)
ashuef3490b2015-02-17 11:01:04 -0600165
166 def __getConfig(self):
167
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500168 config = self.__getGeneralSection() + "\n"
169 config += self.__getNeighborsSection() + "\n"
170 config += self.__getHyperbolicSection() + "\n"
171 config += self.__getFibSection() + "\n"
172 config += self.__getAdvertisingSection() + "\n"
ashuef3490b2015-02-17 11:01:04 -0600173 config += self.__getSecuritySection()
174
175 return config
176
177 def __getGeneralSection(self):
178
179 general = "general\n"
180 general += "{\n"
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -0600181 general += " network {}\n".format(NETWORK)
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -0600182 general += " site /{}-site\n".format(self.node.name)
ashuef3490b2015-02-17 11:01:04 -0600183 general += " router /%C1.Router/cs/" + self.node.name + "\n"
Ashlesh Gawandec3ed2b92015-07-01 12:58:08 -0500184 general += " log-level " + self.logLevel + "\n"
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500185 general += " log-dir " + self.node.homeFolder + "/log\n"
186 general += " seq-dir " + self.node.homeFolder + "/log\n"
ashuef3490b2015-02-17 11:01:04 -0600187 general += "}\n"
188
189 return general
190
191 def __getNeighborsSection(self):
192
193 neighbors = "neighbors\n"
194 neighbors += "{\n"
195
196 for intf in self.node.intfList():
197 link = intf.link
198 if link:
199 node1, node2 = link.intf1.node, link.intf2.node
200
201 if node1 == self.node:
202 other = node2
203 ip = other.IP(str(link.intf2))
204 else:
205 other = node1
206 ip = other.IP(str(link.intf1))
207
ashu7b6ba182015-04-17 15:02:37 -0500208 linkCost = intf.params.get("delay", "10ms").replace("ms", "")
ashuef3490b2015-02-17 11:01:04 -0600209
210 neighbors += "neighbor\n"
211 neighbors += "{\n"
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -0600212 neighbors += " name " + NETWORK + other.name + "-site/%C1.Router/cs/" + other.name + "\n"
ashuef3490b2015-02-17 11:01:04 -0600213 neighbors += " face-uri udp://" + str(ip) + "\n"
214 neighbors += " link-cost " + linkCost + "\n"
215 neighbors += "}\n"
216
217 neighbors += "}\n"
218
219 return neighbors
220
221 def __getHyperbolicSection(self):
222
223 hyper = "hyperbolic\n"
224 hyper += "{\n"
225 hyper += "state %s\n" % self.hyperbolicState
226 hyper += "radius " + str(self.hyperRadius) + "\n"
227 hyper += "angle " + str(self.hyperAngle) + "\n"
228 hyper += "}\n"
229
230 return hyper
231
232 def __getFibSection(self):
233
234 fib = "fib\n"
235 fib += "{\n"
236 fib += " max-faces-per-prefix " + str(self.nFaces) + "\n"
237 fib += "}\n"
238
239 return fib
240
241 def __getAdvertisingSection(self):
242
243 advertising = "advertising\n"
244 advertising += "{\n"
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -0600245 advertising += " prefix "+ NETWORK + self.node.name + "-site/" + self.node.name + "\n"
ashuef3490b2015-02-17 11:01:04 -0600246 advertising += "}\n"
247
248 return advertising
249
250 def __getSecuritySection(self):
Vince Lehman5d5a5662015-12-02 12:33:12 -0600251 if self.isSecurityEnabled is False:
252 security = textwrap.dedent("""\
253 security
254 {
255 validator
256 {
257 trust-anchor
258 {
259 type any
260 }
261 }
262 prefix-update-validator
263 {
264 trust-anchor
265 {
266 type any
267 }
268 }
269 }""")
270 else:
271 security = textwrap.dedent("""\
272 security
273 {
274 validator
275 {
276 rule
277 {
278 id "NSLR Hello Rule"
279 for data
280 filter
281 {
282 type name
283 regex ^[^<NLSR><INFO>]*<NLSR><INFO><><>$
284 }
285 checker
286 {
287 type customized
288 sig-type rsa-sha256
289 key-locator
290 {
291 type name
292 hyper-relation
293 {
294 k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
295 k-expand \\\\1
296 h-relation equal
297 p-regex ^([^<NLSR><INFO>]*)<NLSR><INFO><><>$
298 p-expand \\\\1
299 }
300 }
301 }
302 }
ashuef3490b2015-02-17 11:01:04 -0600303
Vince Lehman5d5a5662015-12-02 12:33:12 -0600304 rule
305 {
306 id "NSLR LSA Rule"
307 for data
308 filter
309 {
310 type name
311 regex ^[^<NLSR><LSA>]*<NLSR><LSA>
312 }
313 checker
314 {
315 type customized
316 sig-type rsa-sha256
317 key-locator
318 {
319 type name
320 hyper-relation
321 {
322 k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
323 k-expand \\\\1
324 h-relation equal
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600325 p-regex ^<localhop>([^<NLSR><LSA>]*)<NLSR><LSA>(<>*)<><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600326 p-expand \\\\1\\\\2
327 }
328 }
329 }
330 }
331
332 rule
333 {
334 id "NSLR Hierarchy Exception Rule"
335 for data
336 filter
337 {
338 type name
339 regex ^[^<KEY><%C1.Router>]*<%C1.Router>[^<KEY><NLSR>]*<KEY><ksk-.*><ID-CERT><>$
340 }
341 checker
342 {
343 type customized
344 sig-type rsa-sha256
345 key-locator
346 {
347 type name
348 hyper-relation
349 {
350 k-regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
351 k-expand \\\\1
352 h-relation equal
353 p-regex ^([^<KEY><%C1.Router>]*)<%C1.Router>[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
354 p-expand \\\\1
355 }
356 }
357 }
358 }
359
360 rule
361 {
362 id "NSLR Hierarchical Rule"
363 for data
364 filter
365 {
366 type name
367 regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
368 }
369 checker
370 {
371 type hierarchical
372 sig-type rsa-sha256
373 }
374 }
375
376 trust-anchor
377 {
378 type file
379 file-name "security/root.cert"
380 }
381 }
382
383 prefix-update-validator
384 {
385 rule
386 {
387 id "NLSR ControlCommand Rule"
388 for interest
389 filter
390 {
391 type name
392 regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<>$
393 }
394 checker
395 {
396 type customized
397 sig-type rsa-sha256
398 key-locator
399 {
400 type name
401 regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
402 }
403 }
404 }
405
406 rule
407 {
408 id "NLSR Hierarchy Rule"
409 for data
410 filter
411 {
412 type name
413 regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
414 }
415 checker
416 {
417 type hierarchical
418 sig-type rsa-sha256
419 }
420 }
421
422 trust-anchor
423 {
424 type file
425 file-name "security/site.cert"
426 }
427 }
428 ; cert-to-publish "security/root.cert" ; optional, a file containing the root certificate
429 ; Only the router that is designated to publish the root cert
430 ; needs to specify this
431
432 cert-to-publish "security/site.cert" ; optional, a file containing the site certificate
433 ; Only the router that is designated to publish the site cert
434 ; needs to specify this
435
436 cert-to-publish "security/op.cert" ; optional, a file containing the operator certificate
437 ; Only the router that is designated to publish the operator
438 ; cert needs to specify this
439
440 cert-to-publish "security/router.cert" ; required, a file containing the router certificate.
441 }""")
ashuef3490b2015-02-17 11:01:04 -0600442
443 return security