Something that should look as if it did locking...
[handlervirt.git] / experiment5.c
blob927e366453d71c7f48dd475a1a9ad47e408297d5
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
6 typedef struct line LINE;
8 struct line {
9 unsigned long int mac;
10 unsigned long int ip;
11 char *fqdn;
12 LINE *next;
15 LINE *first = NULL;
16 LINE *last = NULL;
17 LINE *array = NULL;
19 int listlen = 0;
21 /* Removes an entry from our linked list */
23 static int remove_entry(unsigned long int mac) {
24 LINE *step = first;
25 LINE *prev = NULL;
26 while (step) {
27 LINE *next = step->next;
29 if (step->mac == mac) {
30 if (step->fqdn)
31 free(step->fqdn);
33 if (prev)
34 prev->next = next;
35 free(step);
38 prev = step;
39 step = next;
42 return 0;
45 /* Adds an entry to the linked list */
47 static int add_entry(unsigned long int mac, unsigned long int ip, char *fqdn) {
48 LINE *new = malloc(sizeof(LINE));
49 new->mac = mac;
50 new->ip = ip;
51 new->fqdn = strdup(fqdn);
52 new->next = NULL;
54 if (!first)
55 first = new;
56 else
57 last->next = new;
59 last = new;
61 return 0;
64 /* Converts a MA:CA:DD:RE:SS:00 to an unsigned long int */
66 static unsigned long int macstrtoul(char *mac) {
67 char macstring[4];
68 macstring[2] = '\0';
69 macstring[3] = '\0';
71 unsigned long int newmac = 0;
72 strncpy(macstring, &mac[9], 2);
73 newmac += (strtoul(macstring, NULL, 16) * (unsigned long int)(256 * 256));
74 strncpy(macstring, &mac[12], 2);
75 newmac += (strtoul(macstring, NULL, 16) * (unsigned long int)(256));
76 strncpy(macstring, &mac[15], 2);
77 newmac += (strtoul(macstring, NULL, 16));
79 return newmac;
82 /* Parses a line from the file and adds it to the linked list */
84 static int add_line(char *line) {
85 if (strncmp(line, "dhcp-host=", 10) == 0 &&
86 line[12] == ':' && line[15] == ':' && line[18] == ':' && line[21] == ':' && line[24] == ':' &&
87 line[27] == ',') {
88 char *ip, *nextip;
89 char macstring[4];
90 LINE *new = malloc(sizeof(LINE));
92 if (new == NULL) return -1;
94 listlen++;
95 macstring[2] = '\0';
96 macstring[3] = '\0';
98 new->mac = 0;
99 new->ip = 0;
100 new->next= NULL;
102 new->mac = macstrtoul(&line[10]);
104 ip = strchr(&line[28], ',');
105 new->fqdn = strndup(&line[28], ip - &line[28]);
106 ip++;
108 macstring[1] = '\0'; macstring[2] = '\0';
109 strncpy(macstring, ip, (nextip = strchr(ip, '.')) - ip);
110 new->ip += (strtoul(macstring, NULL, 10) * (unsigned long int)(256 * 256 * 256));
111 ip = nextip + 1;
113 macstring[1] = '\0'; macstring[2] = '\0';
114 strncpy(macstring, ip, (nextip = strchr(ip, '.')) - ip);
115 new->ip += (strtoul(macstring, NULL, 10) * (unsigned long int)(256 * 256));
116 ip = nextip + 1;
118 macstring[1] = '\0'; macstring[2] = '\0';
119 strncpy(macstring, ip, (nextip = strchr(ip, '.')) - ip);
120 new->ip += (strtoul(macstring, NULL, 10) * (unsigned long int)(256));
121 ip = nextip + 1;
123 macstring[1] = '\0'; macstring[2] = '\0';
124 strncpy(macstring, ip, (nextip = strchr(ip, ',')) - ip);
125 new->ip += (strtoul(macstring, NULL, 10));
127 if (!first)
128 first = new;
129 else
130 last->next = new;
132 last = new;
134 return 0;
137 return -1;
140 /* Prints out our mac range */
142 static char * print_mac(unsigned long int mac) {
143 char *macstring = (char *) malloc(sizeof(char*) * 18);
144 strcpy(macstring, "00:16:3E:");
145 snprintf(&macstring[9], 8, "%06lX", mac);
146 strncpy(&macstring[15], &macstring[13], 2);
147 macstring[13] = macstring[12];
148 macstring[12] = macstring[11];
149 macstring[11] = ':';
150 macstring[14] = ':';
151 macstring[17] = '\0';
152 return macstring;
155 /* And prints out an ip address */
157 static char * print_ip(unsigned long int ipaddress) {
158 char *dest = (char *) malloc(sizeof(char*) * 16);
159 int a, b, c, d;
160 ldiv_t ip = ldiv(ipaddress, (256*256*256));
161 a = ip.quot;
162 ip = ldiv(ip.rem, (256*256));
163 b = ip.quot;
164 ip = ldiv(ip.rem, (256));
165 c = ip.quot;
166 d = ip.rem;
168 snprintf(dest, 16, "%d.%d.%d.%d", a, b, c, d);
169 return dest;
172 /* Print out the dnsmasq format and clean up the linked list */
174 static int print_forget(char *path) {
175 FILE *fd = fopen(path, "w+");
177 if (fd)
178 flock(fd, LOCK_EX);
180 LINE *step = first;
181 while (step) {
182 LINE *this = step;
183 char *pretty_mac = print_mac(this->mac);
184 char *pretty_ip = print_ip(this->ip);
186 if (fd)
187 fprintf(fd, "dhcp-host=%s,%s,%s,24h\n", pretty_mac, this->fqdn, pretty_ip);
189 free(pretty_mac);
190 free(pretty_ip);
192 free(this->fqdn);
194 step = this->next;
195 free(this);
198 if (fd) {
199 flock(fd, LOCK_UN);
200 fclose(fd);
203 return 0;
206 /* Convert the linked list to a more 'defacto' array format */
208 static int ll_array() {
209 int i = 0;
210 array = malloc(sizeof(LINE) * listlen);
212 LINE *step = first;
213 while (step) {
214 array[i].mac = step->mac;
215 array[i].ip = step->ip;
216 array[i].fqdn = step->fqdn;
217 step = step->next;
218 i++;
221 return 0;
224 /* Compare functions */
226 static int bymac(const void *a, const void *b) {
227 LINE *temp1 = (LINE *) a;
228 LINE *temp2 = (LINE *) b;
230 return temp1->mac - temp2->mac;
233 static int byip(const void *a, const void *b) {
234 LINE *temp1 = (LINE *) a;
235 LINE *temp2 = (LINE *) b;
237 return temp1->ip - temp2->ip;
240 /* Find the first 'free' mac */
242 static unsigned long int nextmac() {
243 int i;
244 for (i = 0; i < (listlen - 1); i++) {
245 if (array[i+1].mac != 0 && array[i+1].mac != array[i].mac + 1) return array[i].mac + 1;
247 return array[listlen - 1].mac + 1;
250 /* Find the first 'free' ip */
251 static unsigned long int nextip() {
252 int i;
253 for (i = 0; i < (listlen - 1); i++) {
254 if (array[i+1].ip != array[i].ip + 1) return array[i].ip + 1;
256 return array[listlen - 1].ip + 1;
259 /* Opens the cabinet config */
261 static char * loader(char *cabinet) {
262 FILE *fd;
263 char *pad = malloc(sizeof(char) * 128);
265 listlen = 0;
266 first = NULL;
267 last = NULL;
268 array = NULL;
270 if (pad == NULL) return NULL;
272 snprintf(pad, 128, "/mnt/netapp/ipservices/%s.conf", cabinet);
274 if ((fd = fopen(pad, "r")) != NULL) {
275 char line[128];
276 flock(fd, LOCK_EX);
277 while (!feof(fd)) {
278 if (fgets(line, 128, fd) > 0)
279 add_line(line);
281 flock(fd, LOCK_UN);
282 fclose(fd);
285 return pad;
288 /* Exported functions */
290 int removeOldMac(char *cabinet, char *mac) {
291 char *pad = loader(cabinet);
293 if (pad == NULL)
294 return -1;
296 unsigned long int old_mac = macstrtoul(mac);
297 remove_entry(old_mac);
298 print_forget(pad);
299 free(pad);
303 int getNewMac(char *cabinet, char *fqdn, char **mac, char **ip) {
304 unsigned long int new_mac, new_ip;
305 char *pad = loader(cabinet);
307 if (pad == NULL)
308 return -1;
310 if (listlen == 0) {
311 new_mac = 0;
312 new_ip = 0;
313 } else {
314 ll_array();
316 qsort(array, listlen, sizeof(LINE), bymac);
317 new_mac = nextmac();
319 qsort(array, listlen, sizeof(LINE), byip);
320 new_ip = nextip();
323 if (mac)
324 *mac = print_mac(new_mac);
326 if (ip)
327 *ip = print_ip(new_ip);
329 add_entry(new_mac, new_ip, fqdn);
331 free(array);
333 print_forget(pad);
335 free(pad);
337 return 0;
340 /* Good for unittesting */
342 #ifdef WITH_MAIN
343 int main(int argc, char *argv[]) {
344 if (argc == 4) {
345 removeOldMac(argv[1], argv[2]);
346 } else if (argc == 3) {
347 getNewMac(argv[1], argv[2], NULL, NULL);
349 return 0;
351 #endif