blob: 0e22361c69a5c15c5d321adffe6b0865964b21e8 [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 Gawande792c6aa2015-07-10 12:18:36 -050035class Nlsr(NdnApplication):
ashuef3490b2015-02-17 11:01:04 -060036 def __init__(self, node):
Ashlesh Gawande792c6aa2015-07-10 12:18:36 -050037 NdnApplication.__init__(self, node)
ashuef3490b2015-02-17 11:01:04 -060038 self.routerName = "/%sC1.Router/cs/%s" % ('%', node.name)
Ashlesh Gawande1b663692015-10-14 16:38:10 -050039 self.confFile = "%s/nlsr.conf" % node.homeFolder
ashuef3490b2015-02-17 11:01:04 -060040
41 # Make directory for log file
Ashlesh Gawande1b663692015-10-14 16:38:10 -050042 self.logDir = "%s/log" % node.homeFolder
ashuef3490b2015-02-17 11:01:04 -060043 node.cmd("mkdir %s" % self.logDir)
44
ashuef3490b2015-02-17 11:01:04 -060045 def start(self):
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -060046 # Removed & at the end, was giving key not found error
47 # This way NLSR is daemonized fully before continuing
Ashlesh Gawande5518f712016-11-28 13:06:38 -060048 NdnApplication.start(self, "nlsr -d -f {}".format(self.confFile))
ashuef3490b2015-02-17 11:01:04 -060049
Vince Lehman5d5a5662015-12-02 12:33:12 -060050 @staticmethod
51 def createKey(host, name, outputFile):
52 host.cmd("ndnsec-keygen {} > {}".format(name, outputFile))
53
54 @staticmethod
55 def createCertificate(host, name, prefix, keyFile, outputFile, signer=None):
56 if signer is None:
57 host.cmd("ndnsec-certgen -N {} -p {} {} > {}".format(name, prefix, keyFile, outputFile))
58 else:
59 host.cmd("ndnsec-certgen -N {} -p {} -s {} {} > {}".format(name, prefix, signer, keyFile, outputFile))
60
61 @staticmethod
62 def createKeysAndCertificates(net, workDir):
63 securityDir = "{}/security".format(workDir)
64
65 if not os.path.exists(securityDir):
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050066 os.mkdir(securityDir)
Vince Lehman5d5a5662015-12-02 12:33:12 -060067
68 # Create root certificate
69 rootName = "/ndn"
70 sh("ndnsec-keygen {} > {}/root.keys".format(rootName, securityDir))
71 sh("ndnsec-certgen -N {} -p {} {}/root.keys > {}/root.cert".format(rootName, rootName, securityDir, securityDir))
72
73 # Create necessary certificates for each site
74 for host in net.hosts:
75 nodeSecurityFolder = "{}/security".format(host.homeFolder)
76
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050077 host.cmd("mkdir -p %s" % nodeSecurityFolder)
78
79 # Create temp folders for remote nodes on this machine (localhost) to store site.key file
80 # from RemoteNodes
81 if not os.path.exists(nodeSecurityFolder) and isinstance(host, RemoteMixin) and host.isRemote:
82 os.makedirs(nodeSecurityFolder)
Vince Lehman5d5a5662015-12-02 12:33:12 -060083
84 shutil.copyfile("{}/root.cert".format(securityDir), "{}/root.cert".format(nodeSecurityFolder))
85
86 # Create site certificate
Ashlesh Gawande3bed4832017-02-08 18:17:31 -060087 siteName = "/ndn/{}-site".format(host.name)
Vince Lehman5d5a5662015-12-02 12:33:12 -060088 siteKeyFile = "{}/site.keys".format(nodeSecurityFolder)
89 siteCertFile = "{}/site.cert".format(nodeSecurityFolder)
90 Nlsr.createKey(host, siteName, siteKeyFile)
91
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050092 # Copy siteKeyFile from remote for ndnsec-certgen
93 if isinstance(host, RemoteMixin) and host.isRemote:
94 login = "mininet@{}".format(host.server)
95 src = "{}:{}".format(login, siteKeyFile)
96 dst = siteKeyFile
97 scp(src, dst)
98
Vince Lehman5d5a5662015-12-02 12:33:12 -060099 # Root key is in root namespace, must sign site key and then install on host
100 sh("ndnsec-certgen -N {} -s {} -p {} {} > {}".format(siteName, rootName, siteName, siteKeyFile, siteCertFile))
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500101
102 # Copy root.cert and site.cert from localhost to remote host
103 if isinstance(host, RemoteMixin) and host.isRemote:
104 login = "mininet@{}".format(host.server)
105 src = "{}/site.cert".format(nodeSecurityFolder)
106 src2 = "{}/root.cert".format(nodeSecurityFolder)
107 dst = "{}:/tmp/".format(login)
108 scp(src, src2, dst)
109 host.cmd("mv /tmp/*.cert {}".format(nodeSecurityFolder))
110
Vince Lehman5d5a5662015-12-02 12:33:12 -0600111 host.cmd("ndnsec-cert-install -f {}".format(siteCertFile))
112
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600113 # Create and install operator certificate
Vince Lehman5d5a5662015-12-02 12:33:12 -0600114 opName = "{}/%C1.Operator/op".format(siteName)
115 opKeyFile = "{}/op.keys".format(nodeSecurityFolder)
116 opCertFile = "{}/op.cert".format(nodeSecurityFolder)
117 Nlsr.createKey(host, opName, opKeyFile)
118 Nlsr.createCertificate(host, opName, opName, opKeyFile, opCertFile, signer=siteName)
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600119 host.cmd("ndnsec-cert-install -f {}".format(opCertFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -0600120
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600121 # Create and install router certificate
Vince Lehman5d5a5662015-12-02 12:33:12 -0600122 routerName = "{}/%C1.Router/cs/{}".format(siteName, host.name)
123 routerKeyFile = "{}/router.keys".format(nodeSecurityFolder)
124 routerCertFile = "{}/router.cert".format(nodeSecurityFolder)
125 Nlsr.createKey(host, routerName, routerKeyFile)
126 Nlsr.createCertificate(host, routerName, routerName, routerKeyFile, routerCertFile, signer=opName)
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600127 host.cmd("ndnsec-cert-install -f {}".format(routerCertFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -0600128
ashuef3490b2015-02-17 11:01:04 -0600129class NlsrConfigGenerator:
130
131 ROUTING_LINK_STATE = "ls"
132 ROUTING_HYPERBOLIC = "hr"
133
Vince Lehman5d5a5662015-12-02 12:33:12 -0600134 def __init__(self, node, isSecurityEnabled):
ashuef3490b2015-02-17 11:01:04 -0600135 self.node = node
Vince Lehman5d5a5662015-12-02 12:33:12 -0600136 self.isSecurityEnabled = isSecurityEnabled
ashuef3490b2015-02-17 11:01:04 -0600137
138 parameters = node.nlsrParameters
139
140 self.nFaces = parameters.get("max-faces-per-prefix", 3)
141 self.hyperbolicState = parameters.get("hyperbolic-state", "off")
142 self.hyperRadius = parameters.get("radius", 0.0)
143 self.hyperAngle = parameters.get("angle", 0.0)
Ashlesh Gawandec3ed2b92015-07-01 12:58:08 -0500144 self.logLevel = parameters.get("nlsr-log-level", "DEBUG")
ashuef3490b2015-02-17 11:01:04 -0600145
146 def createConfigFile(self):
147
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500148 tmp_conf = "/tmp/nlsr.conf"
ashuef3490b2015-02-17 11:01:04 -0600149
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500150 configFile = open(tmp_conf, 'w')
151 configFile.write(self.__getConfig())
ashuef3490b2015-02-17 11:01:04 -0600152 configFile.close()
153
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500154 # If this node is a remote node scp the nlsr.conf file to its /tmp/nlsr.conf
155 if isinstance(self.node, RemoteMixin) and self.node.isRemote:
156 login = "mininet@%s" % self.node.server
157 src = tmp_conf
158 dst = "%s:%s" % (login, tmp_conf)
159 scp(src, dst)
ashuef3490b2015-02-17 11:01:04 -0600160
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500161 # Copy nlsr.conf to home folder
162 self.node.cmd("mv %s nlsr.conf" % tmp_conf)
ashuef3490b2015-02-17 11:01:04 -0600163
164 def __getConfig(self):
165
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500166 config = self.__getGeneralSection() + "\n"
167 config += self.__getNeighborsSection() + "\n"
168 config += self.__getHyperbolicSection() + "\n"
169 config += self.__getFibSection() + "\n"
170 config += self.__getAdvertisingSection() + "\n"
ashuef3490b2015-02-17 11:01:04 -0600171 config += self.__getSecuritySection()
172
173 return config
174
175 def __getGeneralSection(self):
176
177 general = "general\n"
178 general += "{\n"
179 general += " network /ndn/\n"
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -0600180 general += " site /{}-site\n".format(self.node.name)
ashuef3490b2015-02-17 11:01:04 -0600181 general += " router /%C1.Router/cs/" + self.node.name + "\n"
Ashlesh Gawandec3ed2b92015-07-01 12:58:08 -0500182 general += " log-level " + self.logLevel + "\n"
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500183 general += " log-dir " + self.node.homeFolder + "/log\n"
184 general += " seq-dir " + self.node.homeFolder + "/log\n"
ashuef3490b2015-02-17 11:01:04 -0600185 general += "}\n"
186
187 return general
188
189 def __getNeighborsSection(self):
190
191 neighbors = "neighbors\n"
192 neighbors += "{\n"
193
194 for intf in self.node.intfList():
195 link = intf.link
196 if link:
197 node1, node2 = link.intf1.node, link.intf2.node
198
199 if node1 == self.node:
200 other = node2
201 ip = other.IP(str(link.intf2))
202 else:
203 other = node1
204 ip = other.IP(str(link.intf1))
205
ashu7b6ba182015-04-17 15:02:37 -0500206 linkCost = intf.params.get("delay", "10ms").replace("ms", "")
ashuef3490b2015-02-17 11:01:04 -0600207
208 neighbors += "neighbor\n"
209 neighbors += "{\n"
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -0600210 neighbors += " name /ndn/" + other.name + "-site/%C1.Router/cs/" + other.name + "\n"
ashuef3490b2015-02-17 11:01:04 -0600211 neighbors += " face-uri udp://" + str(ip) + "\n"
212 neighbors += " link-cost " + linkCost + "\n"
213 neighbors += "}\n"
214
215 neighbors += "}\n"
216
217 return neighbors
218
219 def __getHyperbolicSection(self):
220
221 hyper = "hyperbolic\n"
222 hyper += "{\n"
223 hyper += "state %s\n" % self.hyperbolicState
224 hyper += "radius " + str(self.hyperRadius) + "\n"
225 hyper += "angle " + str(self.hyperAngle) + "\n"
226 hyper += "}\n"
227
228 return hyper
229
230 def __getFibSection(self):
231
232 fib = "fib\n"
233 fib += "{\n"
234 fib += " max-faces-per-prefix " + str(self.nFaces) + "\n"
235 fib += "}\n"
236
237 return fib
238
239 def __getAdvertisingSection(self):
240
241 advertising = "advertising\n"
242 advertising += "{\n"
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -0600243 advertising += " prefix /ndn/" + self.node.name + "-site/" + self.node.name + "\n"
ashuef3490b2015-02-17 11:01:04 -0600244 advertising += "}\n"
245
246 return advertising
247
248 def __getSecuritySection(self):
Vince Lehman5d5a5662015-12-02 12:33:12 -0600249 if self.isSecurityEnabled is False:
250 security = textwrap.dedent("""\
251 security
252 {
253 validator
254 {
255 trust-anchor
256 {
257 type any
258 }
259 }
260 prefix-update-validator
261 {
262 trust-anchor
263 {
264 type any
265 }
266 }
267 }""")
268 else:
269 security = textwrap.dedent("""\
270 security
271 {
272 validator
273 {
274 rule
275 {
276 id "NSLR Hello Rule"
277 for data
278 filter
279 {
280 type name
281 regex ^[^<NLSR><INFO>]*<NLSR><INFO><><>$
282 }
283 checker
284 {
285 type customized
286 sig-type rsa-sha256
287 key-locator
288 {
289 type name
290 hyper-relation
291 {
292 k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
293 k-expand \\\\1
294 h-relation equal
295 p-regex ^([^<NLSR><INFO>]*)<NLSR><INFO><><>$
296 p-expand \\\\1
297 }
298 }
299 }
300 }
ashuef3490b2015-02-17 11:01:04 -0600301
Vince Lehman5d5a5662015-12-02 12:33:12 -0600302 rule
303 {
304 id "NSLR LSA Rule"
305 for data
306 filter
307 {
308 type name
309 regex ^[^<NLSR><LSA>]*<NLSR><LSA>
310 }
311 checker
312 {
313 type customized
314 sig-type rsa-sha256
315 key-locator
316 {
317 type name
318 hyper-relation
319 {
320 k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
321 k-expand \\\\1
322 h-relation equal
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600323 p-regex ^<localhop>([^<NLSR><LSA>]*)<NLSR><LSA>(<>*)<><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600324 p-expand \\\\1\\\\2
325 }
326 }
327 }
328 }
329
330 rule
331 {
332 id "NSLR Hierarchy Exception Rule"
333 for data
334 filter
335 {
336 type name
337 regex ^[^<KEY><%C1.Router>]*<%C1.Router>[^<KEY><NLSR>]*<KEY><ksk-.*><ID-CERT><>$
338 }
339 checker
340 {
341 type customized
342 sig-type rsa-sha256
343 key-locator
344 {
345 type name
346 hyper-relation
347 {
348 k-regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
349 k-expand \\\\1
350 h-relation equal
351 p-regex ^([^<KEY><%C1.Router>]*)<%C1.Router>[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
352 p-expand \\\\1
353 }
354 }
355 }
356 }
357
358 rule
359 {
360 id "NSLR Hierarchical Rule"
361 for data
362 filter
363 {
364 type name
365 regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
366 }
367 checker
368 {
369 type hierarchical
370 sig-type rsa-sha256
371 }
372 }
373
374 trust-anchor
375 {
376 type file
377 file-name "security/root.cert"
378 }
379 }
380
381 prefix-update-validator
382 {
383 rule
384 {
385 id "NLSR ControlCommand Rule"
386 for interest
387 filter
388 {
389 type name
390 regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<>$
391 }
392 checker
393 {
394 type customized
395 sig-type rsa-sha256
396 key-locator
397 {
398 type name
399 regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
400 }
401 }
402 }
403
404 rule
405 {
406 id "NLSR Hierarchy Rule"
407 for data
408 filter
409 {
410 type name
411 regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
412 }
413 checker
414 {
415 type hierarchical
416 sig-type rsa-sha256
417 }
418 }
419
420 trust-anchor
421 {
422 type file
423 file-name "security/site.cert"
424 }
425 }
426 ; cert-to-publish "security/root.cert" ; optional, a file containing the root certificate
427 ; Only the router that is designated to publish the root cert
428 ; needs to specify this
429
430 cert-to-publish "security/site.cert" ; optional, a file containing the site certificate
431 ; Only the router that is designated to publish the site cert
432 ; needs to specify this
433
434 cert-to-publish "security/op.cert" ; optional, a file containing the operator certificate
435 ; Only the router that is designated to publish the operator
436 ; cert needs to specify this
437
438 cert-to-publish "security/router.cert" ; required, a file containing the router certificate.
439 }""")
ashuef3490b2015-02-17 11:01:04 -0600440
441 return security