]> git.ipfire.org Git - location/libloc.git/blame - src/python/location-query.in
Implement listing networks in Python
[location/libloc.git] / src / python / location-query.in
CommitLineData
5118a4b8
MT
1#!/usr/bin/python3
2###############################################################################
3# #
4# libloc - A library to determine the location of someone on the Internet #
5# #
6# Copyright (C) 2017 IPFire Development Team <info@ipfire.org> #
7# #
8# This library is free software; you can redistribute it and/or #
9# modify it under the terms of the GNU Lesser General Public #
10# License as published by the Free Software Foundation; either #
11# version 2.1 of the License, or (at your option) any later version. #
12# #
13# This library is distributed in the hope that it will be useful, #
14# but WITHOUT ANY WARRANTY; without even the implied warranty of #
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
16# Lesser General Public License for more details. #
17# #
18###############################################################################
19
20import argparse
2bb7d64e 21import gettext
5118a4b8
MT
22import sys
23import syslog
24
25# Load our location module
26import location
27
28# i18n
2bb7d64e
MT
29def _(singular, plural=None, n=None):
30 if plural:
31 return gettext.dngettext("libloc", singular, plural, n)
32
33 return gettext.dgettext("libloc", singular)
5118a4b8
MT
34
35class CLI(object):
5118a4b8
MT
36 def parse_cli(self):
37 parser = argparse.ArgumentParser(
38 description=_("Location Database Command Line Interface"),
39 )
40 subparsers = parser.add_subparsers()
41
42 # Global configuration flags
43 parser.add_argument("--debug", action="store_true",
44 help=_("Enable debug output"))
45
ddb184be
MT
46 # version
47 parser.add_argument("--version", action="version",
48 version="%%(prog)s %s" % location.__version__)
49
2538ed9a
MT
50 # database
51 parser.add_argument("--database", "-d",
52 default="@databasedir@/database.db", help=_("Path to database"),
53 )
54
5118a4b8
MT
55 # lookup an IP address
56 lookup = subparsers.add_parser("lookup",
57 help=_("Lookup one or multiple IP addresses"),
58 )
59 lookup.add_argument("address", nargs="+")
60 lookup.set_defaults(func=self.handle_lookup)
61
fadc1af0
MT
62 # Get AS
63 get_as = subparsers.add_parser("get-as",
64 help=_("Get information about one or multiple Autonomous Systems"),
65 )
66 get_as.add_argument("asn", nargs="+")
67 get_as.set_defaults(func=self.handle_get_as)
68
da3e360e
MT
69 # Search for AS
70 search_as = subparsers.add_parser("search-as",
71 help=_("Search for Autonomous Systems that match the string"),
72 )
73 search_as.add_argument("query", nargs=1)
74 search_as.set_defaults(func=self.handle_search_as)
75
ccc7ab4e
MT
76 # List all networks in a country
77 search_as = subparsers.add_parser("list-networks-by-cc",
78 help=_("Lists all networks in a country"),
79 )
80 search_as.add_argument("country_code", nargs=1)
81 search_as.set_defaults(func=self.handle_list_networks_by_cc)
82
5118a4b8
MT
83 return parser.parse_args()
84
85 def run(self):
86 # Parse command line arguments
87 args = self.parse_cli()
88
89 # Callback function must be defined
90 assert args.func, "Callback function not defined"
91
2538ed9a
MT
92 # Open database
93 try:
94 db = location.Database(args.database)
95 except FileNotFoundError as e:
96 sys.stderr.write("location-query: Could not open database %s: %s\n" \
97 % (args.database, e))
98 sys.exit(1)
99
5118a4b8 100 # Call function
2538ed9a 101 ret = args.func(db, args)
5118a4b8
MT
102
103 # Return with exit code
104 if ret:
105 sys.exit(ret)
106
107 # Otherwise just exit
108 sys.exit(0)
109
2538ed9a 110 def handle_lookup(self, db, ns):
5118a4b8
MT
111 ret = 0
112
113 for address in ns.address:
114 try:
2538ed9a 115 n = db.lookup(address)
5118a4b8 116 except ValueError:
9f2f5d13 117 print(_("Invalid IP address: %s") % address, file=sys.stderr)
5118a4b8
MT
118
119 args = {
120 "address" : address,
121 "network" : n,
122 }
123
124 # Nothing found?
125 if not n:
9f2f5d13 126 print(_("Nothing found for %(address)s") % args, file=sys.stderr)
5118a4b8
MT
127 ret = 1
128 continue
129
130 # Try to retrieve the AS if we have an AS number
131 if n.asn:
2538ed9a 132 a = db.get_as(n.asn)
5118a4b8
MT
133
134 # If we have found an AS we will print it in the message
135 if a:
136 args.update({
137 "as" : a,
138 })
139
140 print(_("%(address)s belongs to %(network)s which is a part of %(as)s") % args)
141 continue
142
143 print(_("%(address)s belongs to %(network)s") % args)
144
145 return ret
146
2538ed9a 147 def handle_get_as(self, db, ns):
fadc1af0
MT
148 """
149 Gets information about Autonomous Systems
150 """
151 ret = 0
152
153 for asn in ns.asn:
154 try:
155 asn = int(asn)
156 except ValueError:
9f2f5d13 157 print(_("Invalid ASN: %s") % asn, file=sys.stderr)
fadc1af0
MT
158 ret = 1
159 continue
160
161 # Fetch AS from database
2538ed9a 162 a = db.get_as(asn)
fadc1af0
MT
163
164 # Nothing found
165 if not a:
9f2f5d13 166 print(_("Could not find AS%s") % asn, file=sys.stderr)
fadc1af0
MT
167 ret = 1
168 continue
169
170 print(_("AS%(asn)s belongs to %(name)s") % { "asn" : a.number, "name" : a.name })
171
172 return ret
5118a4b8 173
2538ed9a 174 def handle_search_as(self, db, ns):
da3e360e
MT
175 for query in ns.query:
176 # Print all matches ASes
2538ed9a 177 for a in db.search_as(query):
da3e360e
MT
178 print(a)
179
ccc7ab4e
MT
180 def handle_list_networks_by_cc(self, db, ns):
181 for country_code in ns.country_code:
182 # Print all matching networks
183 for n in db.search_networks(country_code=country_code):
184 print(n)
185
5118a4b8
MT
186def main():
187 # Run the command line interface
188 c = CLI()
189 c.run()
190
191main()