mirror of
https://git.dn42.dev/dn42/registry.git
synced 2025-07-19 00:46:59 +08:00
Merge branch 'master' of git.dn42.us:Carlotronics/registry
This commit is contained in:
commit
6c38e897c5
36 changed files with 821 additions and 652 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -2,6 +2,8 @@ _MTN
|
|||
lib/
|
||||
whoisd/
|
||||
__pycache__
|
||||
.index
|
||||
.links
|
||||
.nettree
|
||||
|
||||
/data/.rpsl/index
|
||||
/data/.rpsl/links
|
||||
/data/.rpsl/nettree
|
||||
/data/.rpsl/schema
|
13
data/.rpsl
13
data/.rpsl
|
@ -1,13 +0,0 @@
|
|||
namespace: dn42
|
||||
schema: schema
|
||||
owner: mntner
|
||||
default-owner: DN42-MNT
|
||||
network-owner: inet6num inet6num
|
||||
network-owner: inet6num route
|
||||
network-owner: inet6num inetnum
|
||||
network-owner: inetnum inetnum
|
||||
network-owner: inetnum route
|
||||
primary-key: inetnum cidr
|
||||
primary-key: inet6num cidr
|
||||
primary-key: person nic-hdl
|
||||
primary-key: role nic-hdl
|
16
data/.rpsl/config
Normal file
16
data/.rpsl/config
Normal file
|
@ -0,0 +1,16 @@
|
|||
namespace: dn42
|
||||
schema: schema
|
||||
owners: mntner
|
||||
default-owner: DN42-MNT
|
||||
primary-key: person nic-hdl
|
||||
primary-key: role nic-hdl
|
||||
primary-key: inetnum cidr
|
||||
primary-key: inet6num cidr
|
||||
network-owner: inet6num inet6num
|
||||
network-owner: inet6num inetnum
|
||||
network-owner: inetnum inetnum
|
||||
network-owner: inetnum route
|
||||
network-owner: inet6num route6
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
|
|
@ -23,6 +23,10 @@ remarks: GATUNO-MNT
|
|||
members: AS4242420180
|
||||
remarks: MARROPAX-MNT
|
||||
members: AS4242420880
|
||||
remarks: OWENSRESEARCH-MNT
|
||||
members: AS4242421099
|
||||
remarks: ANDROW-MNT
|
||||
members: AS4242422575
|
||||
admin-c: NAPSTERBATER-DN42
|
||||
tech-c: NAPSTERBATER-DN42
|
||||
mnt-by: NAPSTERBATER-MNT
|
||||
|
|
9
data/aut-num/AS134098
Normal file
9
data/aut-num/AS134098
Normal file
|
@ -0,0 +1,9 @@
|
|||
aut-num: AS134098
|
||||
as-name: SYLVEON-AS-AP
|
||||
admin-c: LICSON-NEONETWORK
|
||||
tech-c: LICSON-NEONETWORK
|
||||
descr: Licson Internet Service
|
||||
remarks: Sylveon Network (Hong Kong) Limited.
|
||||
remarks: This was created to fix missing object from neonetwork.
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
|
@ -1,7 +0,0 @@
|
|||
aut-num: AS4242420674
|
||||
as-name: Vulkan ASN
|
||||
descr: Vulkan Network ASN
|
||||
admin-c: VULKAN-DN42
|
||||
tech-c: VULKAN-DN42
|
||||
mnt-by: VULKAN-MNT
|
||||
source: DN42
|
|
@ -1,9 +0,0 @@
|
|||
inet6num: fd86:bc21:638a:0000:0000:0000:0000:0000 - fd86:bc21:638a:ffff:ffff:ffff:ffff:ffff
|
||||
cidr: fd86:bc21:638a::/48
|
||||
netname: VULKAN-NETWORK
|
||||
country: MX
|
||||
admin-c: VULKAN-DN42
|
||||
tech-c: VULKAN-DN42
|
||||
mnt-by: VULKAN-MNT
|
||||
status: ASSIGNED
|
||||
source: DN42
|
|
@ -1,9 +0,0 @@
|
|||
inetnum: 172.22.122.32 - 172.22.122.63
|
||||
netname: VULKAN-NETWORK
|
||||
country: MX
|
||||
admin-c: VULKAN-DN42
|
||||
tech-c: VULKAN-DN42
|
||||
mnt-by: VULKAN-MNT
|
||||
status: ASSIGNED
|
||||
cidr: 172.22.122.32/27
|
||||
source: DN42
|
9
data/inetnum/172.22.169.64_26
Normal file
9
data/inetnum/172.22.169.64_26
Normal file
|
@ -0,0 +1,9 @@
|
|||
inetnum: 172.22.169.64 - 172.22.169.127
|
||||
cidr: 172.22.169.64/26
|
||||
netname: ZOTAN-NETWORK
|
||||
admin-c: ZOTAN-DN42
|
||||
tech-c: ZOTAN-DN42
|
||||
mnt-by: ZOTAN-MNT
|
||||
status: ASSIGNED
|
||||
nserver: ns1.zotan.dn42
|
||||
source: DN42
|
|
@ -1,6 +0,0 @@
|
|||
mntner: VULKAN-MNT
|
||||
descr: Vulkan Student
|
||||
admin-c: VULKAN-DN42
|
||||
tech-c: VULKAN-DN42
|
||||
mnt-by: VULKAN-MNT
|
||||
source: DN42
|
|
@ -1,5 +1,6 @@
|
|||
person: Alexey
|
||||
contact: ne-vlezay80@yandex.ru
|
||||
contact: mailto:ne-vlezay80@yandex.ru
|
||||
contact: matrix:@ne-vlezay80:matrix.org
|
||||
nic-hdl: NEVLEZAY-DN42
|
||||
mnt-by: NEVLEZAY-MNT
|
||||
source: DN42
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
person: Vulkan Admin
|
||||
contact: email:grande_josh@odontologos.com
|
||||
address: Somewhere over the Rainbow
|
||||
nic-hdl: VULKAN-DN42
|
||||
mnt-by: VULKAN-MNT
|
||||
source: DN42
|
|
@ -1,4 +0,0 @@
|
|||
route: 172.22.122.32/27
|
||||
origin: AS4242420674
|
||||
mnt-by: VULKAN-MNT
|
||||
source: DN42
|
4
data/route/172.22.169.64_26
Normal file
4
data/route/172.22.169.64_26
Normal file
|
@ -0,0 +1,4 @@
|
|||
route: 172.22.169.64/26
|
||||
origin: AS4242422341
|
||||
mnt-by: ZOTAN-MNT
|
||||
source: DN42
|
|
@ -1,4 +0,0 @@
|
|||
route6: fd86:bc21:638a::/48
|
||||
origin: AS4242420674
|
||||
mnt-by: VULKAN-MNT
|
||||
source: DN42
|
|
@ -19,7 +19,5 @@ key: org optional single lookup=dn42.organisation
|
|||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
network-owner: inet6num
|
||||
network-owner: inetnum
|
||||
network-owner: route6
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
|
|
|
@ -18,7 +18,7 @@ key: mnt-routes optional multiple lookup=dn42.mntner
|
|||
key: org optional single lookup=dn42.organisation
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
network-owner: inet6num
|
||||
network-owner: inetnum
|
||||
network-owner: route
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
|
|
|
@ -11,5 +11,6 @@ key: remarks optional multiple
|
|||
key: source required single lookup=dn42.registry
|
||||
key: pingable optional multiple
|
||||
key: max-length optional single
|
||||
network-owner: inetnum
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
|
|
|
@ -11,5 +11,6 @@ key: remarks optional multiple
|
|||
key: source required single lookup=dn42.registry
|
||||
key: pingable optional multiple
|
||||
key: max-length optional single
|
||||
network-owner: inet6num
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
|
|
|
@ -9,7 +9,7 @@ key: key required multiple > [key-name]
|
|||
key: mnt-by required multiple lookup=dn42.mntner > [mntner]
|
||||
key: remarks optional multiple > [text]...
|
||||
key: source required single lookup=dn42.registry
|
||||
key: network-owner optional multiple > [child-schema]
|
||||
key: network-owner optional multiple > [parent-schema]
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
remarks: # option descriptions
|
||||
|
|
|
@ -1,363 +0,0 @@
|
|||
.BEGIN DN42-MNT
|
||||
schema: AUT-NUM-SCHEMA
|
||||
ref: dn42.aut-num
|
||||
key: aut-num required single primary schema
|
||||
key: as-name required single
|
||||
key: descr optional single
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: member-of optional multiple lookup=dn42.as-set,dn42.route-set
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: org optional single lookup=dn42.organisation
|
||||
key: import deprecate multiple
|
||||
key: export deprecate multiple
|
||||
key: default deprecate multiple
|
||||
key: mp-peer deprecate multiple
|
||||
key: mp-group deprecate multiple
|
||||
key: mp-import optional multiple
|
||||
key: mp-export optional multiple
|
||||
key: mp-default optional multiple
|
||||
key: geo-loc optional multiple > [lat-c] [long-c] [name]
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: AS-SET-SCHEMA
|
||||
ref: dn42.as-set
|
||||
key: as-set required single primary schema
|
||||
key: descr optional single
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: members optional multiple lookup=dn42.aut-num,dn42.as-set
|
||||
key: mbrs-by-ref optional multiple lookup=dn42.mntner
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: ROUTE6-SCHEMA
|
||||
ref: dn42.route6
|
||||
key: route6 required single primary schema
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: origin required multiple lookup=dn42.aut-num
|
||||
key: member-of optional multiple lookup=dn42.route-set
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: descr optional multiple
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
key: pingable optional multiple
|
||||
key: max-length optional single
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: TINC-KEYSET-SCHEMA
|
||||
ref: dn42.tinc-keyset
|
||||
key: tinc-keyset required single primary schema
|
||||
key: descr optional single
|
||||
key: remarks optional multiple
|
||||
key: member required multiple lookup=dn42.tinc-key
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: ROLE-SCHEMA
|
||||
ref: dn42.role
|
||||
key: role required single schema
|
||||
key: nic-hdl required single primary
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: org optional multiple lookup=dn42.organisation
|
||||
key: admin-c optional multiple lookup=dn42.person
|
||||
key: tech-c optional multiple lookup=dn42.person
|
||||
key: abuse-c optional multiple lookup=dn42.person
|
||||
key: abuse-mailbox optional multiple
|
||||
key: descr optional single
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: INET6NUM-SCHEMA
|
||||
ref: dn42.inet6num
|
||||
key: inet6num required single schema
|
||||
key: cidr required single primary
|
||||
key: netname required single
|
||||
key: nserver optional multiple > [domain-name]
|
||||
key: country optional multiple
|
||||
key: descr optional single
|
||||
key: status optional single > {ALLOCATED|ASSIGNED} {PI|PA|}
|
||||
key: policy optional single > {open|closed|ask|reserved}
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: zone-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: ds-rdata optional multiple
|
||||
key: mnt-by optional multiple lookup=dn42.mntner
|
||||
key: mnt-lower optional multiple lookup=dn42.mntner
|
||||
key: mnt-routes optional multiple lookup=dn42.mntner
|
||||
key: org optional single lookup=dn42.organisation
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
network-owner: inet6num
|
||||
network-owner: inetnum
|
||||
network-owner: route6
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: MNTNER-SCHEMA
|
||||
ref: dn42.mntner
|
||||
key: mntner required single primary schema
|
||||
key: descr optional single
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: auth optional multiple > [method] [value]...
|
||||
key: org optional multiple lookup=dn42.organisation
|
||||
key: abuse-mailbox optional single
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: ORGANISATION-SCHEMA
|
||||
ref: dn42.organisation
|
||||
key: organisation required single primary schema
|
||||
key: org-name required single
|
||||
key: descr optional single
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: abuse-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: mnt-ref optional multiple lookup=dn42.mntner
|
||||
key: phone optional multiple
|
||||
key: fax-no optional multiple
|
||||
key: www optional multiple
|
||||
key: abuse-mailbox optional multiple
|
||||
key: e-mail optional multiple
|
||||
key: geoloc optional multiple
|
||||
key: language optional multiple
|
||||
key: remarks optional multiple
|
||||
key: address optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: TINC-KEY-SCHEMA
|
||||
ref: dn42.tinc-key
|
||||
key: tinc-key required single primary schema
|
||||
key: tinc-host required single
|
||||
key: tinc-file required single
|
||||
key: descr optional single
|
||||
key: remarks optional multiple
|
||||
key: compression optional single
|
||||
key: subnet optional multiple
|
||||
key: tinc-address optional single
|
||||
key: port optional single
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: AS-BLOCK-SCHEMA
|
||||
ref: dn42.as-block
|
||||
key: as-block required single primary schema
|
||||
key: descr optional single
|
||||
key: policy required single > {open|ask|closed}
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: SCHEMA-SCHEMA
|
||||
ref: dn42.schema
|
||||
key: schema required single primary schema > [name]
|
||||
key: ref required single > [schema]
|
||||
key: key required multiple > [key-name]
|
||||
{required|optional|recommend|deprecate}
|
||||
{single|multiple} {primary|} {schema|}
|
||||
lookup=str '>' [spec]...
|
||||
key: mnt-by required multiple lookup=dn42.mntner > [mntner]
|
||||
key: remarks optional multiple > [text]...
|
||||
key: source required single lookup=dn42.registry
|
||||
key: network-owner optional multiple > [child-schema]
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
remarks: # option descriptions
|
||||
Attribute names must match /[a-zA-Z]([a-zA-Z0-9_\-]*[a-zA-Z0-9])?/.
|
||||
+
|
||||
required
|
||||
: object required to have at least one
|
||||
optional
|
||||
: object not required to have at least one
|
||||
+
|
||||
single
|
||||
: only one of this type allowed
|
||||
multiple
|
||||
: more than one of this type allowed
|
||||
+
|
||||
primary
|
||||
: use field as lookup key for lookup
|
||||
* only one allowed per schema
|
||||
* does not allow newlines
|
||||
+
|
||||
schema
|
||||
: use field name as the name of the schema
|
||||
* only one allowed per schema
|
||||
* does not allow newlines
|
||||
+
|
||||
lookup
|
||||
: schema match to use for related record
|
||||
+
|
||||
\> option specs
|
||||
: defines the option specifications for the key.
|
||||
* must come last in option list
|
||||
+
|
||||
[label] string value. A positional string argument required.
|
||||
Text inside brackets represent a label for the string and must match the same rules as attribute names.
|
||||
If follwed by '...' values are gathered as an array.
|
||||
+
|
||||
{enum1|enum2|} enumeration. One option in pipe('|') deliniation is allowed.
|
||||
If there is a trailing pipe it means the enum is optional. Enum values must match the same rules as attribute names.
|
||||
+
|
||||
'literal' Literal value. literal text value which must not contain any whitespace or single quotes.
|
||||
...
|
||||
schema: ROUTE-SET-SCHEMA
|
||||
ref: dn42.route-set
|
||||
key: route-set required single primary schema
|
||||
key: descr optional single
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: members deprecate multiple
|
||||
key: mp-members optional multiple
|
||||
key: mbrs-by-ref optional multiple lookup=dn42.mntner
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: REGISTRY-SCHEMA
|
||||
ref: dn42.registry
|
||||
key: registry required single primary schema
|
||||
key: url required multiple
|
||||
key: descr optional multiple
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: KEY-CERT-SCHEMA
|
||||
ref: dn42.key-cert
|
||||
key: key-cert required single primary schema
|
||||
key: method required single > {PGP|X509|MTN}
|
||||
key: owner required multiple
|
||||
key: fingerpr required single
|
||||
key: certif required multiple
|
||||
key: org optional multiple lookup=dn42.organisation
|
||||
key: remarks optional multiple
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: source required single
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: ROUTE-SCHEMA
|
||||
ref: dn42.route
|
||||
key: route required single primary schema
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: origin required multiple lookup=dn42.aut-num
|
||||
key: member-of optional multiple lookup=dn42.route-set
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: descr optional single
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
key: pingable optional multiple
|
||||
key: max-length optional single
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: PERSON-SCHEMA
|
||||
ref: dn42.person
|
||||
key: person required single schema
|
||||
key: nic-hdl required single primary
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: org optional multiple lookup=dn42.organisation
|
||||
key: nick optional multiple
|
||||
key: pgp-fingerprint optional multiple
|
||||
key: www optional multiple
|
||||
key: e-mail optional multiple
|
||||
key: contact optional multiple
|
||||
key: abuse-mailbox optional multiple
|
||||
key: phone optional multiple
|
||||
key: fax-no optional multiple
|
||||
key: address optional multiple
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: INETNUM-SCHEMA
|
||||
ref: dn42.inetnum
|
||||
key: inetnum required single schema
|
||||
key: cidr required single primary
|
||||
key: netname required single
|
||||
key: nserver optional multiple > [domain-name]
|
||||
key: country optional multiple
|
||||
key: descr optional single
|
||||
key: status optional single > {ALLOCATED|ASSIGNED} {PI|PA|}
|
||||
key: policy optional single > {open|closed|ask|reserved}
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: zone-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: ds-rdata optional multiple
|
||||
key: mnt-by optional multiple lookup=dn42.mntner
|
||||
key: mnt-lower optional multiple lookup=dn42.mntner
|
||||
key: mnt-routes optional multiple lookup=dn42.mntner
|
||||
key: org optional single lookup=dn42.organisation
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
network-owner: inetnum
|
||||
network-owner: route
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: NAMESPACE-SCHEMA
|
||||
ref: dn42.namespace
|
||||
key: namespace required single primary schema > [name]
|
||||
key: ns-schema required single > [schema]
|
||||
key: ns-owner required single > [schema]
|
||||
key: default-owner optional single lookup=dn42.mntner > [mntner]
|
||||
key: network-owner optional multiple > [parent-schema] [child-schema]
|
||||
key: primary-key optional multiple > [schema] [primary]
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
...
|
||||
schema: DNS-SCHEMA
|
||||
ref: dn42.domain
|
||||
key: domain required single primary schema
|
||||
key: nserver required multiple > [domain-name] [ip-addr]
|
||||
key: descr optional single
|
||||
key: mnt-by required multiple lookup=dn42.mntner
|
||||
key: admin-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: tech-c optional multiple lookup=dn42.person,dn42.role
|
||||
key: org optional multiple lookup=dn42.organisation
|
||||
key: country optional single
|
||||
key: ds-rdata optional multiple
|
||||
key: remarks optional multiple
|
||||
key: source required single lookup=dn42.registry
|
||||
mnt-by: DN42-MNT
|
||||
source: DN42
|
||||
.END
|
|
@ -1,118 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Builds registry index to be used by scan-index.py"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from typing import Dict, Generator, List
|
||||
|
||||
from dom.filedom import FileDOM, read_file
|
||||
from dom.schema import SchemaDOM
|
||||
from dom.nettree import NetTree, NetRecord
|
||||
from dom.transact import TransactDOM
|
||||
|
||||
def index_files(path: str) -> Generator[FileDOM, None, None]:
|
||||
"""generate list of dom files"""
|
||||
for root, _, files in os.walk(path):
|
||||
if root == path:
|
||||
continue
|
||||
|
||||
for f in files:
|
||||
if f[0] == ".":
|
||||
continue
|
||||
|
||||
dom = read_file(os.path.join(root, f))
|
||||
yield dom
|
||||
|
||||
|
||||
def run(path: str = "."):
|
||||
"""run main script"""
|
||||
if not os.path.isdir(os.path.join(path, "schema")):
|
||||
print("schema directory not found in path", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
idx = index_files(path)
|
||||
|
||||
lookup = {} # type: Dict[str, FileDOM]
|
||||
schemas = {} # type: Dict[str, SchemaDOM]
|
||||
files = []
|
||||
nets = [] # type: List[NetRecord]
|
||||
|
||||
print(r"Reading Files...", end="\r", flush=True, file=sys.stderr)
|
||||
|
||||
for (i, dom) in enumerate(idx):
|
||||
if not dom.valid:
|
||||
print("E", end="", flush=True)
|
||||
continue
|
||||
|
||||
key, value = dom.index
|
||||
lookup[key] = value
|
||||
files.append(dom)
|
||||
|
||||
if dom.schema == "schema":
|
||||
schema = SchemaDOM()
|
||||
schema.parse(dom)
|
||||
|
||||
schemas[schema.ref] = schema
|
||||
|
||||
if dom.schema in ["inetnum", "inet6num"]:
|
||||
nets.append(NetRecord(
|
||||
dom.get("cidr").as_net6,
|
||||
dom.mntner,
|
||||
dom.get("policy", default="closed"),
|
||||
dom.get("status", default="ASSIGNED"),
|
||||
))
|
||||
|
||||
if i % 120 == 0:
|
||||
print(
|
||||
f"Reading Files: files: {len(files)} schemas: {len(schemas)}",
|
||||
end="\r", flush=True, file=sys.stderr)
|
||||
|
||||
print(
|
||||
f"Reading Files: done! files: {len(files)}, schemas: {len(schemas)}",
|
||||
file=sys.stderr)
|
||||
|
||||
print("Writing .index", file=sys.stderr)
|
||||
print("Writing .links", file=sys.stderr)
|
||||
with open(".index", 'w') as out:
|
||||
with open(".links", 'w') as link_out:
|
||||
for dom in files:
|
||||
s = schemas.get(dom.rel)
|
||||
if s is None:
|
||||
print(
|
||||
f"{dom.src} schema not found for {dom.rel}",
|
||||
file=sys.stderr)
|
||||
|
||||
print(dom.rel,
|
||||
dom.get(s.primary),
|
||||
dom.src,
|
||||
",".join(dom.mntner),
|
||||
sep="|",
|
||||
file=out)
|
||||
|
||||
for (link, refs) in s.links.items():
|
||||
d = dom.get(link)
|
||||
refs_join = ','.join(refs)
|
||||
if d is not None:
|
||||
print(
|
||||
f"{dom.rel}|{dom.name}|{link}|{d}|{refs_join}",
|
||||
file=link_out)
|
||||
|
||||
print("Generate .nettree", file=sys.stderr)
|
||||
tree = NetTree(nets)
|
||||
|
||||
print("Writing .nettree", file=sys.stderr)
|
||||
tree.write_csv(".nettree")
|
||||
|
||||
print("Writing .schema", file=sys.stderr)
|
||||
s = TransactDOM()
|
||||
s.mntner = "DN42-MNT"
|
||||
s.files = schemas.values()
|
||||
with open(".schema", "w") as out:
|
||||
print(s, file=out)
|
||||
|
||||
print("done.", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(sys.argv[1] if len(sys.argv) > 1 else os.getcwd())
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from typing import Sequence, NamedTuple, List, Dict, Optional, Tuple, Union
|
||||
from typing import Sequence, NamedTuple, List, \
|
||||
Dict, Optional, Tuple, Union, Generator, TypeVar
|
||||
from ipaddress import ip_network, IPv4Network, IPv6Network
|
||||
|
||||
import log
|
||||
|
||||
F = TypeVar("F", bound="FileDOM")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Value:
|
||||
|
@ -143,6 +146,8 @@ class FileDOM:
|
|||
self.keys = keys
|
||||
self.multi = multi
|
||||
self.mntner = mntner
|
||||
if self.src is None:
|
||||
self.src = f"{self.schema}/{self.name}"
|
||||
self.valid = True
|
||||
|
||||
@property
|
||||
|
@ -210,6 +215,13 @@ class FileDOM:
|
|||
|
||||
return self.dom[self.keys[key][index]].value
|
||||
|
||||
def get_all(self, key) -> Generator[str, None, None]:
|
||||
"Get all values for a key"
|
||||
if key not in self.keys:
|
||||
return
|
||||
for i in self.keys[key]:
|
||||
yield self.dom[i].value
|
||||
|
||||
def put(self, key, value, index=0, append=False):
|
||||
"""Put a value"""
|
||||
if key not in self.keys:
|
||||
|
@ -225,8 +237,8 @@ class FileDOM:
|
|||
if index not in self.keys[key]:
|
||||
self.keys[key].append(i)
|
||||
|
||||
|
||||
def read_file(fn: str) -> FileDOM:
|
||||
@staticmethod
|
||||
def from_file(fn: str) -> F:
|
||||
"""Parses FileDOM from file"""
|
||||
with open(fn, mode='r', encoding='utf-8') as f:
|
||||
dom = FileDOM(src=fn, text=f.readlines())
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from ipaddress import ip_network, IPv6Network
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Tuple, Optional
|
||||
from typing import Dict, List, Tuple, Optional, Generator
|
||||
|
||||
NET = IPv6Network
|
||||
V6_NET = ip_network("::/0")
|
||||
|
@ -113,24 +113,25 @@ class NetTree:
|
|||
def write_csv(self, fn: str = ".netindex"):
|
||||
"write tree to csv"
|
||||
with open(fn, "w") as f:
|
||||
f.writelines({line+"\n" for line in self._lines()})
|
||||
f.writelines(self._lines())
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "\n".join(self._lines())
|
||||
return "".join(self._lines())
|
||||
|
||||
def _lines(self) -> List[str]:
|
||||
for v in self.tree.values():
|
||||
def _lines(self) -> Generator[str, None, None]:
|
||||
for v in sorted(
|
||||
sorted(self.tree.values(), key=lambda x: x.index),
|
||||
key=lambda x: x.level):
|
||||
|
||||
net_addr = v.net.network.network_address.exploded
|
||||
net_pfx = v.net.network.prefixlen
|
||||
yield (
|
||||
"|".join([str(i) for i in (
|
||||
v.index,
|
||||
v.parent,
|
||||
v.level,
|
||||
v.net.network.network_address.exploded,
|
||||
v.net.network.prefixlen,
|
||||
v.net.object_type,
|
||||
v.net.object_name,
|
||||
f"{v.index:04d}|{v.parent:04d}|{v.level:04d}",
|
||||
net_addr,
|
||||
net_pfx,
|
||||
v.net.policy,
|
||||
v.net.status,
|
||||
",".join(v.net.mnters),
|
||||
)])
|
||||
)
|
||||
v.net.object_type,
|
||||
v.net.object_name,
|
||||
)]) + "\n")
|
||||
|
|
119
utils/registry/dom/rspl.py
Normal file
119
utils/registry/dom/rspl.py
Normal file
|
@ -0,0 +1,119 @@
|
|||
"RPSL"
|
||||
|
||||
import os
|
||||
import os.path
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List, Set, Tuple, TypeVar
|
||||
|
||||
from .filedom import FileDOM
|
||||
from .nettree import NetTree
|
||||
from .schema import SchemaDOM
|
||||
|
||||
|
||||
C = TypeVar('C', bound='RPSLConfig')
|
||||
|
||||
|
||||
@dataclass
|
||||
class RPSLConfig:
|
||||
"RSPLConfig"
|
||||
namespace: str
|
||||
root: str
|
||||
schema: str
|
||||
owners: str
|
||||
default_owner: str
|
||||
source: str
|
||||
network_owner: Set[Tuple[str, str]] = field(default_factory=set)
|
||||
primary_key: Set[Tuple[str, str]] = field(default_factory=set)
|
||||
|
||||
@property
|
||||
def network_parents(self) -> Set[str]:
|
||||
"return network parents"
|
||||
return set(self.network_owner.values())
|
||||
|
||||
@property
|
||||
def schema_dir(self) -> str:
|
||||
"get schema directory"
|
||||
return os.path.join(self.root, self.schema)
|
||||
|
||||
@property
|
||||
def owner_dir(self) -> str:
|
||||
"get owner directory"
|
||||
return os.path.join(self.root, self.owners)
|
||||
|
||||
@property
|
||||
def config_file(self) -> str:
|
||||
"get config file"
|
||||
return os.path.join(self.root, ".rpsl/config")
|
||||
|
||||
@staticmethod
|
||||
def default() -> C:
|
||||
"create default"
|
||||
root = os.getcwd()
|
||||
return RPSLConfig("dn42", root, "schema", "mntner", "DN42-MNT", "DN42",
|
||||
{}, {})
|
||||
|
||||
@staticmethod
|
||||
def from_dom(dom: FileDOM) -> C:
|
||||
"create from dom"
|
||||
ns = dom.get("namespace", default="dn42").value
|
||||
schema = dom.get("schema", default="schema").value
|
||||
owners = dom.get("owners", default="mntner").value
|
||||
source = dom.get("source", default="DN42").value
|
||||
default_owner = dom.get("default-owner", default=dom.mntner).value
|
||||
|
||||
root = os.path.dirname(dom.src)
|
||||
|
||||
network_owner = {} # type: Dict[str, str]
|
||||
for (parent, child) in [
|
||||
i.fields for i in dom.get_all("network-owner")]:
|
||||
network_owner[child] = parent
|
||||
|
||||
primary_key = {} # type: Dict[str, str]
|
||||
for (parent, child) in [
|
||||
i.fields for i in dom.get_all("primary-key")]:
|
||||
primary_key[child] = parent
|
||||
|
||||
return RPSLConfig(namespace=ns,
|
||||
root=root,
|
||||
schema=schema,
|
||||
owners=owners,
|
||||
source=source,
|
||||
default_owner=default_owner,
|
||||
network_owner=network_owner,
|
||||
primary_key=primary_key,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
dom = FileDOM(ns=self.namespace)
|
||||
dom.put("namespace", self.namespace)
|
||||
dom.put("schema", self.schema)
|
||||
dom.put("owners", self.owners)
|
||||
dom.put("default-owner", self.default_owner)
|
||||
for (k, v) in self.primary_key:
|
||||
dom.put("primary-key", f"{k} {v}", append=True)
|
||||
for (k, v) in self.network_owner:
|
||||
dom.put("network-owner", f"{v} {k}", append=True)
|
||||
dom.put("mnt-by", self.default_owner)
|
||||
dom.put("source", self.source)
|
||||
|
||||
return dom.__str__()
|
||||
|
||||
|
||||
R = TypeVar('R', bound="RPSL")
|
||||
|
||||
|
||||
@dataclass
|
||||
class RSPL:
|
||||
"RSPL"
|
||||
config: RPSLConfig
|
||||
files: List[FileDOM]
|
||||
nettree: NetTree
|
||||
schema: Dict[str, SchemaDOM]
|
||||
|
||||
@staticmethod
|
||||
def from_index(path: str) -> R:
|
||||
"Create RSPL from indexs"
|
||||
|
||||
@staticmethod
|
||||
def from_files(path: str, schema_only: bool = False) -> R:
|
||||
"Create RSPL from files"
|
|
@ -2,12 +2,14 @@
|
|||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum, auto
|
||||
from typing import Optional, List, Tuple, Dict, Set
|
||||
from typing import Optional, List, Tuple, Dict, Set, TypeVar
|
||||
|
||||
import log
|
||||
|
||||
from .filedom import FileDOM, Row
|
||||
|
||||
DOM = TypeVar("DOM", bound="FileDOM")
|
||||
|
||||
|
||||
class Level(Enum):
|
||||
"""State error level"""
|
||||
|
@ -59,7 +61,7 @@ class State:
|
|||
class SchemaDOM:
|
||||
"""Schema DOM"""
|
||||
def __init__(self,
|
||||
dom: Optional[FileDOM] = None,
|
||||
dom: FileDOM,
|
||||
src: Optional[str] = None):
|
||||
self.valid = False
|
||||
self.name = None
|
||||
|
@ -70,9 +72,7 @@ class SchemaDOM:
|
|||
self._schema = {} # type: Dict[str, Set[str]]
|
||||
self._spec = {} # type: Dict[str, str]
|
||||
self._links = {} # type: Dict[str, List[str]]
|
||||
self._dom = dom
|
||||
|
||||
if dom is not None:
|
||||
self.dom = dom
|
||||
self.parse(dom)
|
||||
|
||||
@property
|
||||
|
@ -230,8 +230,8 @@ class SchemaDOM:
|
|||
def __str__(self) -> str:
|
||||
return self._dom.__str__()
|
||||
|
||||
|
||||
def read_file(src: str) -> SchemaDOM:
|
||||
@staticmethod
|
||||
def from_file(src: str) -> DOM:
|
||||
"""Parses SchemaDOM from file"""
|
||||
with open(src, mode='r', encoding='utf-8') as f:
|
||||
dom = FileDOM(src=src, text=f.readlines())
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
"TransactDOM"
|
||||
|
||||
from typing import Sequence, List, Optional, Tuple
|
||||
from typing import Sequence, List, Optional, Tuple, TypeVar
|
||||
|
||||
from .filedom import FileDOM
|
||||
from .schema import SchemaDOM
|
||||
|
||||
DOM = TypeVar("DOM", bound="TransactDOM")
|
||||
|
||||
|
||||
class TransactDOM():
|
||||
|
@ -12,6 +15,7 @@ class TransactDOM():
|
|||
text: Optional[Sequence[str]] = None):
|
||||
self.valid = False
|
||||
self.files = [] # type: List[FileDOM]
|
||||
self.schemas = []
|
||||
self.delete = [] # type: List[Tuple[str, str]]
|
||||
self.mntner = None # type: Optional[str]
|
||||
|
||||
|
@ -42,9 +46,11 @@ class TransactDOM():
|
|||
dom = FileDOM(text=buffer)
|
||||
buffer = []
|
||||
if dom.valid:
|
||||
print(dom.name)
|
||||
self.files.append(dom)
|
||||
|
||||
if dom.schema == 'schema':
|
||||
self.schemas.append(SchemaDOM(dom))
|
||||
|
||||
if line.startswith(".DELETE"):
|
||||
sp = line.split()
|
||||
if len(sp) > 2:
|
||||
|
@ -60,3 +66,9 @@ class TransactDOM():
|
|||
s += "...\n".join({str(record) for record in self.files})
|
||||
s += ".END"
|
||||
return s
|
||||
|
||||
@staticmethod
|
||||
def from_file(src: str) -> DOM:
|
||||
"Read transact from files"
|
||||
with open(src) as f:
|
||||
return TransactDOM(f.readlines())
|
||||
|
|
112
utils/registry/main.py
Normal file
112
utils/registry/main.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
"""rpsl a tool for managing RPSL databases
|
||||
==========================================
|
||||
|
||||
Usage: rpsl [command] [options]
|
||||
rpsl help [command]
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import Tuple, List, Optional
|
||||
|
||||
import importlib
|
||||
import pkgutil
|
||||
|
||||
|
||||
def remove_prefix(text, prefix):
|
||||
"remove the prefix"
|
||||
if text.startswith(prefix):
|
||||
return text[len(prefix):]
|
||||
return text
|
||||
|
||||
|
||||
discovered_plugins = {
|
||||
remove_prefix(name, "rpsl_"): importlib.import_module(name)
|
||||
for finder, name, ispkg
|
||||
in pkgutil.iter_modules()
|
||||
if name.startswith("rpsl_")
|
||||
}
|
||||
|
||||
|
||||
def do_help(cmd: Optional[str] = None):
|
||||
"Print Help and exit"
|
||||
|
||||
print(__doc__, file=sys.stderr)
|
||||
|
||||
if cmd is None:
|
||||
print("Available commands:", file=sys.stderr)
|
||||
for pkg in discovered_plugins.keys():
|
||||
print(f" - {pkg}", file=sys.stderr)
|
||||
return 0
|
||||
|
||||
if cmd not in discovered_plugins:
|
||||
print(f"Command not found: {cmd}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print(discovered_plugins[cmd].__doc__, file=sys.stderr)
|
||||
return 0
|
||||
|
||||
|
||||
def find_rpsl(path: str) -> str:
|
||||
"Find the root directory for RPSL"
|
||||
path = os.path.abspath(path)
|
||||
rpsl = os.path.join(path, ".rpsl")
|
||||
while not os.path.exists(rpsl):
|
||||
if path == "/":
|
||||
break
|
||||
path = os.path.dirname(path)
|
||||
rpsl = os.path.join(path, ".rpsl")
|
||||
|
||||
if not os.path.exists(rpsl):
|
||||
return None
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def run() -> int:
|
||||
"run application"
|
||||
working_dir = os.getcwd()
|
||||
working_dir = os.environ.get("WORKING_DIR", working_dir)
|
||||
prog_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
rpsl_dir = os.environ.get("RPSL_DIR", working_dir)
|
||||
rpsl_dir = find_rpsl(rpsl_dir)
|
||||
|
||||
cmd, args = shift(shift(sys.argv)[1])
|
||||
|
||||
if cmd is None or cmd == 'help':
|
||||
cmd, _ = shift(args)
|
||||
return do_help(cmd)
|
||||
|
||||
if cmd not in discovered_plugins:
|
||||
print(f"Unsupported Command: {cmd}")
|
||||
return 1
|
||||
|
||||
pkg = discovered_plugins[cmd]
|
||||
|
||||
if 'run' not in dir(pkg):
|
||||
print(f"Command {cmd} is not compatible with rspl.", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
return pkg.run(args, {
|
||||
"WORKING_DIR": working_dir,
|
||||
"BIN_DIR": prog_dir,
|
||||
"RPSL_DIR": rpsl_dir,
|
||||
})
|
||||
|
||||
|
||||
def shift(args: List[str]) -> Tuple[str, List[str]]:
|
||||
"shift off first arg + rest"
|
||||
if len(args) == 0:
|
||||
return None, []
|
||||
|
||||
if len(args) == 1:
|
||||
return args[0], []
|
||||
|
||||
return args[0], args[1:]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
code = run()
|
||||
sys.exit(code)
|
8
utils/registry/rpsl
Executable file
8
utils/registry/rpsl
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from main import run
|
||||
|
||||
if __name__ == '__main__':
|
||||
code = run()
|
||||
sys.exit(code)
|
190
utils/registry/rpsl_index/__init__.py
Normal file
190
utils/registry/rpsl_index/__init__.py
Normal file
|
@ -0,0 +1,190 @@
|
|||
"""RSPL Build Indexes
|
||||
=====================
|
||||
|
||||
Usage: rspl index
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from typing import Dict, Generator, List, Set, Tuple
|
||||
|
||||
from dom.filedom import FileDOM
|
||||
from dom.schema import SchemaDOM
|
||||
from dom.nettree import NetTree, NetRecord
|
||||
from dom.transact import TransactDOM
|
||||
from dom.rspl import RPSLConfig
|
||||
|
||||
|
||||
def run(args: List[str], env: Dict[str, str]) -> int:
|
||||
"rspl index"
|
||||
|
||||
_ = args
|
||||
|
||||
path = env.get("WORKING_DIR")
|
||||
|
||||
if not os.path.isdir(os.path.join(path, "schema")):
|
||||
print("schema directory not found in path", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(r"Reading Files...", end="\r", flush=True, file=sys.stderr)
|
||||
idx = index_files(path)
|
||||
lookup, schemas, files, nets = build_index(idx)
|
||||
|
||||
print(
|
||||
f"Reading Files: done! files: {len(files)}" +
|
||||
f" schemas: {len(schemas)}" +
|
||||
f" networks: {len(nets)}",
|
||||
file=sys.stderr)
|
||||
|
||||
print("Writing .rpsl/index", file=sys.stderr)
|
||||
with open(".rpsl/index", 'w') as out:
|
||||
print("Writing .rpsl/links", file=sys.stderr)
|
||||
with open(".rpsl/links", 'w') as link_out:
|
||||
for dom in files:
|
||||
s = schemas.get(dom.rel)
|
||||
if s is None:
|
||||
print(
|
||||
f"{dom.src} schema not found for {dom.rel}",
|
||||
file=sys.stderr)
|
||||
continue
|
||||
|
||||
primary, mntner = dom.get(s.primary), ",".join(dom.mntner)
|
||||
_ = mntner
|
||||
src = remove_prefix(dom.src, path+os.sep)
|
||||
print(dom.rel, primary, src, # mntner,
|
||||
sep="|", file=out)
|
||||
|
||||
for (link, rel, d) in generate_links(dom, s.links, lookup):
|
||||
print(f"{dom.rel}|{dom.name}|{link}|{rel}|{d}",
|
||||
file=link_out)
|
||||
|
||||
print("Generate .rpsl/nettree", file=sys.stderr)
|
||||
tree = NetTree(nets)
|
||||
|
||||
print("Writing .rpsl/nettree", file=sys.stderr)
|
||||
tree.write_csv(".rpsl/nettree")
|
||||
|
||||
print("Writing .rpsl/schema", file=sys.stderr)
|
||||
s = TransactDOM()
|
||||
s.mntner = "DN42-MNT"
|
||||
s.files = schemas.values()
|
||||
with open(".rpsl/schema", "w") as out:
|
||||
print(s, file=out)
|
||||
|
||||
print("done.", file=sys.stderr)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
class NotRPSLPath(Exception):
|
||||
"error raised if unable to determine RPSL root"
|
||||
|
||||
|
||||
def index_files(path: str) -> Generator[FileDOM, None, None]:
|
||||
"""generate list of dom files"""
|
||||
path = os.path.abspath(path)
|
||||
rpsl = os.path.join(path, ".rpsl/config")
|
||||
while not os.path.exists(rpsl):
|
||||
if path == "/":
|
||||
break
|
||||
path = os.path.dirname(path)
|
||||
rpsl = os.path.join(path, ".rpsl/config")
|
||||
|
||||
if not os.path.exists(rpsl):
|
||||
raise NotRPSLPath()
|
||||
|
||||
yield FileDOM.from_file(rpsl)
|
||||
|
||||
for root, _, files in os.walk(path):
|
||||
if root == path:
|
||||
continue
|
||||
if root.endswith(".rpsl"):
|
||||
continue
|
||||
|
||||
for f in files:
|
||||
dom = FileDOM.from_file(os.path.join(root, f))
|
||||
yield dom
|
||||
|
||||
|
||||
def build_index(
|
||||
idx: Generator[FileDOM, None, None]
|
||||
) -> Tuple[
|
||||
Set[Tuple[str, str]],
|
||||
Dict[str, SchemaDOM],
|
||||
List[FileDOM],
|
||||
List[NetRecord]]:
|
||||
"build index for files"
|
||||
rspl = RPSLConfig.default()
|
||||
lookup = set() # type: Set[Tuple[str, str]]
|
||||
schemas = {} # type: Dict[str, SchemaDOM]
|
||||
files = [] # type: List[FileDOM]
|
||||
nets = [] # type: List[NetRecord]
|
||||
|
||||
print(r"Reading Files...", end="\r", flush=True, file=sys.stderr)
|
||||
|
||||
net_types = rspl.network_parents
|
||||
|
||||
for (i, dom) in enumerate(idx):
|
||||
if not dom.valid:
|
||||
print("E", end="", flush=True)
|
||||
continue
|
||||
|
||||
key, _ = dom.index
|
||||
lookup.add(key)
|
||||
files.append(dom)
|
||||
|
||||
if dom.schema == "namespace":
|
||||
rspl = RPSLConfig.from_dom(dom)
|
||||
net_types = rspl.network_parents
|
||||
|
||||
if dom.schema == rspl.schema:
|
||||
schema = SchemaDOM(dom)
|
||||
schemas[schema.ref] = schema
|
||||
|
||||
if dom.schema in net_types:
|
||||
nets.append(NetRecord(
|
||||
dom.get("cidr").as_net6,
|
||||
dom.mntner,
|
||||
dom.get("policy", default="closed"),
|
||||
dom.get("status", default="ASSIGNED"),
|
||||
))
|
||||
|
||||
if i % 120 == 0:
|
||||
print(
|
||||
f"Reading Files: files: {len(files)}" +
|
||||
f" schemas: {len(schemas)} " +
|
||||
f" networks: {len(nets)}",
|
||||
end="\r", flush=True, file=sys.stderr)
|
||||
|
||||
return (lookup, schemas, files, nets)
|
||||
|
||||
|
||||
def generate_links(
|
||||
dom: FileDOM,
|
||||
links: Dict[str, List[str]],
|
||||
lookup: Set[Tuple[str, str]]
|
||||
) -> Generator[Tuple[str, str, str], None, None]:
|
||||
"print file links out to file"
|
||||
for (link, refs) in links.items():
|
||||
d = dom.get(link)
|
||||
if d is None:
|
||||
return
|
||||
|
||||
found = False
|
||||
for ref in refs:
|
||||
if (ref, d.value) in lookup:
|
||||
found = True
|
||||
yield (link, ref, d)
|
||||
|
||||
if not found:
|
||||
print(f"{dom.name} missing link {link} {d.value}")
|
||||
|
||||
|
||||
def remove_prefix(text, prefix):
|
||||
"remove the prefix"
|
||||
if text.startswith(prefix):
|
||||
return text[len(prefix):]
|
||||
return text
|
89
utils/registry/rpsl_init/__init__.py
Normal file
89
utils/registry/rpsl_init/__init__.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
"""RSPL Initialize data store
|
||||
=============================
|
||||
|
||||
Usage: rspl init [options]
|
||||
|
||||
Options:
|
||||
--namespace=<ns> Namespace (default: current working dir name)
|
||||
--schema=<schema> Schema (default: schema)
|
||||
--owners=<mntner> Owner (default: mntner)
|
||||
--default-owner=<mnt> Default Owner (default: DN42-MNT)
|
||||
--source=<src> Source (default: DN42)
|
||||
--force Force creation of config
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import argparse
|
||||
from typing import List, Dict, Generator, Tuple, Set, TypeVar
|
||||
|
||||
from dom.rspl import RPSLConfig
|
||||
from dom.filedom import FileDOM
|
||||
from dom.schema import SchemaDOM
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--namespace", type=str, default=None)
|
||||
parser.add_argument("--schema", type=str, default="schema")
|
||||
parser.add_argument("--owners", type=str, default="mntner")
|
||||
parser.add_argument("--default-owner", type=str, default="DN42-MNT")
|
||||
parser.add_argument("--source", type=str, default="DN42")
|
||||
parser.add_argument("--force", action='store_true')
|
||||
|
||||
|
||||
def run(args: List[str], env: Dict[str, str]) -> int:
|
||||
"rspl init"
|
||||
opts = parser.parse_args(args)
|
||||
if opts.namespace is None:
|
||||
opts.namespace = os.path.basename(env.get("WORKING_DIR"))
|
||||
|
||||
rpsl_dir = env.get("RPSL_DIR")
|
||||
if rpsl_dir is not None and not opts.force:
|
||||
print(f"RPSL database already initialized! Found in: {rpsl_dir}")
|
||||
return 1
|
||||
|
||||
rpsl_dir = env.get("WORKING_DIR")
|
||||
rpsl = RPSLConfig(root=rpsl_dir,
|
||||
namespace=opts.namespace,
|
||||
schema=opts.schema,
|
||||
owners=opts.owners,
|
||||
source=opts.source,
|
||||
default_owner=opts.default_owner)
|
||||
|
||||
if os.path.exists(rpsl.schema_dir):
|
||||
rpsl.network_owner, rpsl.primary_key = _parse_schema(rpsl.schema_dir)
|
||||
|
||||
os.makedirs(os.path.dirname(rpsl.config_file), exist_ok=True)
|
||||
with open(rpsl.config_file, "w") as f:
|
||||
print(rpsl, file=f)
|
||||
|
||||
print(f"Created: {rpsl.config_file}", file=sys.stderr)
|
||||
return 0
|
||||
|
||||
|
||||
def _read_schemas(path: str) -> Generator[SchemaDOM, None, None]:
|
||||
for root, _, files in os.walk(path):
|
||||
for f in files:
|
||||
dom = FileDOM.from_file(os.path.join(root, f))
|
||||
schema = SchemaDOM(dom)
|
||||
yield schema
|
||||
|
||||
|
||||
Group = TypeVar("Group", set, tuple)
|
||||
|
||||
|
||||
def _parse_schema(path: str) -> Tuple[Group, Group]:
|
||||
schemas = _read_schemas(path)
|
||||
|
||||
network_owner = set() # type: Set[str, str]
|
||||
primary_key = set() # type: Set[str, str]
|
||||
|
||||
for s in schemas:
|
||||
for i in s.dom.get_all("network-owner"):
|
||||
network_owner.add((s.type, i.value))
|
||||
|
||||
if s.primary != s.type:
|
||||
primary_key.add((s.type, s.primary))
|
||||
|
||||
print(network_owner)
|
||||
return network_owner, primary_key
|
96
utils/registry/rpsl_scan/__init__.py
Normal file
96
utils/registry/rpsl_scan/__init__.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
"""RSPL Scan
|
||||
============
|
||||
|
||||
Usage: rspl scan [options]
|
||||
|
||||
Options:
|
||||
--scan-dir=<dir> Scan given directory
|
||||
--scan-file=<file> Scan given file
|
||||
--add-index Add scanned items to lookup table
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from typing import List, Dict
|
||||
|
||||
from dom.filedom import FileDOM
|
||||
from dom.schema import SchemaDOM
|
||||
from dom.transact import TransactDOM
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--add-index", action='store_true')
|
||||
parser.add_argument("--scan-dir", type=str, default=None)
|
||||
parser.add_argument("--scan-file", type=str, default=None)
|
||||
|
||||
|
||||
def index_files(path: str):
|
||||
"""generate list of dom files"""
|
||||
for root, _, files in os.walk(path):
|
||||
if root == path:
|
||||
continue
|
||||
if root.endswith(".rpsl"):
|
||||
continue
|
||||
|
||||
for f in files:
|
||||
dom = FileDOM.from_file(os.path.join(root, f))
|
||||
yield dom
|
||||
|
||||
|
||||
def run(args: List[str], env: Dict[str, str]) -> int:
|
||||
"""run scan script"""
|
||||
opts = parser.parse_args(args)
|
||||
|
||||
path = env.get("RPSL_DIR")
|
||||
if path is None:
|
||||
print("RPSL directory not found. do `rpsl init` or set RPSL_DIR",
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
|
||||
index_file = os.path.join(path, ".rpsl/index")
|
||||
schema_file = os.path.join(path, ".rpsl/schema")
|
||||
|
||||
if not os.path.exists(index_file) or not os.path.exists(schema_file):
|
||||
print("RPSL index files not found. do `rpsl index`?")
|
||||
return 1
|
||||
|
||||
lookups = {} # type: Dict[str, FileDOM]
|
||||
schemas = {} # type: Dict[str, SchemaDOM]
|
||||
|
||||
with open(index_file) as fd:
|
||||
print("Reading index... ", end="", file=sys.stderr, flush=True)
|
||||
for line in fd.readlines():
|
||||
sp = line.strip().split(sep="|")
|
||||
lookups[(sp[0], sp[1])] = (sp[2], "")
|
||||
print("done.", file=sys.stderr, flush=True)
|
||||
|
||||
schema_set = TransactDOM.from_file(schema_file)
|
||||
|
||||
for schema in schema_set.schemas:
|
||||
schemas[schema.ref] = schema
|
||||
|
||||
def file_gen(path):
|
||||
if opts.scan_dir is not None:
|
||||
path = os.path.join(env.get("WORKING_DIR"), opts.scan_dir)
|
||||
elif opts.scan_file is not None:
|
||||
path = os.path.join(env.get("WORKING_DIR"), opts.scan_file)
|
||||
return TransactDOM.from_file(path).files
|
||||
|
||||
return index_files(path)
|
||||
|
||||
if opts.add_index:
|
||||
print("Add scanned items to lookup index...", file=sys.stderr)
|
||||
for dom in file_gen(path):
|
||||
key, value = dom.index
|
||||
lookups[key] = value
|
||||
|
||||
for dom in file_gen(path):
|
||||
s = schemas.get(dom.rel)
|
||||
if s is None:
|
||||
print(f"{dom.src} schema not found for {dom.rel}")
|
||||
|
||||
status = s.check_file(dom, lookups=lookups)
|
||||
status.print()
|
||||
print(status)
|
||||
return 0 if status else 1
|
12
utils/registry/rpsl_status/__init__.py
Normal file
12
utils/registry/rpsl_status/__init__.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
"""RSPL Status
|
||||
==============
|
||||
"""
|
||||
|
||||
|
||||
from typing import List, Dict
|
||||
|
||||
|
||||
def run(args: List[str], env: Dict[str, str]) -> int:
|
||||
"do run"
|
||||
print("RUN STATUS", args, env)
|
||||
return 0
|
78
utils/registry/rpsl_whois/__init__.py
Normal file
78
utils/registry/rpsl_whois/__init__.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
"""RSPL Whois Search
|
||||
====================
|
||||
|
||||
Usage: rpsl whois [text]
|
||||
|
||||
"""
|
||||
|
||||
import os.path
|
||||
from ipaddress import ip_network
|
||||
from typing import List, Dict, Tuple
|
||||
|
||||
from dom.filedom import FileDOM
|
||||
|
||||
|
||||
def run(args: List[str], env: Dict[str, str]) -> int:
|
||||
"do whois search"
|
||||
path = env.get("RPSL_DIR")
|
||||
|
||||
if len(args) == 0:
|
||||
print("Usage: rpsl whois [text]")
|
||||
|
||||
schema = None
|
||||
text, args = shift(args)
|
||||
|
||||
if len(args) > 0:
|
||||
schema = text
|
||||
text, args = shift(args)
|
||||
|
||||
ip = None
|
||||
try:
|
||||
ip = ip_network(text)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
lookups, find = load_lookup(path)
|
||||
|
||||
if ip is not None:
|
||||
print(f"Searching network {text}...")
|
||||
return 0
|
||||
|
||||
keys = [(schema, text)]
|
||||
if schema is None:
|
||||
keys = find.get(text, [])
|
||||
|
||||
for i in keys:
|
||||
fn = os.path.join(path, lookups[i][2])
|
||||
print(FileDOM.from_file(fn))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def load_lookup(path: str) -> Tuple[Dict[Tuple[str, str], FileDOM],
|
||||
Dict[str, List[Tuple[str, str]]]]:
|
||||
"Load lookup data"
|
||||
index_file = os.path.join(path, ".rpsl/index")
|
||||
|
||||
lookups = {} # type: Dict[Tuple[str, str], FileDOM]
|
||||
find = {} # type: Dict[str, List[Tuple[str, str]]]
|
||||
|
||||
with open(index_file) as fd:
|
||||
for line in fd.readlines():
|
||||
sp = line.strip().split(sep="|")
|
||||
lookups[(sp[0], sp[1])] = (sp[0], sp[1], sp[2])
|
||||
find[sp[1]] = find.get(sp[1], [])
|
||||
find[sp[1]].append((sp[0], sp[1]))
|
||||
|
||||
return lookups, find
|
||||
|
||||
|
||||
def shift(args: List[str]) -> Tuple[str, List[str]]:
|
||||
"shift off first arg + rest"
|
||||
if len(args) == 0:
|
||||
return None, []
|
||||
|
||||
if len(args) == 1:
|
||||
return args[0], []
|
||||
|
||||
return args[0], args[1:]
|
|
@ -1,64 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Scans Registry at given path for issues using an pregenerated index"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import Dict
|
||||
|
||||
from dom.filedom import FileDOM, read_file
|
||||
from dom.schema import SchemaDOM
|
||||
|
||||
|
||||
def index_files(path: str):
|
||||
"""generate list of dom files"""
|
||||
for root, _, files in os.walk(path):
|
||||
if root == path:
|
||||
continue
|
||||
|
||||
for f in files:
|
||||
if f[0] == ".":
|
||||
continue
|
||||
|
||||
dom = read_file(os.path.join(root, f))
|
||||
yield dom
|
||||
|
||||
|
||||
def run(path: str = ".", index: str = ".index"):
|
||||
"""run main script"""
|
||||
|
||||
lookups = {} # type: Dict[str, FileDOM]
|
||||
schemas = {} # type: Dict[str, SchemaDOM]
|
||||
|
||||
schema_set = set()
|
||||
with open(index) as fd:
|
||||
for line in fd.readlines():
|
||||
sp = line.split()
|
||||
lookups[(sp[0], sp[1])] = (sp[2], sp[3])
|
||||
|
||||
if sp[0] == "dn42.schema":
|
||||
schema_set.add(sp[2])
|
||||
|
||||
for s in schema_set:
|
||||
dom = read_file(s)
|
||||
schema = SchemaDOM()
|
||||
schema.parse(dom)
|
||||
|
||||
schemas[schema.ref] = schema
|
||||
|
||||
files = index_files(path)
|
||||
for dom in files:
|
||||
key, value = dom.index
|
||||
lookups[key] = value
|
||||
|
||||
for dom in files:
|
||||
s = schemas.get(dom.rel)
|
||||
if s is None:
|
||||
print(f"{dom.src} schema not found for {dom.rel}")
|
||||
|
||||
status = s.check_file(dom, lookups=lookups)
|
||||
status.print()
|
||||
print(status)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(sys.argv[1] if len(sys.argv) >= 2 else os.getcwd())
|
|
@ -5,7 +5,7 @@ import os
|
|||
import sys
|
||||
from typing import Dict
|
||||
|
||||
from dom.filedom import FileDOM, read_file
|
||||
from dom.filedom import FileDOM
|
||||
from dom.schema import SchemaDOM
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ def index_files(path: str):
|
|||
if f[0] == ".":
|
||||
continue
|
||||
|
||||
dom = read_file(os.path.join(root, f))
|
||||
dom = FileDOM.from_file(os.path.join(root, f))
|
||||
|
||||
yield dom
|
||||
|
||||
|
@ -44,9 +44,7 @@ def run(path: str = "."):
|
|||
files.append(dom)
|
||||
|
||||
if dom.schema == "schema":
|
||||
schema = SchemaDOM()
|
||||
schema.parse(dom)
|
||||
|
||||
schema = SchemaDOM(dom)
|
||||
schemas[schema.ref] = schema
|
||||
|
||||
if i % 120 == 0:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue