root/branches/batctl-0.2.x/bat-hosts.c @ 1592

Revision 1592, 5.8 kB (checked in by marek, 6 months ago)

batctl: fix typos in error messages

Line 
1/*
2 * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
3 *
4 * Andreas Langer <a.langer@q-dsl.de>, Marek Lindner <lindner_marek@yahoo.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22
23
24#define _GNU_SOURCE
25#include <stdio.h>
26#include <stdint.h>
27#include <limits.h>
28#include <stdlib.h>
29#include <errno.h>
30#include <string.h>
31
32#include "main.h"
33#include "bat-hosts.h"
34#include "hash.h"
35
36
37static struct hashtable_t *host_hash = NULL;
38const char *bat_hosts_path[3] = {"/etc/bat-hosts", "~/bat-hosts", "bat-hosts"};
39
40
41static int compare_mac(void *data1, void *data2)
42{
43        return (memcmp(data1, data2, sizeof(struct ether_addr)) == 0 ? 1 : 0);
44}
45
46static int choose_mac(void *data, int32_t size)
47{
48        unsigned char *key= data;
49        uint32_t hash = 0, m_size = sizeof(struct ether_addr);
50        size_t i;
51
52        for (i = 0; i < m_size; i++) {
53                hash += key[i];
54                hash += (hash << 10);
55                hash ^= (hash >> 6);
56        }
57
58        hash += (hash << 3);
59        hash ^= (hash >> 11);
60        hash += (hash << 15);
61
62        return (hash % size);
63}
64
65static void parse_hosts_file(struct hashtable_t **hash, const char path[])
66{
67        FILE *fd;
68        char *line_ptr = NULL;
69        char name[HOST_NAME_MAX_LEN], mac_str[18];
70        struct ether_addr *mac_addr;
71        struct bat_host *bat_host;
72        struct hashtable_t *swaphash;
73        size_t len = 0;
74
75        name[0] = mac_str[0] = '\0';
76
77        fd = fopen(path, "r");
78        if (!fd)
79                return;
80
81        while (getline(&line_ptr, &len, fd) != -1) {
82                /* ignore empty lines and comments */
83                if ((line_ptr[0] == '\n') || (line_ptr[0] == '#'))
84                        continue;
85
86                if (sscanf(line_ptr, "%17[^ \t]%49s\n", mac_str, name) != 2) {
87                        fprintf(stderr, "Warning - unrecognized bat-host definition: %s", line_ptr);
88                        continue;
89                }
90
91                mac_addr = ether_aton(mac_str);
92                if (!mac_addr) {
93                        fprintf(stderr, "Warning - invalid mac address in '%s' detected: %s\n", path, mac_str);
94                        continue;
95                }
96
97                bat_host = bat_hosts_find_by_mac((char *)mac_addr);
98
99                /* mac entry already exists - we found a new name for it */
100                if (bat_host) {
101                        fprintf(stderr, "Warning - mac already known (changing name from '%s' to '%s'): %s\n",
102                                        bat_host->name, name, mac_str);
103                        strncpy(bat_host->name, name, HOST_NAME_MAX_LEN - 1);
104                        continue;
105                }
106
107                bat_host = bat_hosts_find_by_name(name);
108
109                /* name entry already exists - we found a new mac address for it */
110                if (bat_host) {
111                        fprintf(stderr, "Warning - name already known (changing mac from '%s' to '%s'): %s\n",
112                                        ether_ntoa(&bat_host->mac_addr), mac_str, name);
113                        hash_remove(*hash, bat_host);
114                        free(bat_host);
115                }
116
117                bat_host = malloc(sizeof(struct bat_host));
118
119                if (!bat_host) {
120                        fprintf(stderr, "Error - could not allocate memory: %s\n", strerror(errno));
121                        goto out;
122                }
123
124                memcpy(&bat_host->mac_addr, mac_addr, sizeof(struct ether_addr));
125                strncpy(bat_host->name, name, HOST_NAME_MAX_LEN - 1);
126
127                hash_add(*hash, bat_host);
128
129                if ((*hash)->elements * 4 > (*hash)->size) {
130                        swaphash = hash_resize((*hash), (*hash)->size * 2);
131
132                        if (swaphash == NULL)
133                                fprintf(stderr, "Warning - couldn't resize bat hosts hash table\n");
134                        else
135                                *hash = swaphash;
136                }
137        }
138
139out:
140        if (fd)
141                fclose(fd);
142        if (line_ptr)
143                free(line_ptr);
144        return;
145}
146
147void bat_hosts_init(void)
148{
149        unsigned int i, j, parse;
150        char confdir[CONF_DIR_LEN];
151        char *homedir;
152        size_t locations = sizeof(bat_hosts_path) / sizeof(char *);
153        char *normalized;
154
155        /***
156         * realpath could allocate the memory for us but some embedded libc
157         * implementations seem to expect a buffer as second argument
158         */
159        normalized = malloc(locations * PATH_MAX);
160        if (!normalized) {
161                printf("Warning - could not get memory for bat-hosts file parsing\n");
162                return;
163        }
164
165        memset(normalized, 0, locations * PATH_MAX);
166        host_hash = hash_new(64, compare_mac, choose_mac);
167
168        if (!host_hash) {
169                printf("Warning - could not create bat hosts hash table\n");
170                return;
171        }
172
173        homedir = getenv("HOME");
174
175        for (i = 0; i < locations; i++) {
176                strcpy(confdir, "");
177
178                if (strlen(bat_hosts_path[i]) >= 2
179                    && bat_hosts_path[i][0] == '~' && bat_hosts_path[i][1] == '/') {
180                        strncpy(confdir, homedir, CONF_DIR_LEN);
181                        confdir[CONF_DIR_LEN - 1] = '\0';
182                        strncat(confdir, &bat_hosts_path[i][1], CONF_DIR_LEN - strlen(confdir));
183                } else {
184                        strncpy(confdir, bat_hosts_path[i], CONF_DIR_LEN);
185                        confdir[CONF_DIR_LEN - 1] = '\0';
186                }
187
188                if (!realpath(confdir, normalized + (i * PATH_MAX)))
189                        continue;
190
191                /* check for duplicates: don't parse the same file twice */
192                parse = 1;
193                for (j = 0; j < i; j++) {
194                        if (strncmp(normalized + (i * PATH_MAX), normalized + (j * PATH_MAX), CONF_DIR_LEN) == 0) {
195                                parse = 0;
196                                break;
197                        }
198                }
199
200                if (parse)
201                        parse_hosts_file(&host_hash, normalized + (i * PATH_MAX));
202        }
203
204        free(normalized);
205}
206
207struct bat_host *bat_hosts_find_by_name(char *name)
208{
209        struct hash_it_t *hashit = NULL;
210        struct bat_host *bat_host = NULL, *tmp_bat_host;
211
212        if (!host_hash)
213                return NULL;
214
215        while (NULL != (hashit = hash_iterate(host_hash, hashit))) {
216                tmp_bat_host = (struct bat_host *)hashit->bucket->data;
217
218                if (strncmp(tmp_bat_host->name, name, HOST_NAME_MAX_LEN - 1) == 0)
219                        bat_host = tmp_bat_host;
220        }
221
222        return bat_host;
223}
224
225struct bat_host *bat_hosts_find_by_mac(char *mac)
226{
227        if (!host_hash)
228                return NULL;
229
230        return (struct bat_host *)hash_find(host_hash, mac);
231}
232
233static void bat_host_free(void *data)
234{
235        free(data);
236}
237
238void bat_hosts_free(void)
239{
240        if (host_hash)
241                hash_delete(host_hash, bat_host_free);
242}
Note: See TracBrowser for help on using the browser.