]>
Commit | Line | Data |
---|---|---|
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" |
49463375 | 27 | #include "country.h" |
7eaabd10 | 28 | #include "database.h" |
9fac2ef2 | 29 | #include "network.h" |
7eaabd10 MT |
30 | |
31 | typedef struct database { | |
32 | struct loc_database* db; | |
33 | } Database; | |
34 | ||
35 | static Database* luaL_checkdatabase(lua_State* L, int i) { | |
36 | void* userdata = luaL_checkudata(L, i, "location.Database"); | |
37 | ||
38 | // Throw an error if the argument doesn't match | |
39 | luaL_argcheck(L, userdata, i, "Database expected"); | |
40 | ||
41 | return (Database*)userdata; | |
42 | } | |
43 | ||
44 | static int Database_open(lua_State* L) { | |
45 | const char* path = NULL; | |
46 | FILE* f = NULL; | |
47 | int r; | |
48 | ||
49 | // Fetch the path | |
50 | path = luaL_checkstring(L, 1); | |
51 | ||
52 | // Allocate a new object | |
53 | Database* self = (Database*)lua_newuserdata(L, sizeof(*self)); | |
54 | ||
55 | // Set metatable | |
56 | luaL_setmetatable(L, "location.Database"); | |
57 | ||
58 | // Open the database file | |
59 | f = fopen(path, "r"); | |
60 | if (!f) | |
61 | return luaL_error(L, "Could not open %s: %s\n", path, strerror(errno)); | |
62 | ||
63 | // Open the database | |
64 | r = loc_database_new(ctx, &self->db, f); | |
65 | ||
66 | // Close the file descriptor | |
67 | fclose(f); | |
68 | ||
69 | // Check for errors | |
70 | if (r) | |
71 | return luaL_error(L, "Could not open database %s: %s\n", path, strerror(errno)); | |
72 | ||
73 | return 1; | |
74 | } | |
75 | ||
75448a02 | 76 | static int Database_gc(lua_State* L) { |
3b06229b | 77 | Database* self = luaL_checkdatabase(L, 1); |
7eaabd10 | 78 | |
3b06229b MT |
79 | // Free database |
80 | if (self->db) { | |
7eaabd10 | 81 | loc_database_unref(self->db); |
3b06229b MT |
82 | self->db = NULL; |
83 | } | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
77ee9330 MT |
88 | static int Database_get_as(lua_State* L) { |
89 | struct loc_as* as = NULL; | |
90 | int r; | |
91 | ||
92 | Database* self = luaL_checkdatabase(L, 1); | |
93 | ||
94 | // Fetch number | |
95 | uint32_t asn = luaL_checknumber(L, 2); | |
96 | ||
97 | // Fetch the AS | |
98 | r = loc_database_get_as(self->db, &as, asn); | |
99 | if (r) { | |
100 | lua_pushnil(L); | |
101 | return 1; | |
102 | } | |
103 | ||
104 | // Create a new AS object | |
105 | r = create_as(L, as); | |
106 | loc_as_unref(as); | |
107 | ||
108 | return r; | |
109 | } | |
110 | ||
49463375 MT |
111 | static int Database_get_country(lua_State* L) { |
112 | struct loc_country* country = NULL; | |
113 | int r; | |
114 | ||
115 | Database* self = luaL_checkdatabase(L, 1); | |
116 | ||
117 | // Fetch code | |
118 | const char* code = luaL_checkstring(L, 2); | |
119 | ||
120 | // Fetch the country | |
121 | r = loc_database_get_country(self->db, &country, code); | |
122 | if (r) { | |
123 | lua_pushnil(L); | |
124 | return 1; | |
125 | } | |
126 | ||
127 | // Create a new country object | |
128 | r = create_country(L, country); | |
129 | loc_country_unref(country); | |
130 | ||
131 | return r; | |
132 | } | |
133 | ||
7eaabd10 MT |
134 | static int Database_lookup(lua_State* L) { |
135 | struct loc_network* network = NULL; | |
136 | int r; | |
137 | ||
b49c59d2 | 138 | Database* self = luaL_checkdatabase(L, 1); |
7eaabd10 MT |
139 | |
140 | // Require a string | |
b49c59d2 | 141 | const char* address = luaL_checkstring(L, 2); |
7eaabd10 MT |
142 | |
143 | // Perform lookup | |
144 | r = loc_database_lookup_from_string(self->db, address, &network); | |
145 | if (r) | |
146 | return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno)); | |
147 | ||
9fac2ef2 MT |
148 | // Create a network object |
149 | r = create_network(L, network); | |
7eaabd10 MT |
150 | loc_network_unref(network); |
151 | ||
9fac2ef2 | 152 | return r; |
7eaabd10 MT |
153 | } |
154 | ||
155 | static const struct luaL_Reg database_functions[] = { | |
77ee9330 | 156 | { "get_as", Database_get_as }, |
49463375 | 157 | { "get_country", Database_get_country }, |
7eaabd10 MT |
158 | { "open", Database_open }, |
159 | { "lookup", Database_lookup }, | |
e1c9275c | 160 | { "__gc", Database_gc }, |
7eaabd10 MT |
161 | { NULL, NULL }, |
162 | }; | |
163 | ||
164 | int register_database(lua_State* L) { | |
e914e3ca | 165 | return register_class(L, "location.Database", database_functions); |
7eaabd10 | 166 | } |