1ce95744a937ad9ffa34e93fea20b5ec635139e7
[mech_eap.git] / src / ap / vlan_init.c
1 /*
2  * hostapd / VLAN initialization
3  * Copyright 2003, Instant802 Networks, Inc.
4  * Copyright 2005-2006, Devicescape Software, Inc.
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10
11 #include "utils/includes.h"
12
13 #include "utils/common.h"
14 #include "hostapd.h"
15 #include "ap_config.h"
16 #include "ap_drv_ops.h"
17 #include "wpa_auth.h"
18 #include "vlan_init.h"
19 #include "vlan_util.h"
20
21 #include <net/if.h>
22 #include <sys/ioctl.h>
23 #ifdef CONFIG_FULL_DYNAMIC_VLAN
24 #include <linux/if_vlan.h>
25 #include <linux/if_bridge.h>
26 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
27
28
29 #ifdef CONFIG_FULL_DYNAMIC_VLAN
30
31 #include "drivers/priv_netlink.h"
32 #include "utils/eloop.h"
33
34
35 struct full_dynamic_vlan {
36         int s; /* socket on which to listen for new/removed interfaces. */
37 };
38
39 #define DVLAN_CLEAN_BR         0x1
40 #define DVLAN_CLEAN_VLAN       0x2
41 #define DVLAN_CLEAN_VLAN_PORT  0x4
42
43 struct dynamic_iface {
44         char ifname[IFNAMSIZ + 1];
45         int usage;
46         int clean;
47         struct dynamic_iface *next;
48 };
49
50
51 /* Increment ref counter for ifname and add clean flag.
52  * If not in list, add it only if some flags are given.
53  */
54 static void dyn_iface_get(struct hostapd_data *hapd, const char *ifname,
55                           int clean)
56 {
57         struct dynamic_iface *next, **dynamic_ifaces;
58         struct hapd_interfaces *interfaces;
59
60         interfaces = hapd->iface->interfaces;
61         dynamic_ifaces = &interfaces->vlan_priv;
62
63         for (next = *dynamic_ifaces; next; next = next->next) {
64                 if (os_strcmp(ifname, next->ifname) == 0)
65                         break;
66         }
67
68         if (next) {
69                 next->usage++;
70                 next->clean |= clean;
71                 return;
72         }
73
74         if (!clean)
75                 return;
76
77         next = os_zalloc(sizeof(*next));
78         if (!next)
79                 return;
80         os_strlcpy(next->ifname, ifname, sizeof(next->ifname));
81         next->usage = 1;
82         next->clean = clean;
83         next->next = *dynamic_ifaces;
84         *dynamic_ifaces = next;
85 }
86
87
88 /* Decrement reference counter for given ifname.
89  * Return clean flag iff reference counter was decreased to zero, else zero
90  */
91 static int dyn_iface_put(struct hostapd_data *hapd, const char *ifname)
92 {
93         struct dynamic_iface *next, *prev = NULL, **dynamic_ifaces;
94         struct hapd_interfaces *interfaces;
95         int clean;
96
97         interfaces = hapd->iface->interfaces;
98         dynamic_ifaces = &interfaces->vlan_priv;
99
100         for (next = *dynamic_ifaces; next; next = next->next) {
101                 if (os_strcmp(ifname, next->ifname) == 0)
102                         break;
103                 prev = next;
104         }
105
106         if (!next)
107                 return 0;
108
109         next->usage--;
110         if (next->usage)
111                 return 0;
112
113         if (prev)
114                 prev->next = next->next;
115         else
116                 *dynamic_ifaces = next->next;
117         clean = next->clean;
118         os_free(next);
119
120         return clean;
121 }
122
123 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
124
125
126 static int ifconfig_helper(const char *if_name, int up)
127 {
128         int fd;
129         struct ifreq ifr;
130
131         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
132                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
133                            "failed: %s", __func__, strerror(errno));
134                 return -1;
135         }
136
137         os_memset(&ifr, 0, sizeof(ifr));
138         os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
139
140         if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
141                 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
142                            "for interface %s: %s",
143                            __func__, if_name, strerror(errno));
144                 close(fd);
145                 return -1;
146         }
147
148         if (up)
149                 ifr.ifr_flags |= IFF_UP;
150         else
151                 ifr.ifr_flags &= ~IFF_UP;
152
153         if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
154                 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
155                            "for interface %s (up=%d): %s",
156                            __func__, if_name, up, strerror(errno));
157                 close(fd);
158                 return -1;
159         }
160
161         close(fd);
162         return 0;
163 }
164
165
166 int ifconfig_up(const char *if_name)
167 {
168         wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
169         return ifconfig_helper(if_name, 1);
170 }
171
172
173 static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
174                        int existsok)
175 {
176         int ret, i;
177
178         for (i = 0; i < NUM_WEP_KEYS; i++) {
179                 if (!hapd->conf->ssid.wep.key[i])
180                         continue;
181                 wpa_printf(MSG_ERROR,
182                            "VLAN: Refusing to set up VLAN iface %s with WEP",
183                            vlan->ifname);
184                 return -1;
185         }
186
187         if (!if_nametoindex(vlan->ifname))
188                 ret = hostapd_vlan_if_add(hapd, vlan->ifname);
189         else if (!existsok)
190                 return -1;
191         else
192                 ret = 0;
193
194         if (ret)
195                 return ret;
196
197         ifconfig_up(vlan->ifname); /* else wpa group will fail fatal */
198
199         if (hapd->wpa_auth)
200                 ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
201
202         if (ret == 0)
203                 return ret;
204
205         wpa_printf(MSG_ERROR, "WPA initialization for VLAN %d failed (%d)",
206                    vlan->vlan_id, ret);
207         if (wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id))
208                 wpa_printf(MSG_ERROR, "WPA deinit of %s failed", vlan->ifname);
209
210         /* group state machine setup failed */
211         if (hostapd_vlan_if_remove(hapd, vlan->ifname))
212                 wpa_printf(MSG_ERROR, "Removal of %s failed", vlan->ifname);
213
214         return ret;
215 }
216
217
218 static int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
219 {
220         int ret;
221
222         ret = wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id);
223         if (ret)
224                 wpa_printf(MSG_ERROR,
225                            "WPA deinitialization for VLAN %d failed (%d)",
226                            vlan->vlan_id, ret);
227
228         return hostapd_vlan_if_remove(hapd, vlan->ifname);
229 }
230
231
232 #ifdef CONFIG_FULL_DYNAMIC_VLAN
233
234 static int ifconfig_down(const char *if_name)
235 {
236         wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
237         return ifconfig_helper(if_name, 0);
238 }
239
240
241 /* This value should be 256 ONLY. If it is something else, then hostapd
242  * might crash!, as this value has been hard-coded in 2.4.x kernel
243  * bridging code.
244  */
245 #define MAX_BR_PORTS                    256
246
247 static int br_delif(const char *br_name, const char *if_name)
248 {
249         int fd;
250         struct ifreq ifr;
251         unsigned long args[2];
252         int if_index;
253
254         wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
255         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
256                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
257                            "failed: %s", __func__, strerror(errno));
258                 return -1;
259         }
260
261         if_index = if_nametoindex(if_name);
262
263         if (if_index == 0) {
264                 wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
265                            "interface index for '%s'",
266                            __func__, if_name);
267                 close(fd);
268                 return -1;
269         }
270
271         args[0] = BRCTL_DEL_IF;
272         args[1] = if_index;
273
274         os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
275         ifr.ifr_data = (void *) args;
276
277         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
278                 /* No error if interface already removed. */
279                 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
280                            "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
281                            "%s", __func__, br_name, if_name, strerror(errno));
282                 close(fd);
283                 return -1;
284         }
285
286         close(fd);
287         return 0;
288 }
289
290
291 /*
292         Add interface 'if_name' to the bridge 'br_name'
293
294         returns -1 on error
295         returns 1 if the interface is already part of the bridge
296         returns 0 otherwise
297 */
298 static int br_addif(const char *br_name, const char *if_name)
299 {
300         int fd;
301         struct ifreq ifr;
302         unsigned long args[2];
303         int if_index;
304
305         wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
306         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
307                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
308                            "failed: %s", __func__, strerror(errno));
309                 return -1;
310         }
311
312         if_index = if_nametoindex(if_name);
313
314         if (if_index == 0) {
315                 wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
316                            "interface index for '%s'",
317                            __func__, if_name);
318                 close(fd);
319                 return -1;
320         }
321
322         args[0] = BRCTL_ADD_IF;
323         args[1] = if_index;
324
325         os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
326         ifr.ifr_data = (void *) args;
327
328         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
329                 if (errno == EBUSY) {
330                         /* The interface is already added. */
331                         close(fd);
332                         return 1;
333                 }
334
335                 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
336                            "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
337                            "%s", __func__, br_name, if_name, strerror(errno));
338                 close(fd);
339                 return -1;
340         }
341
342         close(fd);
343         return 0;
344 }
345
346
347 static int br_delbr(const char *br_name)
348 {
349         int fd;
350         unsigned long arg[2];
351
352         wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
353         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
354                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
355                            "failed: %s", __func__, strerror(errno));
356                 return -1;
357         }
358
359         arg[0] = BRCTL_DEL_BRIDGE;
360         arg[1] = (unsigned long) br_name;
361
362         if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
363                 /* No error if bridge already removed. */
364                 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
365                            "%s: %s", __func__, br_name, strerror(errno));
366                 close(fd);
367                 return -1;
368         }
369
370         close(fd);
371         return 0;
372 }
373
374
375 /*
376         Add a bridge with the name 'br_name'.
377
378         returns -1 on error
379         returns 1 if the bridge already exists
380         returns 0 otherwise
381 */
382 static int br_addbr(const char *br_name)
383 {
384         int fd;
385         unsigned long arg[4];
386         struct ifreq ifr;
387
388         wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
389         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
390                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
391                            "failed: %s", __func__, strerror(errno));
392                 return -1;
393         }
394
395         arg[0] = BRCTL_ADD_BRIDGE;
396         arg[1] = (unsigned long) br_name;
397
398         if (ioctl(fd, SIOCGIFBR, arg) < 0) {
399                 if (errno == EEXIST) {
400                         /* The bridge is already added. */
401                         close(fd);
402                         return 1;
403                 } else {
404                         wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
405                                    "failed for %s: %s",
406                                    __func__, br_name, strerror(errno));
407                         close(fd);
408                         return -1;
409                 }
410         }
411
412         /* Decrease forwarding delay to avoid EAPOL timeouts. */
413         os_memset(&ifr, 0, sizeof(ifr));
414         os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
415         arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
416         arg[1] = 1;
417         arg[2] = 0;
418         arg[3] = 0;
419         ifr.ifr_data = (char *) &arg;
420         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
421                 wpa_printf(MSG_ERROR, "VLAN: %s: "
422                            "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
423                            "%s: %s", __func__, br_name, strerror(errno));
424                 /* Continue anyway */
425         }
426
427         close(fd);
428         return 0;
429 }
430
431
432 static int br_getnumports(const char *br_name)
433 {
434         int fd;
435         int i;
436         int port_cnt = 0;
437         unsigned long arg[4];
438         int ifindices[MAX_BR_PORTS];
439         struct ifreq ifr;
440
441         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
442                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
443                            "failed: %s", __func__, strerror(errno));
444                 return -1;
445         }
446
447         arg[0] = BRCTL_GET_PORT_LIST;
448         arg[1] = (unsigned long) ifindices;
449         arg[2] = MAX_BR_PORTS;
450         arg[3] = 0;
451
452         os_memset(ifindices, 0, sizeof(ifindices));
453         os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
454         ifr.ifr_data = (void *) arg;
455
456         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
457                 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
458                            "failed for %s: %s",
459                            __func__, br_name, strerror(errno));
460                 close(fd);
461                 return -1;
462         }
463
464         for (i = 1; i < MAX_BR_PORTS; i++) {
465                 if (ifindices[i] > 0) {
466                         port_cnt++;
467                 }
468         }
469
470         close(fd);
471         return port_cnt;
472 }
473
474
475 static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface,
476                                 const char *br_name, int vid,
477                                 struct hostapd_data *hapd)
478 {
479         char vlan_ifname[IFNAMSIZ];
480         int clean;
481
482         if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
483                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
484                             tagged_interface, vid);
485         else
486                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
487
488         clean = 0;
489         ifconfig_up(tagged_interface);
490         if (!vlan_add(tagged_interface, vid, vlan_ifname))
491                 clean |= DVLAN_CLEAN_VLAN;
492
493         if (!br_addif(br_name, vlan_ifname))
494                 clean |= DVLAN_CLEAN_VLAN_PORT;
495
496         dyn_iface_get(hapd, vlan_ifname, clean);
497
498         ifconfig_up(vlan_ifname);
499 }
500
501
502 static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid)
503 {
504         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
505
506         if (hapd->conf->vlan_bridge[0]) {
507                 os_snprintf(br_name, IFNAMSIZ, "%s%d",
508                             hapd->conf->vlan_bridge, vid);
509         } else if (tagged_interface) {
510                 os_snprintf(br_name, IFNAMSIZ, "br%s.%d",
511                             tagged_interface, vid);
512         } else {
513                 os_snprintf(br_name, IFNAMSIZ, "brvlan%d", vid);
514         }
515 }
516
517
518 static void vlan_get_bridge(const char *br_name, struct hostapd_data *hapd,
519                             int vid)
520 {
521         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
522         int vlan_naming = hapd->conf->ssid.vlan_naming;
523
524         dyn_iface_get(hapd, br_name, br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
525
526         ifconfig_up(br_name);
527
528         if (tagged_interface)
529                 vlan_newlink_tagged(vlan_naming, tagged_interface, br_name,
530                                     vid, hapd);
531 }
532
533
534 static void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
535 {
536         char br_name[IFNAMSIZ];
537         struct hostapd_vlan *vlan;
538         int untagged, *tagged, i, notempty;
539
540         wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
541
542         for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
543                 if (vlan->configured ||
544                     os_strcmp(ifname, vlan->ifname) != 0)
545                         continue;
546                 break;
547         }
548         if (!vlan)
549                 return;
550
551         vlan->configured = 1;
552
553         notempty = vlan->vlan_desc.notempty;
554         untagged = vlan->vlan_desc.untagged;
555         tagged = vlan->vlan_desc.tagged;
556
557         if (!notempty) {
558                 /* Non-VLAN STA */
559                 if (hapd->conf->bridge[0] &&
560                     !br_addif(hapd->conf->bridge, ifname))
561                         vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
562         } else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
563                 vlan_bridge_name(br_name, hapd, untagged);
564
565                 vlan_get_bridge(br_name, hapd, untagged);
566
567                 if (!br_addif(br_name, ifname))
568                         vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
569         }
570
571         for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
572                 if (tagged[i] == untagged ||
573                     tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
574                     (i > 0 && tagged[i] == tagged[i - 1]))
575                         continue;
576                 vlan_bridge_name(br_name, hapd, tagged[i]);
577                 vlan_get_bridge(br_name, hapd, tagged[i]);
578                 vlan_newlink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
579                                     ifname, br_name, tagged[i], hapd);
580         }
581
582         ifconfig_up(ifname);
583 }
584
585
586 static void vlan_dellink_tagged(int vlan_naming, const char *tagged_interface,
587                                 const char *br_name, int vid,
588                                 struct hostapd_data *hapd)
589 {
590         char vlan_ifname[IFNAMSIZ];
591         int clean;
592
593         if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
594                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
595                             tagged_interface, vid);
596         else
597                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
598
599         clean = dyn_iface_put(hapd, vlan_ifname);
600
601         if (clean & DVLAN_CLEAN_VLAN_PORT)
602                 br_delif(br_name, vlan_ifname);
603
604         if (clean & DVLAN_CLEAN_VLAN) {
605                 ifconfig_down(vlan_ifname);
606                 vlan_rem(vlan_ifname);
607         }
608 }
609
610
611 static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd,
612                             int vid)
613 {
614         int clean;
615         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
616         int vlan_naming = hapd->conf->ssid.vlan_naming;
617
618         if (tagged_interface)
619                 vlan_dellink_tagged(vlan_naming, tagged_interface, br_name,
620                                     vid, hapd);
621
622         clean = dyn_iface_put(hapd, br_name);
623         if ((clean & DVLAN_CLEAN_BR) && br_getnumports(br_name) == 0) {
624                 ifconfig_down(br_name);
625                 br_delbr(br_name);
626         }
627 }
628
629
630 static void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
631 {
632         struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
633
634         wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
635
636         first = prev = vlan;
637
638         while (vlan) {
639                 if (os_strcmp(ifname, vlan->ifname) != 0) {
640                         prev = vlan;
641                         vlan = vlan->next;
642                         continue;
643                 }
644                 break;
645         }
646         if (!vlan)
647                 return;
648
649         if (vlan->configured) {
650                 int notempty = vlan->vlan_desc.notempty;
651                 int untagged = vlan->vlan_desc.untagged;
652                 int *tagged = vlan->vlan_desc.tagged;
653                 char br_name[IFNAMSIZ];
654                 int i;
655
656                 for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
657                         if (tagged[i] == untagged ||
658                             tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
659                             (i > 0 && tagged[i] == tagged[i - 1]))
660                                 continue;
661                         vlan_bridge_name(br_name, hapd, tagged[i]);
662                         vlan_dellink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
663                                             ifname, br_name, tagged[i], hapd);
664                         vlan_put_bridge(br_name, hapd, tagged[i]);
665                 }
666
667                 if (!notempty) {
668                         /* Non-VLAN STA */
669                         if (hapd->conf->bridge[0] &&
670                             (vlan->clean & DVLAN_CLEAN_WLAN_PORT))
671                                 br_delif(hapd->conf->bridge, ifname);
672                 } else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
673                         vlan_bridge_name(br_name, hapd, untagged);
674
675                         if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
676                                 br_delif(br_name, vlan->ifname);
677
678                         vlan_put_bridge(br_name, hapd, untagged);
679                 }
680         }
681
682         /*
683          * Ensure this VLAN interface is actually removed even if
684          * NEWLINK message is only received later.
685          */
686         if (if_nametoindex(vlan->ifname) && vlan_if_remove(hapd, vlan))
687                 wpa_printf(MSG_ERROR,
688                            "VLAN: Could not remove VLAN iface: %s: %s",
689                            vlan->ifname, strerror(errno));
690
691         if (vlan == first)
692                 hapd->conf->vlan = vlan->next;
693         else
694                 prev->next = vlan->next;
695
696         os_free(vlan);
697 }
698
699
700 static void
701 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
702                   struct hostapd_data *hapd)
703 {
704         struct ifinfomsg *ifi;
705         int attrlen, nlmsg_len, rta_len;
706         struct rtattr *attr;
707         char ifname[IFNAMSIZ + 1];
708
709         if (len < sizeof(*ifi))
710                 return;
711
712         ifi = NLMSG_DATA(h);
713
714         nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
715
716         attrlen = h->nlmsg_len - nlmsg_len;
717         if (attrlen < 0)
718                 return;
719
720         attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
721
722         os_memset(ifname, 0, sizeof(ifname));
723         rta_len = RTA_ALIGN(sizeof(struct rtattr));
724         while (RTA_OK(attr, attrlen)) {
725                 if (attr->rta_type == IFLA_IFNAME) {
726                         int n = attr->rta_len - rta_len;
727                         if (n < 0)
728                                 break;
729
730                         if ((size_t) n >= sizeof(ifname))
731                                 n = sizeof(ifname) - 1;
732                         os_memcpy(ifname, ((char *) attr) + rta_len, n);
733
734                 }
735
736                 attr = RTA_NEXT(attr, attrlen);
737         }
738
739         if (!ifname[0])
740                 return;
741         if (del && if_nametoindex(ifname)) {
742                  /* interface still exists, race condition ->
743                   * iface has just been recreated */
744                 return;
745         }
746
747         wpa_printf(MSG_DEBUG,
748                    "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
749                    del ? "DEL" : "NEW",
750                    ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
751                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
752                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
753                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
754                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
755
756         if (del)
757                 vlan_dellink(ifname, hapd);
758         else
759                 vlan_newlink(ifname, hapd);
760 }
761
762
763 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
764 {
765         char buf[8192];
766         int left;
767         struct sockaddr_nl from;
768         socklen_t fromlen;
769         struct nlmsghdr *h;
770         struct hostapd_data *hapd = eloop_ctx;
771
772         fromlen = sizeof(from);
773         left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
774                         (struct sockaddr *) &from, &fromlen);
775         if (left < 0) {
776                 if (errno != EINTR && errno != EAGAIN)
777                         wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
778                                    __func__, strerror(errno));
779                 return;
780         }
781
782         h = (struct nlmsghdr *) buf;
783         while (NLMSG_OK(h, left)) {
784                 int len, plen;
785
786                 len = h->nlmsg_len;
787                 plen = len - sizeof(*h);
788                 if (len > left || plen < 0) {
789                         wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
790                                    "message: len=%d left=%d plen=%d",
791                                    len, left, plen);
792                         break;
793                 }
794
795                 switch (h->nlmsg_type) {
796                 case RTM_NEWLINK:
797                         vlan_read_ifnames(h, plen, 0, hapd);
798                         break;
799                 case RTM_DELLINK:
800                         vlan_read_ifnames(h, plen, 1, hapd);
801                         break;
802                 }
803
804                 h = NLMSG_NEXT(h, left);
805         }
806
807         if (left > 0) {
808                 wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
809                            "netlink message", __func__, left);
810         }
811 }
812
813
814 static struct full_dynamic_vlan *
815 full_dynamic_vlan_init(struct hostapd_data *hapd)
816 {
817         struct sockaddr_nl local;
818         struct full_dynamic_vlan *priv;
819
820         priv = os_zalloc(sizeof(*priv));
821         if (priv == NULL)
822                 return NULL;
823
824         vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
825                            DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
826                            VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
827                            VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
828
829         priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
830         if (priv->s < 0) {
831                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
832                            "NETLINK_ROUTE) failed: %s",
833                            __func__, strerror(errno));
834                 os_free(priv);
835                 return NULL;
836         }
837
838         os_memset(&local, 0, sizeof(local));
839         local.nl_family = AF_NETLINK;
840         local.nl_groups = RTMGRP_LINK;
841         if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
842                 wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
843                            __func__, strerror(errno));
844                 close(priv->s);
845                 os_free(priv);
846                 return NULL;
847         }
848
849         if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
850         {
851                 close(priv->s);
852                 os_free(priv);
853                 return NULL;
854         }
855
856         return priv;
857 }
858
859
860 static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
861 {
862         if (priv == NULL)
863                 return;
864         eloop_unregister_read_sock(priv->s);
865         close(priv->s);
866         os_free(priv);
867 }
868 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
869
870
871 static int vlan_dynamic_add(struct hostapd_data *hapd,
872                             struct hostapd_vlan *vlan)
873 {
874         while (vlan) {
875                 if (vlan->vlan_id != VLAN_ID_WILDCARD) {
876                         if (vlan_if_add(hapd, vlan, 1)) {
877                                 wpa_printf(MSG_ERROR,
878                                            "VLAN: Could not add VLAN %s: %s",
879                                            vlan->ifname, strerror(errno));
880                                 return -1;
881                         }
882 #ifdef CONFIG_FULL_DYNAMIC_VLAN
883                         vlan_newlink(vlan->ifname, hapd);
884 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
885                 }
886
887                 vlan = vlan->next;
888         }
889
890         return 0;
891 }
892
893
894 static void vlan_dynamic_remove(struct hostapd_data *hapd,
895                                 struct hostapd_vlan *vlan)
896 {
897         struct hostapd_vlan *next;
898
899         while (vlan) {
900                 next = vlan->next;
901
902 #ifdef CONFIG_FULL_DYNAMIC_VLAN
903                 /* vlan_dellink() takes care of cleanup and interface removal */
904                 if (vlan->vlan_id != VLAN_ID_WILDCARD)
905                         vlan_dellink(vlan->ifname, hapd);
906 #else /* CONFIG_FULL_DYNAMIC_VLAN */
907                 if (vlan->vlan_id != VLAN_ID_WILDCARD &&
908                     vlan_if_remove(hapd, vlan)) {
909                         wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
910                                    "iface: %s: %s",
911                                    vlan->ifname, strerror(errno));
912                 }
913 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
914
915                 vlan = next;
916         }
917 }
918
919
920 int vlan_init(struct hostapd_data *hapd)
921 {
922 #ifdef CONFIG_FULL_DYNAMIC_VLAN
923         hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
924 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
925
926         if ((hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED ||
927              hapd->conf->ssid.per_sta_vif) &&
928             !hapd->conf->vlan) {
929                 /* dynamic vlans enabled but no (or empty) vlan_file given */
930                 struct hostapd_vlan *vlan;
931                 vlan = os_zalloc(sizeof(*vlan));
932                 if (vlan == NULL) {
933                         wpa_printf(MSG_ERROR, "Out of memory while assigning "
934                                    "VLAN interfaces");
935                         return -1;
936                 }
937
938                 vlan->vlan_id = VLAN_ID_WILDCARD;
939                 os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
940                             hapd->conf->iface);
941                 vlan->next = hapd->conf->vlan;
942                 hapd->conf->vlan = vlan;
943         }
944
945         if (vlan_dynamic_add(hapd, hapd->conf->vlan))
946                 return -1;
947
948         return 0;
949 }
950
951
952 void vlan_deinit(struct hostapd_data *hapd)
953 {
954         vlan_dynamic_remove(hapd, hapd->conf->vlan);
955
956 #ifdef CONFIG_FULL_DYNAMIC_VLAN
957         full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
958         hapd->full_dynamic_vlan = NULL;
959 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
960 }
961
962
963 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
964                                        struct hostapd_vlan *vlan,
965                                        int vlan_id,
966                                        struct vlan_description *vlan_desc)
967 {
968         struct hostapd_vlan *n;
969         char ifname[IFNAMSIZ + 1], *pos;
970
971         if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
972                 return NULL;
973
974         wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
975                    __func__, vlan_id, vlan->ifname);
976         os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
977         pos = os_strchr(ifname, '#');
978         if (pos == NULL)
979                 return NULL;
980         *pos++ = '\0';
981
982         n = os_zalloc(sizeof(*n));
983         if (n == NULL)
984                 return NULL;
985
986         n->vlan_id = vlan_id;
987         if (vlan_desc)
988                 n->vlan_desc = *vlan_desc;
989         n->dynamic_vlan = 1;
990
991         os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
992                     pos);
993
994         n->next = hapd->conf->vlan;
995         hapd->conf->vlan = n;
996
997         /* hapd->conf->vlan needs this new VLAN here for WPA setup */
998         if (vlan_if_add(hapd, n, 0)) {
999                 hapd->conf->vlan = n->next;
1000                 os_free(n);
1001                 n = NULL;
1002         }
1003
1004         return n;
1005 }
1006
1007
1008 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
1009 {
1010         struct hostapd_vlan *vlan;
1011
1012         if (vlan_id <= 0)
1013                 return 1;
1014
1015         wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
1016                    __func__, hapd->conf->iface, vlan_id);
1017
1018         vlan = hapd->conf->vlan;
1019         while (vlan) {
1020                 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
1021                         vlan->dynamic_vlan--;
1022                         break;
1023                 }
1024                 vlan = vlan->next;
1025         }
1026
1027         if (vlan == NULL)
1028                 return 1;
1029
1030         if (vlan->dynamic_vlan == 0) {
1031                 vlan_if_remove(hapd, vlan);
1032 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1033                 vlan_dellink(vlan->ifname, hapd);
1034 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1035         }
1036
1037         return 0;
1038 }