IPv6: Use source-routing to allow multi-wan
[project/netifd.git] / utils.c
1 /*
2  * netifd - network interface daemon
3  * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14 #include <string.h>
15 #include <stdlib.h>
16 #include "utils.h"
17
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
20
21 void
22 __vlist_simple_init(struct vlist_simple_tree *tree, int offset)
23 {
24         INIT_LIST_HEAD(&tree->list);
25         tree->version = 1;
26         tree->head_offset = offset;
27 }
28
29 void
30 vlist_simple_delete(struct vlist_simple_tree *tree, struct vlist_simple_node *node)
31 {
32         char *ptr;
33
34         list_del(&node->list);
35         ptr = (char *) node - tree->head_offset;
36         free(ptr);
37 }
38
39 void
40 vlist_simple_flush(struct vlist_simple_tree *tree)
41 {
42         struct vlist_simple_node *n, *tmp;
43
44         list_for_each_entry_safe(n, tmp, &tree->list, list) {
45                 if ((n->version == tree->version || n->version == -1) &&
46                     tree->version != -1)
47                         continue;
48
49                 vlist_simple_delete(tree, n);
50         }
51 }
52
53 void
54 vlist_simple_replace(struct vlist_simple_tree *dest, struct vlist_simple_tree *old)
55 {
56         struct vlist_simple_node *n, *tmp;
57
58         vlist_simple_update(dest);
59         list_for_each_entry_safe(n, tmp, &old->list, list) {
60                 list_del(&n->list);
61                 vlist_simple_add(dest, n);
62         }
63         vlist_simple_flush(dest);
64 }
65
66 void
67 vlist_simple_flush_all(struct vlist_simple_tree *tree)
68 {
69         tree->version = -1;
70         vlist_simple_flush(tree);
71 }
72
73 unsigned int
74 parse_netmask_string(const char *str, bool v6)
75 {
76         struct in_addr addr;
77         unsigned int ret;
78         char *err = NULL;
79
80         if (!strchr(str, '.')) {
81                 ret = strtoul(str, &err, 0);
82                 if (err && *err)
83                         goto error;
84
85                 return ret;
86         }
87
88         if (v6)
89                 goto error;
90
91         if (inet_aton(str, &addr) != 1)
92                 goto error;
93
94         return 32 - fls(~(ntohl(addr.s_addr)));
95
96 error:
97         return ~0;
98 }
99
100 bool
101 split_netmask(char *str, unsigned int *netmask, bool v6)
102 {
103         char *delim = strchr(str, '/');
104
105         if (delim) {
106                 *(delim++) = 0;
107
108                 *netmask = parse_netmask_string(delim, v6);
109         }
110         return true;
111 }
112
113 int
114 parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask)
115 {
116         char *astr = alloca(strlen(str) + 1);
117
118         strcpy(astr, str);
119         if (!split_netmask(astr, netmask, af == AF_INET6))
120                 return 0;
121
122         if (af == AF_INET6) {
123                 if (*netmask > 128)
124                         return 0;
125         } else {
126                 if (*netmask > 32)
127                         return 0;
128         }
129
130         return inet_pton(af, astr, addr);
131 }
132
133 char *
134 format_macaddr(uint8_t *mac)
135 {
136         static char str[sizeof("ff:ff:ff:ff:ff:ff ")];
137
138         snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
139                  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
140
141         return str;
142 }
143
144 uint32_t
145 crc32_file(FILE *fp)
146 {
147         static uint32_t *crcvals = NULL;
148         if (!crcvals) {
149                 crcvals = malloc(sizeof(*crcvals) * 256);
150
151                 for (size_t i = 0; i < 256; ++i) {
152                         uint32_t c = i;
153                         for (size_t j = 0; j < 8; ++j)
154                                 c = (c & 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1);
155                         crcvals[i] = c;
156                 }
157         }
158
159         uint8_t buf[1024];
160         size_t len;
161         uint32_t c = 0xFFFFFFFF;
162
163         do {
164                 len = fread(buf, 1, sizeof(buf), fp);
165                 for (size_t i = 0; i < len; ++i)
166                         c = crcvals[(c ^ buf[i]) & 0xFF] ^ (c >> 8);
167         } while (len == sizeof(buf));
168
169         return c ^ 0xFFFFFFFF;
170 }