~ubuntu-branches/ubuntu/karmic/gtk-gnutella/karmic

« back to all changes in this revision

Viewing changes to src/core/whitelist.c

  • Committer: Bazaar Package Importer
  • Author(s): Anand Kumria
  • Date: 2005-08-04 11:32:05 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050804113205-q746i4lgo3rtlegn
Tags: 0.95.4-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2002, Vidar Madsen
 
3
 *
 
4
 *----------------------------------------------------------------------
 
5
 * This file is part of gtk-gnutella.
 
6
 *
 
7
 *  gtk-gnutella is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License as published by
 
9
 *  the Free Software Foundation; either version 2 of the License, or
 
10
 *  (at your option) any later version.
 
11
 *
 
12
 *  gtk-gnutella is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with gtk-gnutella; if not, write to the Free Software
 
19
 *  Foundation, Inc.:
 
20
 *      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
21
 *----------------------------------------------------------------------
 
22
 */
 
23
 
 
24
/**
 
25
 * @ingroup core
 
26
 * @file
 
27
 *
 
28
 * Needs brief description here.
 
29
 *
 
30
 * Functions for keeping a whitelist of nodes we always allow in,
 
31
 * and whom we try to keep a connection to.
 
32
 *
 
33
 * @author Vidar Madsen
 
34
 * @date 2002
 
35
 */
 
36
 
 
37
#include "common.h"
 
38
 
 
39
RCSID("$Id: whitelist.c,v 1.6 2005/06/29 14:24:25 daichik Exp $");
 
40
 
 
41
#include "whitelist.h"
 
42
#include "settings.h"
 
43
#include "nodes.h"
 
44
 
 
45
#include "lib/file.h"
 
46
#include "lib/glib-missing.h"
 
47
#include "lib/override.h"               /* Must be the last header included */
 
48
 
 
49
static GSList *sl_whitelist = NULL;
 
50
 
 
51
static const gchar whitelist_file[] = "whitelist";
 
52
static time_t whitelist_mtime, whitelist_checked;
 
53
static gchar *whitelist_path = NULL;
 
54
 
 
55
/**
 
56
 * whitelist_retrieve
 
57
 *
 
58
 * Loads the whitelist into memory.
 
59
 */
 
60
static void whitelist_retrieve(void)
 
61
{
 
62
    gchar line[1024];
 
63
    gchar *p, *sport, *snetmask;
 
64
    guint32 ip, port, netmask;
 
65
    struct whitelist *n;
 
66
    FILE *f;
 
67
    struct stat st;
 
68
    int linenum = 0;
 
69
        file_path_t fp[1];
 
70
 
 
71
        file_path_set(fp, settings_config_dir(), whitelist_file);
 
72
        f = file_config_open_read_norename("Host Whitelist", fp, G_N_ELEMENTS(fp));
 
73
        if (!f)
 
74
                return;
 
75
 
 
76
        if (fstat(fileno(f), &st)) {
 
77
                g_warning("whitelist_retrieve: fstat() failed: %s", g_strerror(errno));
 
78
                fclose(f);
 
79
                return;
 
80
        }
 
81
    whitelist_checked = time(NULL);
 
82
    whitelist_mtime = st.st_mtime;
 
83
 
 
84
    while (fgets(line, sizeof(line), f)) {
 
85
        linenum++;
 
86
        if (*line == '#') continue;
 
87
 
 
88
                /* Remove trailing spaces so that lines that contain spaces only
 
89
                 * are ignored and cause no warnings. */
 
90
                p = strchr(line, '\0');
 
91
        while (--p >= line) {
 
92
                        if (!is_ascii_space((guchar) *p))
 
93
                                break;
 
94
                *p = '\0';
 
95
                }
 
96
 
 
97
        if ('\0' == *line)
 
98
            continue;
 
99
 
 
100
        sport = snetmask = NULL;
 
101
 
 
102
        if ((p = strchr(line, '/')) != NULL) {
 
103
            *p = '\0';
 
104
            snetmask = ++p;
 
105
        }
 
106
        if ((p = strchr(line, ':')) != NULL) {
 
107
            *p = '\0';
 
108
            sport = ++p;
 
109
        }
 
110
 
 
111
        ip = host_to_ip(line);
 
112
        if (!ip) {
 
113
            g_warning("whitelist_retrieve(): "
 
114
                                "Line %d: Invalid IP \"%s\"", linenum, line);
 
115
            continue;
 
116
        }
 
117
 
 
118
        if (sport)
 
119
            port = atol(sport);
 
120
        else
 
121
            port = 0;
 
122
 
 
123
        netmask = 0xffffffffU; /* Default mask */
 
124
        if (snetmask) {
 
125
            if (strchr(snetmask, '.')) {
 
126
                netmask = gchar_to_ip(snetmask);
 
127
                if (!netmask) {
 
128
                        netmask = 0xffffffff;
 
129
                        g_warning("whitelist_retrieve(): "
 
130
                                                "Line %d: Invalid netmask \"%s\", "
 
131
                                                "using 255.255.255.255 instead.", linenum, snetmask);
 
132
                }
 
133
            } else {
 
134
                                gint error;
 
135
                                gulong v;
 
136
 
 
137
                                v = gm_atoul(snetmask, NULL, &error);
 
138
                if (!error && v > 0 && v <= 32) {
 
139
                        netmask = ~(0xffffffffU >> v);
 
140
                                } else {
 
141
                                        g_warning("whitelist_retrieve(): "
 
142
                                                "Line %d: Invalid netmask \"%s\", "
 
143
                                                "using /32 instead.", linenum, snetmask);
 
144
                                }
 
145
            }
 
146
                }
 
147
 
 
148
        n = g_malloc0(sizeof(*n));
 
149
        n->ip = ip;
 
150
        n->port = port;
 
151
        n->netmask = netmask;
 
152
 
 
153
        sl_whitelist = g_slist_prepend(sl_whitelist, n);
 
154
    }
 
155
 
 
156
    sl_whitelist = g_slist_reverse(sl_whitelist);
 
157
        fclose(f);
 
158
}
 
159
 
 
160
/**
 
161
 * whitelist_connect
 
162
 *
 
163
 * Attempts to connect to the nodes we have whitelisted.
 
164
 * Only entries with a specified port will be tried.
 
165
 *
 
166
 * @returns the number of new nodes that are connected to.
 
167
 */
 
168
guint whitelist_connect(void)
 
169
{
 
170
    GSList *sl;
 
171
    struct whitelist *n;
 
172
    time_t now = time(NULL);
 
173
    guint num = 0;
 
174
 
 
175
    for (sl = sl_whitelist; sl; sl = g_slist_next(sl)) {
 
176
        n = sl->data;
 
177
        if (!n->port)
 
178
            continue;
 
179
        if (node_is_connected(n->ip, n->port, TRUE))
 
180
            continue;
 
181
 
 
182
        if (delta_time(now, n->last_try) > WHITELIST_RETRY_DELAY) {
 
183
            n->last_try = now;
 
184
            node_add(n->ip, n->port);
 
185
            num++;
 
186
        }
 
187
    }
 
188
    return num;
 
189
}
 
190
 
 
191
/**
 
192
 * whitelist_init
 
193
 *
 
194
 * Called on startup. Loads the whitelist into memory.
 
195
 */
 
196
void whitelist_init(void)
 
197
{
 
198
        whitelist_path = make_pathname(settings_config_dir(), whitelist_file);
 
199
    whitelist_retrieve();
 
200
}
 
201
 
 
202
/**
 
203
 * whitelist_close
 
204
 *
 
205
 * Frees all entries in the whitelist.
 
206
 */
 
207
void whitelist_close(void)
 
208
{
 
209
    GSList *sl;
 
210
 
 
211
    for (sl = sl_whitelist; sl; sl = g_slist_next(sl))
 
212
        g_free(sl->data);
 
213
 
 
214
    g_slist_free(sl_whitelist);
 
215
    sl_whitelist = NULL;
 
216
        G_FREE_NULL(whitelist_path);
 
217
}
 
218
 
 
219
/**
 
220
 * whitelist_reload
 
221
 *
 
222
 * Reloads the whitelist.
 
223
 */
 
224
void whitelist_reload(void)
 
225
{
 
226
    whitelist_close();
 
227
    whitelist_retrieve();
 
228
}
 
229
 
 
230
/**
 
231
 * whitelist_check
 
232
 *
 
233
 * Check the given IP agains the entries in the whitelist.
 
234
 * @returns TRUE if found, and FALSE if not.
 
235
 *
 
236
 * Also, it will peridically check the whitelist file for
 
237
 * updates, and reload it if it has changed.
 
238
 */
 
239
gboolean whitelist_check(guint32 ip)
 
240
{
 
241
    struct whitelist *n;
 
242
    time_t now = time(NULL);
 
243
    GSList *sl;
 
244
 
 
245
    /* Check if the file has changed on disk, and reload it if necessary. */
 
246
    if (delta_time(now, whitelist_checked) > WHITELIST_CHECK_INTERVAL) {
 
247
        struct stat st;
 
248
 
 
249
        whitelist_checked = now;
 
250
 
 
251
        if (NULL != whitelist_path && 0 == stat(whitelist_path, &st)) {
 
252
            if (st.st_mtime != whitelist_mtime) {
 
253
                g_warning("whitelist_check(): "
 
254
                                        "Whitelist changed on disk. Reloading.");
 
255
                whitelist_reload();
 
256
            }
 
257
        }
 
258
    }
 
259
 
 
260
    for (sl = sl_whitelist; sl; sl = g_slist_next(sl)) {
 
261
        n = sl->data;
 
262
        if ((ip & n->netmask) == (n->ip & n->netmask))
 
263
            return TRUE;
 
264
    }
 
265
 
 
266
    return FALSE;
 
267
}
 
268
 
 
269
/* vi: set ts=4: */