AmendHub

Download

jcs

/

subtext

/

ipdb.c

 

(View History)

jcs   ipdb: Log when the database has been loaded Latest amendment: 555 on 2023-11-21

1 /*
2 * Copyright (c) 2023 joshua stein <jcs@jcs.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "ipdb.h"
21 #include "logger.h"
22 #include "tcp.h" /* for long2ip/ip2long */
23 #include "util.h"
24
25 struct ipdb_file *
26 ipdb_open(char *filename)
27 {
28 struct ipdb_file *ipdb;
29 size_t size;
30 short error, fh;
31
32 CtoPstr(filename);
33 error = FSOpen(filename, 0, &fh);
34 PtoCstr(filename);
35 if (error) {
36 logger_printf("[ipdb] Failed opening database %s: %d", filename,
37 err);
38 return NULL;
39 }
40
41 ipdb = xmalloc(sizeof(struct ipdb_file));
42 if (ipdb == NULL) {
43 logger_printf("[ipdb] Failed malloc");
44 goto bail;
45 }
46
47 ipdb->fh = fh;
48 SetFPos(ipdb->fh, fsFromLEOF, 0);
49 GetFPos(ipdb->fh, &ipdb->fsize);
50 SetFPos(ipdb->fh, fsFromStart, 0);
51
52 if (ipdb->fsize == 0) {
53 logger_printf("[ipdb] Empty database file %s", filename);
54 goto bail;
55 }
56
57 size = sizeof(ipdb->starts);
58 error = FSRead(ipdb->fh, &size, &ipdb->starts);
59 if (error) {
60 logger_printf("[ipdb] Error reading network table from %s: %d",
61 filename, error);
62 goto bail;
63 }
64
65 logger_printf("[ipdb] Loaded database %s of size %lu", filename,
66 ipdb->fsize);
67
68 return ipdb;
69
70 bail:
71 FSClose(ipdb->fh);
72 if (ipdb != NULL)
73 xfree(&ipdb);
74 return NULL;
75 }
76
77 void
78 ipdb_close(struct ipdb_file **ipdbp)
79 {
80 struct ipdb_file *ipdb = (struct ipdb_file *)*ipdbp;
81
82 FSClose(ipdb->fh);
83 xfree(ipdbp);
84 }
85
86 char *
87 ipdb_lookup(struct ipdb_file *ipdb, u_int32_t ip)
88 {
89 size_t size;
90 u_int32_t range[3], net_start, net_end, start, end, mid, last_mid, pos;
91 short error;
92 unsigned char ip_o[4], locsize, *tmp;
93 char *loc;
94
95 tmp = (unsigned char *)&ip;
96 ip_o[0] = tmp[0];
97 ip_o[1] = tmp[1];
98 ip_o[2] = tmp[2];
99 ip_o[3] = tmp[3];
100
101 net_start = ipdb->starts[ip_o[0]];
102 if (net_start == 0)
103 return NULL;
104
105 net_end = 0;
106 if (ip_o[0] != 255)
107 net_end = ipdb->starts[ip_o[0] + 1];
108 if (net_end == 0)
109 net_end = ipdb->fsize;
110
111 start = net_start;
112 end = net_end;
113 pos = 0;
114 last_mid = 0;
115
116 for (;;) {
117 mid = start + ((end - start) / 2);
118 /* align */
119 mid -= ((mid - net_start) % (sizeof(u_int32_t) * 3));
120 if (mid == last_mid)
121 break;
122 last_mid = mid;
123
124 SetFPos(ipdb->fh, fsFromStart, mid);
125 size = sizeof(range);
126 error = FSRead(ipdb->fh, &size, &range);
127 if (error) {
128 logger_printf("[ipdb] Error reading from database: %d", error);
129 return NULL;
130 }
131
132 if (ip >= range[0] && ip <= range[1]) {
133 pos = range[2];
134 break;
135 }
136
137 if (ip < range[0])
138 /* too high, clamp to [start, mid] */
139 end = mid;
140 else if (ip > range[1])
141 /* too low, clamp to [mid, end] */
142 start = mid;
143
144 if (mid < net_start || mid > net_end)
145 break;
146 }
147
148 if (!pos)
149 return NULL;
150
151 SetFPos(ipdb->fh, fsFromStart, pos);
152 size = 1;
153 error = FSRead(ipdb->fh, &size, &locsize);
154 if (error) {
155 logger_printf("[ipdb] Error reading from database: %d", error);
156 return NULL;
157 }
158
159 loc = xmalloc(locsize + 1);
160 if (loc == NULL) {
161 logger_printf("[ipdb] Out of memory");
162 return NULL;
163 }
164 size = locsize;
165 error = FSRead(ipdb->fh, &size, loc);
166 if (error) {
167 logger_printf("[ipdb] Error reading from database: %d", error);
168 xfree(&loc);
169 return NULL;
170 }
171 loc[locsize] = '\0';
172
173 return loc;
174 }