]> git.ipfire.org Git - location/libloc.git/blame - src/lua/database.c
lua: Don't raise an error if a network cannot be found
[location/libloc.git] / src / lua / database.c
CommitLineData
7eaabd10
MT
1/*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2024 IPFire Development Team <info@ipfire.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15*/
16
17#include <errno.h>
18#include <string.h>
19
20#include <lua.h>
21#include <lauxlib.h>
22
23#include <libloc/database.h>
24
25#include "location.h"
77ee9330 26#include "as.h"
031bae06 27#include "compat.h"
49463375 28#include "country.h"
7eaabd10 29#include "database.h"
9fac2ef2 30#include "network.h"
7eaabd10
MT
31
32typedef struct database {
33 struct loc_database* db;
34} Database;
35
36static Database* luaL_checkdatabase(lua_State* L, int i) {
37 void* userdata = luaL_checkudata(L, i, "location.Database");
38
39 // Throw an error if the argument doesn't match
40 luaL_argcheck(L, userdata, i, "Database expected");
41
42 return (Database*)userdata;
43}
44
45static int Database_open(lua_State* L) {
46 const char* path = NULL;
47 FILE* f = NULL;
48 int r;
49
50 // Fetch the path
51 path = luaL_checkstring(L, 1);
52
53 // Allocate a new object
54 Database* self = (Database*)lua_newuserdata(L, sizeof(*self));
55
56 // Set metatable
57 luaL_setmetatable(L, "location.Database");
58
59 // Open the database file
60 f = fopen(path, "r");
61 if (!f)
62 return luaL_error(L, "Could not open %s: %s\n", path, strerror(errno));
63
64 // Open the database
65 r = loc_database_new(ctx, &self->db, f);
66
67 // Close the file descriptor
68 fclose(f);
69
70 // Check for errors
71 if (r)
72 return luaL_error(L, "Could not open database %s: %s\n", path, strerror(errno));
73
74 return 1;
75}
76
75448a02 77static int Database_gc(lua_State* L) {
3b06229b 78 Database* self = luaL_checkdatabase(L, 1);
7eaabd10 79
3b06229b
MT
80 // Free database
81 if (self->db) {
7eaabd10 82 loc_database_unref(self->db);
3b06229b
MT
83 self->db = NULL;
84 }
85
86 return 0;
87}
88
ba81f732
MT
89// Description
90
91static int Database_get_description(lua_State* L) {
92 Database* self = luaL_checkdatabase(L, 1);
93
94 // Push the description
95 lua_pushstring(L, loc_database_get_description(self->db));
96
97 return 1;
98}
99
100// License
101
102static int Database_get_license(lua_State* L) {
103 Database* self = luaL_checkdatabase(L, 1);
104
105 // Push the license
106 lua_pushstring(L, loc_database_get_license(self->db));
107
108 return 1;
109}
110
111static int Database_get_vendor(lua_State* L) {
112 Database* self = luaL_checkdatabase(L, 1);
113
114 // Push the vendor
115 lua_pushstring(L, loc_database_get_vendor(self->db));
116
117 return 1;
118}
119
77ee9330
MT
120static int Database_get_as(lua_State* L) {
121 struct loc_as* as = NULL;
122 int r;
123
124 Database* self = luaL_checkdatabase(L, 1);
125
126 // Fetch number
127 uint32_t asn = luaL_checknumber(L, 2);
128
129 // Fetch the AS
130 r = loc_database_get_as(self->db, &as, asn);
131 if (r) {
132 lua_pushnil(L);
133 return 1;
134 }
135
136 // Create a new AS object
137 r = create_as(L, as);
138 loc_as_unref(as);
139
140 return r;
141}
142
49463375
MT
143static int Database_get_country(lua_State* L) {
144 struct loc_country* country = NULL;
145 int r;
146
147 Database* self = luaL_checkdatabase(L, 1);
148
149 // Fetch code
150 const char* code = luaL_checkstring(L, 2);
151
152 // Fetch the country
153 r = loc_database_get_country(self->db, &country, code);
154 if (r) {
155 lua_pushnil(L);
156 return 1;
157 }
158
159 // Create a new country object
160 r = create_country(L, country);
161 loc_country_unref(country);
162
163 return r;
164}
165
7eaabd10
MT
166static int Database_lookup(lua_State* L) {
167 struct loc_network* network = NULL;
168 int r;
169
b49c59d2 170 Database* self = luaL_checkdatabase(L, 1);
7eaabd10
MT
171
172 // Require a string
b49c59d2 173 const char* address = luaL_checkstring(L, 2);
7eaabd10
MT
174
175 // Perform lookup
176 r = loc_database_lookup_from_string(self->db, address, &network);
88908fd4
MT
177 if (r) {
178 switch (errno) {
179 // Return nil if the network was not found
180 case ENOENT:
181 lua_pushnil(L);
182 return 1;
183
184 default:
185 return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno));
186 }
187 }
7eaabd10 188
9fac2ef2
MT
189 // Create a network object
190 r = create_network(L, network);
7eaabd10
MT
191 loc_network_unref(network);
192
9fac2ef2 193 return r;
7eaabd10
MT
194}
195
24fce3a8
MT
196static int Database_verify(lua_State* L) {
197 FILE* f = NULL;
198 int r;
199
200 Database* self = luaL_checkdatabase(L, 1);
201
202 // Fetch path to key
203 const char* key = luaL_checkstring(L, 2);
204
205 // Open the keyfile
206 f = fopen(key, "r");
207 if (!f)
208 return luaL_error(L, "Could not open key %s: %s\n", key, strerror(errno));
209
210 // Verify!
211 r = loc_database_verify(self->db, f);
212 fclose(f);
213
214 // Push result onto the stack
215 lua_pushboolean(L, (r == 0));
216
217 return 1;
218}
219
7eaabd10 220static const struct luaL_Reg database_functions[] = {
77ee9330 221 { "get_as", Database_get_as },
ba81f732 222 { "get_description", Database_get_description },
49463375 223 { "get_country", Database_get_country },
ba81f732
MT
224 { "get_license", Database_get_license },
225 { "get_vendor", Database_get_vendor },
7eaabd10
MT
226 { "open", Database_open },
227 { "lookup", Database_lookup },
24fce3a8 228 { "verify", Database_verify },
e1c9275c 229 { "__gc", Database_gc },
7eaabd10
MT
230 { NULL, NULL },
231};
232
233int register_database(lua_State* L) {
e914e3ca 234 return register_class(L, "location.Database", database_functions);
7eaabd10 235}