]> git.ipfire.org Git - location/libloc.git/blob - src/lua/network.c
network: Add function to return a reverse pointer for networks
[location/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 // Reverse Pointer
155
156 static int Network_reverse_pointer(lua_State* L) {
157 char* rp = NULL;
158
159 Network* self = luaL_checknetwork(L, 1);
160
161 // Fetch the suffix
162 const char* suffix = luaL_optstring(L, 2, NULL);
163
164 // Make the reverse pointer
165 rp = loc_network_reverse_pointer(self->network, suffix);
166 if (!rp) {
167 switch (errno) {
168 case ENOTSUP:
169 lua_pushnil(L);
170 return 1;
171
172 default:
173 return luaL_error(L, "Could not create reverse pointer: %s\n", strerror(errno));
174 }
175 }
176
177 // Return the response
178 lua_pushstring(L, rp);
179 free(rp);
180
181 return 1;
182 }
183
184 static const struct luaL_Reg Network_functions[] = {
185 { "new", Network_new },
186 { "get_asn", Network_get_asn },
187 { "get_country_code", Network_get_country_code },
188 { "get_family", Network_get_family },
189 { "has_flag", Network_has_flag },
190 { "reverse_pointer", Network_reverse_pointer },
191 { "__gc", Network_gc },
192 { "__tostring", Network_tostring },
193 { NULL, NULL },
194 };
195
196 int register_network(lua_State* L) {
197 return register_class(L, "location.Network", Network_functions);
198 }