]> git.ipfire.org Git - location/libloc.git/blame - src/libloc.c
database: Implement lookup
[location/libloc.git] / src / libloc.c
CommitLineData
46aded9a
MT
1/*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2017 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
2a30e4de
MT
17#include <arpa/inet.h>
18#include <netinet/in.h>
46aded9a
MT
19#include <stdio.h>
20#include <stdlib.h>
21#include <stddef.h>
22#include <stdarg.h>
23#include <unistd.h>
24#include <errno.h>
25#include <string.h>
26#include <ctype.h>
27
28#include <loc/libloc.h>
9fc7f001
MT
29#include <loc/database.h>
30#include <loc/private.h>
46aded9a
MT
31
32struct loc_ctx {
33 int refcount;
34 void (*log_fn)(struct loc_ctx* ctx,
35 int priority, const char *file, int line, const char *fn,
36 const char *format, va_list args);
37 int log_priority;
2601e83e
MT
38
39 struct loc_database* db;
46aded9a
MT
40};
41
42void loc_log(struct loc_ctx* ctx,
43 int priority, const char* file, int line, const char* fn,
44 const char* format, ...) {
45 va_list args;
46
47 va_start(args, format);
48 ctx->log_fn(ctx, priority, file, line, fn, format, args);
49 va_end(args);
50}
51
52static void log_stderr(struct loc_ctx* ctx,
53 int priority, const char* file, int line, const char* fn,
54 const char* format, va_list args) {
55 fprintf(stderr, "libloc: %s: ", fn);
56 vfprintf(stderr, format, args);
57}
58
59static int log_priority(const char* priority) {
60 char *endptr;
61
62 int prio = strtol(priority, &endptr, 10);
63
64 if (endptr[0] == '\0' || isspace(endptr[0]))
65 return prio;
66
67 if (strncmp(priority, "err", 3) == 0)
68 return LOG_ERR;
69
70 if (strncmp(priority, "info", 4) == 0)
71 return LOG_INFO;
72
73 if (strncmp(priority, "debug", 5) == 0)
74 return LOG_DEBUG;
75
76 return 0;
77}
78
79LOC_EXPORT int loc_new(struct loc_ctx** ctx) {
80 struct loc_ctx* c = calloc(1, sizeof(*c));
81 if (!c)
82 return -ENOMEM;
83
84 c->refcount = 1;
85 c->log_fn = log_stderr;
86 c->log_priority = LOG_ERR;
87
2601e83e
MT
88 c->db = NULL;
89
46aded9a
MT
90 const char* env = secure_getenv("LOC_LOG");
91 if (env)
92 loc_set_log_priority(c, log_priority(env));
93
94 INFO(c, "ctx %p created\n", c);
95 DEBUG(c, "log_priority=%d\n", c->log_priority);
96 *ctx = c;
97
98 return 0;
99}
100
101LOC_EXPORT struct loc_ctx* loc_ref(struct loc_ctx* ctx) {
102 if (!ctx)
103 return NULL;
104
105 ctx->refcount++;
106
107 return ctx;
108}
109
110LOC_EXPORT struct loc_ctx* loc_unref(struct loc_ctx* ctx) {
111 if (!ctx)
112 return NULL;
113
114 if (--ctx->refcount > 0)
115 return NULL;
116
2601e83e
MT
117 // Release any loaded databases
118 if (ctx->db)
119 loc_database_unref(ctx->db);
120
46aded9a
MT
121 INFO(ctx, "context %p released\n", ctx);
122 free(ctx);
123
124 return NULL;
125}
126
127LOC_EXPORT void loc_set_log_fn(struct loc_ctx* ctx,
128 void (*log_fn)(struct loc_ctx* ctx, int priority, const char* file,
129 int line, const char* fn, const char* format, va_list args)) {
130 ctx->log_fn = log_fn;
131 INFO(ctx, "custom logging function %p registered\n", log_fn);
132}
133
134LOC_EXPORT int loc_get_log_priority(struct loc_ctx* ctx) {
135 return ctx->log_priority;
136}
137
138LOC_EXPORT void loc_set_log_priority(struct loc_ctx* ctx, int priority) {
139 ctx->log_priority = priority;
140}
2601e83e
MT
141
142LOC_EXPORT int loc_load(struct loc_ctx* ctx, const char* path) {
143 FILE* f = fopen(path, "r");
144 if (!f)
145 return -errno;
146
147 // Release any previously openend database
148 if (ctx->db)
149 loc_database_unref(ctx->db);
150
151 // Open the new database
c182393f 152 int r = loc_database_new(ctx, &ctx->db, f);
2601e83e
MT
153 if (r)
154 return r;
155
156 // Close the file
157 fclose(f);
158
159 return 0;
160}
2a30e4de
MT
161
162LOC_EXPORT int loc_parse_address(struct loc_ctx* ctx, const char* string, struct in6_addr* address) {
163 DEBUG(ctx, "Paring IP address %s\n", string);
164
165 // Try parsing this as an IPv6 address
166 int r = inet_pton(AF_INET6, string, address);
167
168 // If inet_pton returns one it has been successful
169 if (r == 1) {
170 DEBUG(ctx, "%s is an IPv6 address\n", string);
171 return 0;
172 }
173
174 // Try parsing this as an IPv4 address
175 struct in_addr ipv4_address;
176 r = inet_pton(AF_INET, string, &ipv4_address);
177 if (r == 1) {
178 DEBUG(ctx, "%s is an IPv4 address\n", string);
179
180 // Convert to IPv6-mapped address
181 address->s6_addr32[0] = htonl(0x0000);
182 address->s6_addr32[1] = htonl(0x0000);
183 address->s6_addr32[2] = htonl(0xffff);
184 address->s6_addr32[3] = ipv4_address.s_addr;
185
186 return 0;
187 }
188
189 DEBUG(ctx, "%s is not an valid IP address\n", string);
190 return 1;
191}