*Very Exprimental*
[handlervirt.git] / experiment5.c
bloba40be9af585cfcfd57046f090ccdc1a7a86105f4
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <sys/file.h>
7 typedef struct line LINE;
9 struct line {
10 unsigned long int mac;
11 unsigned long int ip;
12 char *fqdn;
13 LINE *next;
16 LINE *first = NULL;
17 LINE *last = NULL;
18 LINE *array = NULL;
20 int listlen = 0;
22 /* Removes an entry from our linked list */
24 static int remove_entry(unsigned long int mac) {
25 LINE *step = first;
26 LINE *prev = NULL;
27 while (step) {
28 LINE *next = step->next;
30 if (step->mac == mac) {
31 if (step->fqdn)
32 free(step->fqdn);
34 if (prev)
35 prev->next = next;
36 free(step);
39 prev = step;
40 step = next;
43 return 0;
46 /* Adds an entry to the linked list */
48 static int add_entry(unsigned long int mac, unsigned long int ip, char *fqdn) {
49 LINE *new = malloc(sizeof(LINE));
50 new->mac = mac;
51 new->ip = ip;
52 new->fqdn = strdup(fqdn);
53 new->next = NULL;
55 if (!first)
56 first = new;
57 else
58 last->next = new;
60 last = new;
62 return 0;
65 /* Converts a MA:CA:DD:RE:SS:00 to an unsigned long int */
67 static unsigned long int macstrtoul(char *mac) {
68 char macstring[4];
69 macstring[2] = '\0';
70 macstring[3] = '\0';
72 unsigned long int newmac = 0;
73 strncpy(macstring, &mac[9], 2);
74 newmac += (strtoul(macstring, NULL, 16) * (unsigned long int)(256 * 256));
75 strncpy(macstring, &mac[12], 2);
76 newmac += (strtoul(macstring, NULL, 16) * (unsigned long int)(256));
77 strncpy(macstring, &mac[15], 2);
78 newmac += (strtoul(macstring, NULL, 16));
80 return newmac;
83 /* Parses a line from the file and adds it to the linked list */
85 static int add_line(char *line) {
86 if (strncmp(line, "dhcp-host=", 10) == 0 &&
87 line[12] == ':' && line[15] == ':' && line[18] == ':' && line[21] == ':' && line[24] == ':' &&
88 line[27] == ',') {
89 char *ip, *nextip;
90 char macstring[4];
91 LINE *new = malloc(sizeof(LINE));
93 if (new == NULL) return -1;
95 listlen++;
96 macstring[2] = '\0';
97 macstring[3] = '\0';
99 new->mac = 0;
100 new->ip = 0;
101 new->next= NULL;
103 new->mac = macstrtoul(&line[10]);
105 ip = strchr(&line[28], ',');
106 new->fqdn = strndup(&line[28], ip - &line[28]);
107 ip++;
109 macstring[1] = '\0'; macstring[2] = '\0';
110 strncpy(macstring, ip, (nextip = strchr(ip, '.')) - ip);
111 new->ip += (strtoul(macstring, NULL, 10) * (unsigned long int)(256 * 256 * 256));
112 ip = nextip + 1;
114 macstring[1] = '\0'; macstring[2] = '\0';
115 strncpy(macstring, ip, (nextip = strchr(ip, '.')) - ip);
116 new->ip += (strtoul(macstring, NULL, 10) * (unsigned long int)(256 * 256));
117 ip = nextip + 1;
119 macstring[1] = '\0'; macstring[2] = '\0';
120 strncpy(macstring, ip, (nextip = strchr(ip, '.')) - ip);
121 new->ip += (strtoul(macstring, NULL, 10) * (unsigned long int)(256));
122 ip = nextip + 1;
124 macstring[1] = '\0'; macstring[2] = '\0';
125 strncpy(macstring, ip, (nextip = strchr(ip, ',')) - ip);
126 new->ip += (strtoul(macstring, NULL, 10));
128 if (!first)
129 first = new;
130 else
131 last->next = new;
133 last = new;
135 return 0;
138 return -1;
141 /* Prints out our mac range */
143 static char * print_mac(unsigned long int mac) {
144 char *macstring = (char *) malloc(sizeof(char*) * 18);
145 strcpy(macstring, "00:16:3E:");
146 snprintf(&macstring[9], 8, "%06lX", mac);
147 strncpy(&macstring[15], &macstring[13], 2);
148 macstring[13] = macstring[12];
149 macstring[12] = macstring[11];
150 macstring[11] = ':';
151 macstring[14] = ':';
152 macstring[17] = '\0';
153 return macstring;
156 /* And prints out an ip address */
158 static char * print_ip(unsigned long int ipaddress) {
159 char *dest = (char *) malloc(sizeof(char*) * 16);
160 int a, b, c, d;
161 ldiv_t ip = ldiv(ipaddress, (256*256*256));
162 a = ip.quot;
163 ip = ldiv(ip.rem, (256*256));
164 b = ip.quot;
165 ip = ldiv(ip.rem, (256));
166 c = ip.quot;
167 d = ip.rem;
169 snprintf(dest, 16, "%d.%d.%d.%d", a, b, c, d);
170 return dest;
173 /* Print out the dnsmasq format and clean up the linked list */
175 static int print_forget(char *path) {
176 FILE *fd = fopen(path, "w+");
178 LINE *step = first;
179 while (step) {
180 LINE *this = step;
181 char *pretty_mac = print_mac(this->mac);
182 char *pretty_ip = print_ip(this->ip);
184 if (fd)
185 fprintf(fd, "dhcp-host=%s,%s,%s,24h\n", pretty_mac, this->fqdn, pretty_ip);
187 free(pretty_mac);
188 free(pretty_ip);
190 free(this->fqdn);
192 step = this->next;
193 free(this);
196 if (fd)
197 fclose(fd);
199 return 0;
202 /* Convert the linked list to a more 'defacto' array format */
204 static int ll_array() {
205 int i = 0;
206 array = malloc(sizeof(LINE) * listlen);
208 LINE *step = first;
209 while (step) {
210 array[i].mac = step->mac;
211 array[i].ip = step->ip;
212 array[i].fqdn = step->fqdn;
213 step = step->next;
214 i++;
217 return 0;
220 /* Compare functions */
222 static int bymac(const void *a, const void *b) {
223 LINE *temp1 = (LINE *) a;
224 LINE *temp2 = (LINE *) b;
226 return temp1->mac - temp2->mac;
229 static int byip(const void *a, const void *b) {
230 LINE *temp1 = (LINE *) a;
231 LINE *temp2 = (LINE *) b;
233 return temp1->ip - temp2->ip;
236 /* Find the first 'free' mac */
238 static unsigned long int nextmac() {
239 int i;
240 for (i = 0; i < (listlen - 1); i++) {
241 if (array[i+1].mac != 0 && array[i+1].mac != array[i].mac + 1) return array[i].mac + 1;
243 return array[listlen - 1].mac + 1;
246 /* Find the first 'free' ip */
247 static unsigned long int nextip() {
248 int i;
249 for (i = 0; i < (listlen - 1); i++) {
250 if (array[i+1].ip != array[i].ip + 1) return array[i].ip + 1;
252 return array[listlen - 1].ip + 1;
255 /* Opens the cabinet config */
257 static char * loader(char *cabinet) {
258 FILE *fd;
259 char *pad = malloc(sizeof(char) * 128);
261 listlen = 0;
262 first = NULL;
263 last = NULL;
264 array = NULL;
266 if (pad == NULL) return NULL;
268 snprintf(pad, 128, "/mnt/netapp/ipservices/%s.conf", cabinet);
270 if ((fd = fopen(pad, "r")) != NULL) {
271 char line[128];
272 while (!feof(fd)) {
273 if (fgets(line, 128, fd) > 0)
274 add_line(line);
276 fclose(fd);
279 return pad;
282 /* Exported functions */
283 /* TODO: implement better locking */
285 int removeOldMac(char *cabinet, char *mac) {
286 char *pad = loader(cabinet);
288 if (pad == NULL)
289 return -1;
291 unsigned long int old_mac = macstrtoul(mac);
292 remove_entry(old_mac);
293 print_forget(pad);
294 free(pad);
295 return 0;
299 int getNewMac(char *cabinet, char *fqdn, char **mac, char **ip) {
300 unsigned long int new_mac, new_ip;
301 char *pad = loader(cabinet);
303 if (pad == NULL)
304 return -1;
306 if (listlen == 0) {
307 new_mac = 0;
308 new_ip = 0;
309 } else {
310 ll_array();
312 qsort(array, listlen, sizeof(LINE), bymac);
313 new_mac = nextmac();
315 qsort(array, listlen, sizeof(LINE), byip);
316 new_ip = nextip();
319 if (mac)
320 *mac = print_mac(new_mac);
322 if (ip)
323 *ip = print_ip(new_ip);
325 add_entry(new_mac, new_ip, fqdn);
327 free(array);
329 print_forget(pad);
331 free(pad);
333 return 0;
336 /* Good for unittesting */
338 #ifdef WITH_MAIN
339 int main(int argc, char *argv[]) {
340 if (argc == 4) {
341 removeOldMac(argv[1], argv[2]);
342 } else if (argc == 3) {
343 getNewMac(argv[1], argv[2], NULL, NULL);
345 return 0;
347 #endif