]> git.proxmox.com Git - ifupdown-pve.git/blame - archcommon.c
Squashed 'src/' content from commit c732260
[ifupdown-pve.git] / archcommon.c
CommitLineData
6f248ce1
TL
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/utsname.h>
6#include <sys/stat.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <arpa/inet.h>
11#include <err.h>
12
13#include "archcommon.h"
14
15bool _iface_has(const char *iface, const char *delims) {
16 char _iface[80];
17
18 strncpy(_iface, iface, sizeof(_iface));
19 _iface[sizeof(_iface) - 1] = 0;
20 strtok(_iface, delims);
21 void *token = strtok(NULL, delims);
22
23 return (token != NULL);
24}
25
26bool execable(const char *program) {
27 struct stat buf;
28
29 if (0 == stat(program, &buf))
30 if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode))
31 return true;
32
33 return false;
34}
35
36void cleanup_hwaddress(interface_defn *ifd, char **pparam, int argc, char **argv) {
37 /* replace "random" with a random MAC address */
38 if (strcmp(*pparam, "random") == 0) {
39 uint8_t mac[6];
40 int fd = open("/dev/urandom", O_RDONLY);
41 if(!fd) {
42 warn("/dev/urandom");
43 return;
44 }
45 if(read(fd, mac, sizeof mac) != sizeof mac) {
46 warn("/dev/urandom");
47 return;
48 }
49 close(fd);
50 mac[0] |= 0x2; // locally administered
51 mac[0] &= ~0x1; // unicast
52 *pparam = realloc(*pparam, 18);
53 if (!*pparam)
54 err(1, "realloc");
55 snprintf(*pparam, 18, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
56 return;
57 }
58
59 char *rest = *pparam;
60
61 /* we're shrinking the text, so no realloc needed */
62 char *space = strchr(rest, ' ');
63 if (space == NULL)
64 return;
65 *space = '\0';
66
67 if (strcasecmp(rest, "ether") == 0 || strcasecmp(rest, "ax25") == 0 || strcasecmp(rest, "ARCnet") == 0 || strcasecmp(rest, "netrom") == 0)
68 /* found deprecated <class> attribute */
69 memmove(rest, space + 1, strlen(space + 1) + 1);
70 else
71 *space = ' ';
72}
73
74void make_hex_address(interface_defn *ifd, char **pparam, int argc, char **argv) {
75 char addrcomp[4];
76 int maxlen = strlen("0000:0000");
77
78 int ret = sscanf(*pparam, "%3hhu.%3hhu.%3hhu.%3hhu", &addrcomp[0], &addrcomp[1], &addrcomp[2], &addrcomp[3]);
79 if (ret != 4)
80 return;
81
82 *pparam = realloc(*pparam, maxlen + 1);
83 if (*pparam == NULL)
84 return;
85 snprintf(*pparam, maxlen + 1, "%.2hhx%.2hhx:%.2hhx%.2hhx", addrcomp[0], addrcomp[1], addrcomp[2], addrcomp[3]);
86}
87
88void compute_v4_addr(interface_defn *ifd, char **pparam, int argc, char **argv) {
89 char s[INET_ADDRSTRLEN * 2 + 2]; /* 2 is for slash and \0 */
90
91 strncpy(s, *pparam, sizeof(s));
92 s[sizeof(s) - 1] = 0;
93
94 char *token = strtok(s, "/");
95 if (!token)
96 return;
97
98 *pparam = realloc(*pparam, strlen(token) + 1);
99 if (*pparam == NULL)
100 return;
101 strcpy(*pparam, token);
102}
103
104void compute_v4_mask(interface_defn *ifd, char **pparam, int argc, char **argv) {
105 char s[INET_ADDRSTRLEN * 2 + 2]; /* 2 is for slash and \0 */
106
107 strncpy(s, *pparam, sizeof(s));
108 s[sizeof(s) - 1] = 0;
109
110 char *token = strtok(s, "/");
111 if (!token)
112 return;
113
114 uint8_t addr[sizeof(struct in_addr)];
115 struct in_addr mask;
116
117 if (inet_pton(AF_INET, token, &addr) != 1)
118 return;
119
120 token = strtok(NULL, "/");
121 int maskwidth = -1;
122
123 if (!token) {
124 if (addr[0] <= 127)
125 maskwidth = 8;
126 else if ((addr[0] >= 128) && (addr[0] <= 191))
127 maskwidth = 16;
128 else if ((addr[0] >= 192) && (addr[0] <= 223))
129 maskwidth = 24;
130 else
131 maskwidth = 32;
132 } else {
133 switch (inet_pton(AF_INET, token, &mask)) {
134 case -1:
135 return;
136
137 case 0:
138 if (sscanf(token, "%d", &maskwidth) != 1)
139 return;
140 }
141 }
142
143 if (maskwidth != -1)
144 mask.s_addr = htonl(~((1L << (32 - maskwidth)) - 1));
145
146 if (inet_ntop(AF_INET, &mask, s, sizeof(s)) == NULL)
147 return;
148
149 *pparam = realloc(*pparam, strlen(s) + 1);
150 if (*pparam == NULL)
151 return;
152 strcpy(*pparam, s);
153}
154
155void compute_v4_broadcast(interface_defn *ifd, char **pparam, int argc, char **argv) {
156 /* If we don't get special value don't do anything */
157 if (strcmp(*pparam, "+") && strcmp(*pparam, "-"))
158 return;
159
160 struct in_addr addr;
161 struct in_addr mask;
162
163 char *s = get_var("address", strlen("address"), ifd);
164 if (!s)
165 return;
166
167 int r = inet_pton(AF_INET, s, &addr);
168 free(s);
169 if (r != 1)
170 return;
171
172 s = get_var("netmask", strlen("netmask"), ifd);
173 if (!s)
174 return;
175
176 r = inet_pton(AF_INET, s, &mask);
177 free(s);
178 if (r != 1)
179 return;
180
181 if (mask.s_addr != htonl(0xfffffffe)) {
182 if (!strcmp(*pparam, "+"))
183 addr.s_addr |= ~mask.s_addr;
184
185 if (!strcmp(*pparam, "-"))
186 addr.s_addr &= mask.s_addr;
187 } else {
188 if (!strcmp(*pparam, "+"))
189 addr.s_addr = 0xffffffff;
190
191 if (!strcmp(*pparam, "-"))
192 addr.s_addr = 0;
193 }
194
195 char buffer[INET_ADDRSTRLEN + 1];
196
197 if (inet_ntop(AF_INET, &addr, buffer, sizeof(buffer)) == NULL)
198 return;
199
200 *pparam = realloc(*pparam, strlen(buffer) + 1);
201 if (*pparam == NULL)
202 return;
203 strcpy(*pparam, buffer);
204}
205
206void set_preferred_lft(interface_defn *ifd, char **pparam, int argc, char **argv) {
207 if (!ifd->real_iface)
208 return;
209
210 if (iface_has(":")) {
211 char s[] = "0";
212
213 *pparam = realloc(*pparam, sizeof(s));
214 if (*pparam == NULL)
215 return;
216 strcpy(*pparam, s);
217 }
218}
219
220void get_token(interface_defn *ifd, char **pparam, int argc, char **argv) {
221 if (argc < 1)
222 return;
223
224 int token_no = 0;
225
226 if (argc > 1)
227 token_no = atoi(argv[1]);
228
229 char *s = strdup(*pparam);
230 char *token = strtok(s, argv[0]);
231
232 while (token_no > 0) {
233 token = strtok(NULL, argv[0]);
234 token_no--;
235 }
236
237 if (token) {
238 strcpy(*pparam, token);
239 } else {
240 if (argc == 3) {
241 free(*pparam);
242 *pparam = strdup(argv[2]);
243 if (!*pparam)
244 err(1, "strdup");
245 }
246 }
247
248 free(s);
249}
250
251void to_decimal(interface_defn *ifd, char **pparam, int argc, char **argv) {
252 int base = 10;
253
254 if (argc > 0)
255 base = atoi(argv[0]);
256
257 char *result;
258 long value = strtol(*pparam, &result, base);
259
260 if (result == *pparam)
261 return;
262
263 snprintf(*pparam, strlen(*pparam) + 1, "%ld", value);
264}
265
266void map_value(interface_defn *ifd, char **pparam, int argc, char **argv) {
267 if (argc < 2)
268 return;
269
270 int value = (atoi(*pparam) || strcasecmp(*pparam, "on") == 0 || strcasecmp(*pparam, "true") == 0 || strcasecmp(*pparam, "yes") == 0);
271
272 if ((value < argc) && (argv[value] != NULL)) {
273 *pparam = realloc(*pparam, strlen(argv[value]) + 1);
274 if (*pparam == NULL)
275 return;
276 strcpy(*pparam, argv[value]);
277 } else {
278 *pparam = realloc(*pparam, 1);
279 if (*pparam == NULL)
280 return;
281 *pparam[0] = 0;
282 }
283}
284
285void if_set(interface_defn *ifd, char **pparam, int argc, char **argv) {
286 if (argc < 1)
287 return;
288
289 *pparam = realloc(*pparam, strlen(argv[0]) + 1);
290 if (*pparam == NULL)
291 return;
292 strcpy(*pparam, argv[0]);
293}