blob: 0fb73a7084cdb95869195701021d18146b0ba436 [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
Ashlesh Gawande59f86242017-05-05 09:45:18 -050034import time
Vince Lehman5d5a5662015-12-02 12:33:12 -060035
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -060036NETWORK="/ndn/"
37
Ashlesh Gawande792c6aa2015-07-10 12:18:36 -050038class Nlsr(NdnApplication):
Ashlesh Gawande708fcca2017-06-23 14:04:12 -050039 def __init__(self, node, neighbors, faceType):
Ashlesh Gawande792c6aa2015-07-10 12:18:36 -050040 NdnApplication.__init__(self, node)
Ashlesh Gawande708fcca2017-06-23 14:04:12 -050041 self.node = node
42 self.neighbors = neighbors
43 self.faceType = faceType
ashuef3490b2015-02-17 11:01:04 -060044 self.routerName = "/%sC1.Router/cs/%s" % ('%', node.name)
Ashlesh Gawande1b663692015-10-14 16:38:10 -050045 self.confFile = "%s/nlsr.conf" % node.homeFolder
ashuef3490b2015-02-17 11:01:04 -060046
47 # Make directory for log file
Ashlesh Gawande1b663692015-10-14 16:38:10 -050048 self.logDir = "%s/log" % node.homeFolder
Ashlesh Gawande708fcca2017-06-23 14:04:12 -050049 self.node.cmd("mkdir %s" % self.logDir)
50
51 # Create faces in NFD
52 self.createFaces()
ashuef3490b2015-02-17 11:01:04 -060053
ashuef3490b2015-02-17 11:01:04 -060054 def start(self):
Ashlesh Gawande59f86242017-05-05 09:45:18 -050055 NdnApplication.start(self, "nlsr -f {} > /dev/null 2>&1 &".format(self.confFile))
56 time.sleep(1)
ashuef3490b2015-02-17 11:01:04 -060057
Ashlesh Gawande708fcca2017-06-23 14:04:12 -050058 def createFaces(self):
59 for ip in self.neighbors:
60 self.node.cmd("nfdc face create {}://{} permanent".format(self.faceType, ip))
61
Vince Lehman5d5a5662015-12-02 12:33:12 -060062 @staticmethod
63 def createKey(host, name, outputFile):
64 host.cmd("ndnsec-keygen {} > {}".format(name, outputFile))
65
66 @staticmethod
Ashlesh Gawandea80484e2017-10-17 15:52:23 -050067 def createCertificate(host, signer, keyFile, outputFile):
68 host.cmd("ndnsec-certgen -s {} -r {} > {}".format(signer, keyFile, outputFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -060069
70 @staticmethod
71 def createKeysAndCertificates(net, workDir):
72 securityDir = "{}/security".format(workDir)
73
74 if not os.path.exists(securityDir):
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050075 os.mkdir(securityDir)
Vince Lehman5d5a5662015-12-02 12:33:12 -060076
77 # Create root certificate
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -060078 rootName = NETWORK
Ashlesh Gawandea80484e2017-10-17 15:52:23 -050079 sh("ndnsec-keygen {}".format(rootName)) # Installs a self-signed cert into the system
80 sh("ndnsec-cert-dump -i {} > {}/root.cert".format(rootName, securityDir, securityDir))
Vince Lehman5d5a5662015-12-02 12:33:12 -060081
82 # Create necessary certificates for each site
83 for host in net.hosts:
84 nodeSecurityFolder = "{}/security".format(host.homeFolder)
85
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -050086 host.cmd("mkdir -p %s" % nodeSecurityFolder)
87
88 # Create temp folders for remote nodes on this machine (localhost) to store site.key file
89 # from RemoteNodes
90 if not os.path.exists(nodeSecurityFolder) and isinstance(host, RemoteMixin) and host.isRemote:
91 os.makedirs(nodeSecurityFolder)
Vince Lehman5d5a5662015-12-02 12:33:12 -060092
93 shutil.copyfile("{}/root.cert".format(securityDir), "{}/root.cert".format(nodeSecurityFolder))
94
95 # Create site certificate
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -060096 siteName = "{}{}-site".format(NETWORK, host.name)
Vince Lehman5d5a5662015-12-02 12:33:12 -060097 siteKeyFile = "{}/site.keys".format(nodeSecurityFolder)
98 siteCertFile = "{}/site.cert".format(nodeSecurityFolder)
99 Nlsr.createKey(host, siteName, siteKeyFile)
100
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500101 # Copy siteKeyFile from remote for ndnsec-certgen
102 if isinstance(host, RemoteMixin) and host.isRemote:
103 login = "mininet@{}".format(host.server)
104 src = "{}:{}".format(login, siteKeyFile)
105 dst = siteKeyFile
106 scp(src, dst)
107
Vince Lehman5d5a5662015-12-02 12:33:12 -0600108 # Root key is in root namespace, must sign site key and then install on host
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500109 sh("ndnsec-certgen -s {} -r {} > {}".format(rootName, siteKeyFile, siteCertFile))
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500110
111 # Copy root.cert and site.cert from localhost to remote host
112 if isinstance(host, RemoteMixin) and host.isRemote:
113 login = "mininet@{}".format(host.server)
114 src = "{}/site.cert".format(nodeSecurityFolder)
115 src2 = "{}/root.cert".format(nodeSecurityFolder)
116 dst = "{}:/tmp/".format(login)
117 scp(src, src2, dst)
118 host.cmd("mv /tmp/*.cert {}".format(nodeSecurityFolder))
119
Vince Lehman5d5a5662015-12-02 12:33:12 -0600120 host.cmd("ndnsec-cert-install -f {}".format(siteCertFile))
121
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600122 # Create and install operator certificate
Vince Lehman5d5a5662015-12-02 12:33:12 -0600123 opName = "{}/%C1.Operator/op".format(siteName)
124 opKeyFile = "{}/op.keys".format(nodeSecurityFolder)
125 opCertFile = "{}/op.cert".format(nodeSecurityFolder)
126 Nlsr.createKey(host, opName, opKeyFile)
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500127 Nlsr.createCertificate(host, siteName, opKeyFile, opCertFile)
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600128 host.cmd("ndnsec-cert-install -f {}".format(opCertFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -0600129
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600130 # Create and install router certificate
Vince Lehman5d5a5662015-12-02 12:33:12 -0600131 routerName = "{}/%C1.Router/cs/{}".format(siteName, host.name)
132 routerKeyFile = "{}/router.keys".format(nodeSecurityFolder)
133 routerCertFile = "{}/router.cert".format(nodeSecurityFolder)
134 Nlsr.createKey(host, routerName, routerKeyFile)
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500135 Nlsr.createCertificate(host, opName, routerKeyFile, routerCertFile)
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600136 host.cmd("ndnsec-cert-install -f {}".format(routerCertFile))
Vince Lehman5d5a5662015-12-02 12:33:12 -0600137
ashuef3490b2015-02-17 11:01:04 -0600138class NlsrConfigGenerator:
139
140 ROUTING_LINK_STATE = "ls"
141 ROUTING_HYPERBOLIC = "hr"
142
Ashlesh Gawande708fcca2017-06-23 14:04:12 -0500143 def __init__(self, node, isSecurityEnabled, faceType):
ashuef3490b2015-02-17 11:01:04 -0600144 self.node = node
Vince Lehman5d5a5662015-12-02 12:33:12 -0600145 self.isSecurityEnabled = isSecurityEnabled
Ashlesh Gawande708fcca2017-06-23 14:04:12 -0500146 self.faceType = faceType
ashuef3490b2015-02-17 11:01:04 -0600147
148 parameters = node.nlsrParameters
149
150 self.nFaces = parameters.get("max-faces-per-prefix", 3)
151 self.hyperbolicState = parameters.get("hyperbolic-state", "off")
152 self.hyperRadius = parameters.get("radius", 0.0)
153 self.hyperAngle = parameters.get("angle", 0.0)
Ashlesh Gawandec3ed2b92015-07-01 12:58:08 -0500154 self.logLevel = parameters.get("nlsr-log-level", "DEBUG")
Ashlesh Gawande708fcca2017-06-23 14:04:12 -0500155 self.neighborIPs = []
ashuef3490b2015-02-17 11:01:04 -0600156
157 def createConfigFile(self):
158
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500159 tmp_conf = "/tmp/nlsr.conf"
ashuef3490b2015-02-17 11:01:04 -0600160
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500161 configFile = open(tmp_conf, 'w')
162 configFile.write(self.__getConfig())
ashuef3490b2015-02-17 11:01:04 -0600163 configFile.close()
164
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500165 # If this node is a remote node scp the nlsr.conf file to its /tmp/nlsr.conf
166 if isinstance(self.node, RemoteMixin) and self.node.isRemote:
167 login = "mininet@%s" % self.node.server
168 src = tmp_conf
169 dst = "%s:%s" % (login, tmp_conf)
170 scp(src, dst)
ashuef3490b2015-02-17 11:01:04 -0600171
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500172 # Copy nlsr.conf to home folder
173 self.node.cmd("mv %s nlsr.conf" % tmp_conf)
ashuef3490b2015-02-17 11:01:04 -0600174
175 def __getConfig(self):
176
Ashlesh Gawandef5f304b2016-06-16 16:42:41 -0500177 config = self.__getGeneralSection() + "\n"
178 config += self.__getNeighborsSection() + "\n"
179 config += self.__getHyperbolicSection() + "\n"
180 config += self.__getFibSection() + "\n"
181 config += self.__getAdvertisingSection() + "\n"
ashuef3490b2015-02-17 11:01:04 -0600182 config += self.__getSecuritySection()
183
184 return config
185
186 def __getGeneralSection(self):
187
188 general = "general\n"
189 general += "{\n"
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -0600190 general += " network {}\n".format(NETWORK)
Ashlesh Gawandee144ceb2016-11-14 13:56:24 -0600191 general += " site /{}-site\n".format(self.node.name)
ashuef3490b2015-02-17 11:01:04 -0600192 general += " router /%C1.Router/cs/" + self.node.name + "\n"
Ashlesh Gawandec3ed2b92015-07-01 12:58:08 -0500193 general += " log-level " + self.logLevel + "\n"
Ashlesh Gawande1b663692015-10-14 16:38:10 -0500194 general += " log-dir " + self.node.homeFolder + "/log\n"
195 general += " seq-dir " + self.node.homeFolder + "/log\n"
ashuef3490b2015-02-17 11:01:04 -0600196 general += "}\n"
197
198 return general
199
200 def __getNeighborsSection(self):
201
202 neighbors = "neighbors\n"
203 neighbors += "{\n"
204
205 for intf in self.node.intfList():
206 link = intf.link
207 if link:
208 node1, node2 = link.intf1.node, link.intf2.node
209
210 if node1 == self.node:
211 other = node2
212 ip = other.IP(str(link.intf2))
213 else:
214 other = node1
215 ip = other.IP(str(link.intf1))
216
ashu7b6ba182015-04-17 15:02:37 -0500217 linkCost = intf.params.get("delay", "10ms").replace("ms", "")
ashuef3490b2015-02-17 11:01:04 -0600218
Ashlesh Gawande708fcca2017-06-23 14:04:12 -0500219 # To be used later to create faces
220 self.neighborIPs.append(ip)
221
ashuef3490b2015-02-17 11:01:04 -0600222 neighbors += "neighbor\n"
223 neighbors += "{\n"
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -0600224 neighbors += " name " + NETWORK + other.name + "-site/%C1.Router/cs/" + other.name + "\n"
Ashlesh Gawande708fcca2017-06-23 14:04:12 -0500225 neighbors += " face-uri {}://{}\n".format(self.faceType, ip)
ashuef3490b2015-02-17 11:01:04 -0600226 neighbors += " link-cost " + linkCost + "\n"
227 neighbors += "}\n"
228
229 neighbors += "}\n"
230
231 return neighbors
232
233 def __getHyperbolicSection(self):
234
235 hyper = "hyperbolic\n"
236 hyper += "{\n"
237 hyper += "state %s\n" % self.hyperbolicState
238 hyper += "radius " + str(self.hyperRadius) + "\n"
239 hyper += "angle " + str(self.hyperAngle) + "\n"
240 hyper += "}\n"
241
242 return hyper
243
244 def __getFibSection(self):
245
246 fib = "fib\n"
247 fib += "{\n"
248 fib += " max-faces-per-prefix " + str(self.nFaces) + "\n"
249 fib += "}\n"
250
251 return fib
252
253 def __getAdvertisingSection(self):
254
255 advertising = "advertising\n"
256 advertising += "{\n"
Ashlesh Gawandef6a610b2017-02-21 14:48:08 -0600257 advertising += " prefix "+ NETWORK + self.node.name + "-site/" + self.node.name + "\n"
ashuef3490b2015-02-17 11:01:04 -0600258 advertising += "}\n"
259
260 return advertising
261
262 def __getSecuritySection(self):
Vince Lehman5d5a5662015-12-02 12:33:12 -0600263 if self.isSecurityEnabled is False:
264 security = textwrap.dedent("""\
265 security
266 {
267 validator
268 {
269 trust-anchor
270 {
271 type any
272 }
273 }
274 prefix-update-validator
275 {
276 trust-anchor
277 {
278 type any
279 }
280 }
281 }""")
282 else:
283 security = textwrap.dedent("""\
284 security
285 {
286 validator
287 {
288 rule
289 {
290 id "NSLR Hello Rule"
291 for data
292 filter
293 {
294 type name
295 regex ^[^<NLSR><INFO>]*<NLSR><INFO><><>$
296 }
297 checker
298 {
299 type customized
300 sig-type rsa-sha256
301 key-locator
302 {
303 type name
304 hyper-relation
305 {
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500306 k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600307 k-expand \\\\1
308 h-relation equal
309 p-regex ^([^<NLSR><INFO>]*)<NLSR><INFO><><>$
310 p-expand \\\\1
311 }
312 }
313 }
314 }
ashuef3490b2015-02-17 11:01:04 -0600315
Vince Lehman5d5a5662015-12-02 12:33:12 -0600316 rule
317 {
318 id "NSLR LSA Rule"
319 for data
320 filter
321 {
322 type name
323 regex ^[^<NLSR><LSA>]*<NLSR><LSA>
324 }
325 checker
326 {
327 type customized
328 sig-type rsa-sha256
329 key-locator
330 {
331 type name
332 hyper-relation
333 {
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500334 k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600335 k-expand \\\\1
336 h-relation equal
Ashlesh Gawande3bed4832017-02-08 18:17:31 -0600337 p-regex ^<localhop>([^<NLSR><LSA>]*)<NLSR><LSA>(<>*)<><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600338 p-expand \\\\1\\\\2
339 }
340 }
341 }
342 }
343
344 rule
345 {
346 id "NSLR Hierarchy Exception Rule"
347 for data
348 filter
349 {
350 type name
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500351 regex ^[^<KEY><%C1.Router>]*<%C1.Router>[^<KEY><NLSR>]*<KEY><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600352 }
353 checker
354 {
355 type customized
356 sig-type rsa-sha256
357 key-locator
358 {
359 type name
360 hyper-relation
361 {
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500362 k-regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600363 k-expand \\\\1
364 h-relation equal
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500365 p-regex ^([^<KEY><%C1.Router>]*)<%C1.Router>[^<KEY>]*<KEY><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600366 p-expand \\\\1
367 }
368 }
369 }
370 }
371
372 rule
373 {
374 id "NSLR Hierarchical Rule"
375 for data
376 filter
377 {
378 type name
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500379 regex ^[^<KEY>]*<KEY><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600380 }
381 checker
382 {
383 type hierarchical
384 sig-type rsa-sha256
385 }
386 }
387
388 trust-anchor
389 {
390 type file
391 file-name "security/root.cert"
392 }
393 }
394
395 prefix-update-validator
396 {
397 rule
398 {
399 id "NLSR ControlCommand Rule"
400 for interest
401 filter
402 {
403 type name
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500404 regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600405 }
406 checker
407 {
408 type customized
409 sig-type rsa-sha256
410 key-locator
411 {
412 type name
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500413 regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600414 }
415 }
416 }
417
418 rule
419 {
420 id "NLSR Hierarchy Rule"
421 for data
422 filter
423 {
424 type name
Ashlesh Gawandea80484e2017-10-17 15:52:23 -0500425 regex ^[^<KEY>]*<KEY><><><>$
Vince Lehman5d5a5662015-12-02 12:33:12 -0600426 }
427 checker
428 {
429 type hierarchical
430 sig-type rsa-sha256
431 }
432 }
433
434 trust-anchor
435 {
436 type file
437 file-name "security/site.cert"
438 }
439 }
440 ; cert-to-publish "security/root.cert" ; optional, a file containing the root certificate
441 ; Only the router that is designated to publish the root cert
442 ; needs to specify this
443
444 cert-to-publish "security/site.cert" ; optional, a file containing the site certificate
445 ; Only the router that is designated to publish the site cert
446 ; needs to specify this
447
448 cert-to-publish "security/op.cert" ; optional, a file containing the operator certificate
449 ; Only the router that is designated to publish the operator
450 ; cert needs to specify this
451
452 cert-to-publish "security/router.cert" ; required, a file containing the router certificate.
453 }""")
ashuef3490b2015-02-17 11:01:04 -0600454
455 return security