]> git.ipfire.org Git - people/ms/libloc.git/blob - src/lua/network.c
database: Re-open the file handle in r+ mode
[people/ms/libloc.git] / src / lua / network.c
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 <stdlib.h>
19 #include <string.h>
20
21 #include <lua.h>
22 #include <lauxlib.h>
23
24 #include <libloc/network.h>
25
26 #include "location.h"
27 #include "compat.h"
28 #include "network.h"
29
30 typedef struct network {
31 struct loc_network* network;
32 } Network;
33
34 static Network* luaL_checknetwork(lua_State* L, int i) {
35 void* userdata = luaL_checkudata(L, i, "location.Network");
36
37 // Throw an error if the argument doesn't match
38 luaL_argcheck(L, userdata, i, "Network expected");
39
40 return (Network*)userdata;
41 }
42
43 int create_network(lua_State* L, struct loc_network* network) {
44 // Allocate a new object
45 Network* self = (Network*)lua_newuserdata(L, sizeof(*self));
46
47 // Set metatable
48 luaL_setmetatable(L, "location.Network");
49
50 // Store network
51 self->network = loc_network_ref(network);
52
53 return 1;
54 }
55
56 static int Network_new(lua_State* L) {
57 struct loc_network* network = NULL;
58 const char* n = NULL;
59 int r;
60
61 // Fetch the network
62 n = luaL_checkstring(L, 1);
63
64 // Parse the string
65 r = loc_network_new_from_string(ctx, &network, n);
66 if (r)
67 return luaL_error(L, "Could not create network %s: %s\n", n, strerror(errno));
68
69 // Return the network
70 r = create_network(L, network);
71 loc_network_unref(network);
72
73 return r;
74 }
75
76 static int Network_gc(lua_State* L) {
77 Network* self = luaL_checknetwork(L, 1);
78
79 // Free the network
80 if (self->network) {
81 loc_network_unref(self->network);
82 self->network = NULL;
83 }
84
85 return 0;
86 }
87
88 static int Network_tostring(lua_State* L) {
89 Network* self = luaL_checknetwork(L, 1);
90
91 // Push string representation of the network
92 lua_pushstring(L, loc_network_str(self->network));
93
94 return 1;
95 }
96
97 // ASN
98
99 static int Network_get_asn(lua_State* L) {
100 Network* self = luaL_checknetwork(L, 1);
101
102 uint32_t asn = loc_network_get_asn(self->network);
103
104 // Push ASN
105 if (asn)
106 lua_pushnumber(L, asn);
107 else
108 lua_pushnil(L);
109
110 return 1;
111 }
112
113 // Family
114
115 static int Network_get_family(lua_State* L) {
116 Network* self = luaL_checknetwork(L, 1);
117
118 // Push family
119 lua_pushnumber(L, loc_network_address_family(self->network));
120
121 return 1;
122 }
123
124 // Country Code
125
126 static int Network_get_country_code(lua_State* L) {
127 Network* self = luaL_checknetwork(L, 1);
128
129 const char* country_code = loc_network_get_country_code(self->network);
130
131 // Push country code
132 if (country_code && *country_code)
133 lua_pushstring(L, country_code);
134 else
135 lua_pushnil(L);
136
137 return 1;
138 }
139
140 // Has Flag?
141
142 static int Network_has_flag(lua_State* L) {
143 Network* self = luaL_checknetwork(L, 1);
144
145 // Fetch flag
146 int flag = luaL_checknumber(L, 2);
147
148 // Push result
149 lua_pushboolean(L, loc_network_has_flag(self->network, flag));
150
151 return 1;
152 }
153
154 // Subnets
155
156 static int Network_subnets(lua_State* L) {
157 struct loc_network* subnet1 = NULL;
158 struct loc_network* subnet2 = NULL;
159 int r;
160
161 Network* self = luaL_checknetwork(L, 1);
162
163 // Make subnets
164 r = loc_network_subnets(self->network, &subnet1, &subnet2);
165 if (r)
166 return luaL_error(L, "Could not create subnets of %s: %s\n",
167 loc_network_str(self->network), strerror(errno));
168
169 // Create a new table
170 lua_createtable(L, 2, 0);
171
172 // Create the networks & push them onto the table
173 create_network(L, subnet1);
174 loc_network_unref(subnet1);
175 lua_rawseti(L, -2, 1);
176
177 create_network(L, subnet2);
178 loc_network_unref(subnet2);
179 lua_rawseti(L, -2, 2);
180
181 return 1;
182 }
183
184 // Reverse Pointer
185
186 static int Network_reverse_pointer(lua_State* L) {
187 char* rp = NULL;
188
189 Network* self = luaL_checknetwork(L, 1);
190
191 // Fetch the suffix
192 const char* suffix = luaL_optstring(L, 2, NULL);
193
194 // Make the reverse pointer
195 rp = loc_network_reverse_pointer(self->network, suffix);
196 if (!rp) {
197 switch (errno) {
198 case ENOTSUP:
199 lua_pushnil(L);
200 return 1;
201
202 default:
203 return luaL_error(L, "Could not create reverse pointer: %s\n", strerror(errno));
204 }
205 }
206
207 // Return the response
208 lua_pushstring(L, rp);
209 free(rp);
210
211 return 1;
212 }
213
214 static const struct luaL_Reg Network_functions[] = {
215 { "new", Network_new },
216 { "get_asn", Network_get_asn },
217 { "get_country_code", Network_get_country_code },
218 { "get_family", Network_get_family },
219 { "has_flag", Network_has_flag },
220 { "reverse_pointer", Network_reverse_pointer },
221 { "subnets", Network_subnets },
222 { "__gc", Network_gc },
223 { "__tostring", Network_tostring },
224 { NULL, NULL },
225 };
226
227 int register_network(lua_State* L) {
228 return register_class(L, "location.Network", Network_functions);
229 }