56959e5d6f11f17f34458c4eb6357f7c1cf4c567
[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 #include <net/if.h>
13 #include <sys/ioctl.h>
14 #ifdef CONFIG_FULL_DYNAMIC_VLAN
15 #include <linux/sockios.h>
16 #include <linux/if_vlan.h>
17 #include <linux/if_bridge.h>
18 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
19
20 #include "utils/common.h"
21 #include "hostapd.h"
22 #include "ap_config.h"
23 #include "ap_drv_ops.h"
24 #include "wpa_auth.h"
25 #include "vlan_init.h"
26 #include "vlan_util.h"
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 static 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 /*
242  * These are only available in recent linux headers (without the leading
243  * underscore).
244  */
245 #define _GET_VLAN_REALDEV_NAME_CMD      8
246 #define _GET_VLAN_VID_CMD               9
247
248 /* This value should be 256 ONLY. If it is something else, then hostapd
249  * might crash!, as this value has been hard-coded in 2.4.x kernel
250  * bridging code.
251  */
252 #define MAX_BR_PORTS                    256
253
254 static int br_delif(const char *br_name, const char *if_name)
255 {
256         int fd;
257         struct ifreq ifr;
258         unsigned long args[2];
259         int if_index;
260
261         wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
262         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
263                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
264                            "failed: %s", __func__, strerror(errno));
265                 return -1;
266         }
267
268         if_index = if_nametoindex(if_name);
269
270         if (if_index == 0) {
271                 wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
272                            "interface index for '%s'",
273                            __func__, if_name);
274                 close(fd);
275                 return -1;
276         }
277
278         args[0] = BRCTL_DEL_IF;
279         args[1] = if_index;
280
281         os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
282         ifr.ifr_data = (__caddr_t) args;
283
284         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
285                 /* No error if interface already removed. */
286                 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
287                            "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
288                            "%s", __func__, br_name, if_name, strerror(errno));
289                 close(fd);
290                 return -1;
291         }
292
293         close(fd);
294         return 0;
295 }
296
297
298 /*
299         Add interface 'if_name' to the bridge 'br_name'
300
301         returns -1 on error
302         returns 1 if the interface is already part of the bridge
303         returns 0 otherwise
304 */
305 static int br_addif(const char *br_name, const char *if_name)
306 {
307         int fd;
308         struct ifreq ifr;
309         unsigned long args[2];
310         int if_index;
311
312         wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
313         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
314                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
315                            "failed: %s", __func__, strerror(errno));
316                 return -1;
317         }
318
319         if_index = if_nametoindex(if_name);
320
321         if (if_index == 0) {
322                 wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
323                            "interface index for '%s'",
324                            __func__, if_name);
325                 close(fd);
326                 return -1;
327         }
328
329         args[0] = BRCTL_ADD_IF;
330         args[1] = if_index;
331
332         os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
333         ifr.ifr_data = (__caddr_t) args;
334
335         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
336                 if (errno == EBUSY) {
337                         /* The interface is already added. */
338                         close(fd);
339                         return 1;
340                 }
341
342                 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
343                            "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
344                            "%s", __func__, br_name, if_name, strerror(errno));
345                 close(fd);
346                 return -1;
347         }
348
349         close(fd);
350         return 0;
351 }
352
353
354 static int br_delbr(const char *br_name)
355 {
356         int fd;
357         unsigned long arg[2];
358
359         wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
360         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
361                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
362                            "failed: %s", __func__, strerror(errno));
363                 return -1;
364         }
365
366         arg[0] = BRCTL_DEL_BRIDGE;
367         arg[1] = (unsigned long) br_name;
368
369         if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
370                 /* No error if bridge already removed. */
371                 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
372                            "%s: %s", __func__, br_name, strerror(errno));
373                 close(fd);
374                 return -1;
375         }
376
377         close(fd);
378         return 0;
379 }
380
381
382 /*
383         Add a bridge with the name 'br_name'.
384
385         returns -1 on error
386         returns 1 if the bridge already exists
387         returns 0 otherwise
388 */
389 static int br_addbr(const char *br_name)
390 {
391         int fd;
392         unsigned long arg[4];
393         struct ifreq ifr;
394
395         wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
396         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
397                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
398                            "failed: %s", __func__, strerror(errno));
399                 return -1;
400         }
401
402         arg[0] = BRCTL_ADD_BRIDGE;
403         arg[1] = (unsigned long) br_name;
404
405         if (ioctl(fd, SIOCGIFBR, arg) < 0) {
406                 if (errno == EEXIST) {
407                         /* The bridge is already added. */
408                         close(fd);
409                         return 1;
410                 } else {
411                         wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
412                                    "failed for %s: %s",
413                                    __func__, br_name, strerror(errno));
414                         close(fd);
415                         return -1;
416                 }
417         }
418
419         /* Decrease forwarding delay to avoid EAPOL timeouts. */
420         os_memset(&ifr, 0, sizeof(ifr));
421         os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
422         arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
423         arg[1] = 1;
424         arg[2] = 0;
425         arg[3] = 0;
426         ifr.ifr_data = (char *) &arg;
427         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
428                 wpa_printf(MSG_ERROR, "VLAN: %s: "
429                            "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
430                            "%s: %s", __func__, br_name, strerror(errno));
431                 /* Continue anyway */
432         }
433
434         close(fd);
435         return 0;
436 }
437
438
439 static int br_getnumports(const char *br_name)
440 {
441         int fd;
442         int i;
443         int port_cnt = 0;
444         unsigned long arg[4];
445         int ifindices[MAX_BR_PORTS];
446         struct ifreq ifr;
447
448         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
449                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
450                            "failed: %s", __func__, strerror(errno));
451                 return -1;
452         }
453
454         arg[0] = BRCTL_GET_PORT_LIST;
455         arg[1] = (unsigned long) ifindices;
456         arg[2] = MAX_BR_PORTS;
457         arg[3] = 0;
458
459         os_memset(ifindices, 0, sizeof(ifindices));
460         os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
461         ifr.ifr_data = (__caddr_t) arg;
462
463         if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
464                 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
465                            "failed for %s: %s",
466                            __func__, br_name, strerror(errno));
467                 close(fd);
468                 return -1;
469         }
470
471         for (i = 1; i < MAX_BR_PORTS; i++) {
472                 if (ifindices[i] > 0) {
473                         port_cnt++;
474                 }
475         }
476
477         close(fd);
478         return port_cnt;
479 }
480
481
482 #ifndef CONFIG_VLAN_NETLINK
483
484 int vlan_rem(const char *if_name)
485 {
486         int fd;
487         struct vlan_ioctl_args if_request;
488
489         wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
490         if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
491                 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
492                            if_name);
493                 return -1;
494         }
495
496         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
497                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
498                            "failed: %s", __func__, strerror(errno));
499                 return -1;
500         }
501
502         os_memset(&if_request, 0, sizeof(if_request));
503
504         os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
505         if_request.cmd = DEL_VLAN_CMD;
506
507         if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
508                 wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
509                            "%s", __func__, if_name, strerror(errno));
510                 close(fd);
511                 return -1;
512         }
513
514         close(fd);
515         return 0;
516 }
517
518
519 /*
520         Add a vlan interface with VLAN ID 'vid' and tagged interface
521         'if_name'.
522
523         returns -1 on error
524         returns 1 if the interface already exists
525         returns 0 otherwise
526 */
527 int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
528 {
529         int fd;
530         struct vlan_ioctl_args if_request;
531
532         wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
533                    if_name, vid);
534         ifconfig_up(if_name);
535
536         if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
537                 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
538                            if_name);
539                 return -1;
540         }
541
542         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
543                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
544                            "failed: %s", __func__, strerror(errno));
545                 return -1;
546         }
547
548         os_memset(&if_request, 0, sizeof(if_request));
549
550         /* Determine if a suitable vlan device already exists. */
551
552         os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
553                     vid);
554
555         if_request.cmd = _GET_VLAN_VID_CMD;
556
557         if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) {
558
559                 if (if_request.u.VID == vid) {
560                         if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD;
561
562                         if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
563                             os_strncmp(if_request.u.device2, if_name,
564                                        sizeof(if_request.u.device2)) == 0) {
565                                 close(fd);
566                                 wpa_printf(MSG_DEBUG, "VLAN: vlan_add: "
567                                            "if_name %s exists already",
568                                            if_request.device1);
569                                 return 1;
570                         }
571                 }
572         }
573
574         /* A suitable vlan device does not already exist, add one. */
575
576         os_memset(&if_request, 0, sizeof(if_request));
577         os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
578         if_request.u.VID = vid;
579         if_request.cmd = ADD_VLAN_CMD;
580
581         if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
582                 wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: "
583                            "%s",
584                            __func__, if_request.device1, strerror(errno));
585                 close(fd);
586                 return -1;
587         }
588
589         close(fd);
590         return 0;
591 }
592
593
594 static int vlan_set_name_type(unsigned int name_type)
595 {
596         int fd;
597         struct vlan_ioctl_args if_request;
598
599         wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
600                    name_type);
601         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
602                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
603                            "failed: %s", __func__, strerror(errno));
604                 return -1;
605         }
606
607         os_memset(&if_request, 0, sizeof(if_request));
608
609         if_request.u.name_type = name_type;
610         if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
611         if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
612                 wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD "
613                            "name_type=%u failed: %s",
614                            __func__, name_type, strerror(errno));
615                 close(fd);
616                 return -1;
617         }
618
619         close(fd);
620         return 0;
621 }
622
623 #endif /* CONFIG_VLAN_NETLINK */
624
625
626 static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface,
627                                 const char *br_name, int vid,
628                                 struct hostapd_data *hapd)
629 {
630         char vlan_ifname[IFNAMSIZ];
631         int clean;
632
633         if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
634                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
635                             tagged_interface, vid);
636         else
637                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
638
639         clean = 0;
640         ifconfig_up(tagged_interface);
641         if (!vlan_add(tagged_interface, vid, vlan_ifname))
642                 clean |= DVLAN_CLEAN_VLAN;
643
644         if (!br_addif(br_name, vlan_ifname))
645                 clean |= DVLAN_CLEAN_VLAN_PORT;
646
647         dyn_iface_get(hapd, vlan_ifname, clean);
648
649         ifconfig_up(vlan_ifname);
650 }
651
652
653 static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid)
654 {
655         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
656
657         if (hapd->conf->vlan_bridge[0]) {
658                 os_snprintf(br_name, IFNAMSIZ, "%s%d",
659                             hapd->conf->vlan_bridge, vid);
660         } else if (tagged_interface) {
661                 os_snprintf(br_name, IFNAMSIZ, "br%s.%d",
662                             tagged_interface, vid);
663         } else {
664                 os_snprintf(br_name, IFNAMSIZ, "brvlan%d", vid);
665         }
666 }
667
668
669 static void vlan_get_bridge(const char *br_name, struct hostapd_data *hapd,
670                             int vid)
671 {
672         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
673         int vlan_naming = hapd->conf->ssid.vlan_naming;
674
675         dyn_iface_get(hapd, br_name, br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
676
677         ifconfig_up(br_name);
678
679         if (tagged_interface)
680                 vlan_newlink_tagged(vlan_naming, tagged_interface, br_name,
681                                     vid, hapd);
682 }
683
684
685 static void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
686 {
687         char br_name[IFNAMSIZ];
688         struct hostapd_vlan *vlan;
689         int untagged, *tagged, i;
690
691         wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
692
693         for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
694                 if (vlan->configured ||
695                     os_strcmp(ifname, vlan->ifname) != 0)
696                         continue;
697                 break;
698         }
699         if (!vlan)
700                 return;
701
702         vlan->configured = 1;
703
704         untagged = vlan->vlan_desc.untagged;
705         tagged = vlan->vlan_desc.tagged;
706
707         if (untagged > 0 && untagged <= MAX_VLAN_ID) {
708                 vlan_bridge_name(br_name, hapd, untagged);
709
710                 vlan_get_bridge(br_name, hapd, untagged);
711
712                 if (!br_addif(br_name, ifname))
713                         vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
714         }
715
716         for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
717                 if (tagged[i] == untagged ||
718                     tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
719                     (i > 0 && tagged[i] == tagged[i - 1]))
720                         continue;
721                 vlan_bridge_name(br_name, hapd, tagged[i]);
722                 vlan_get_bridge(br_name, hapd, tagged[i]);
723                 vlan_newlink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
724                                     ifname, br_name, tagged[i], hapd);
725         }
726
727         ifconfig_up(ifname);
728 }
729
730
731 static void vlan_dellink_tagged(int vlan_naming, const char *tagged_interface,
732                                 const char *br_name, int vid,
733                                 struct hostapd_data *hapd)
734 {
735         char vlan_ifname[IFNAMSIZ];
736         int clean;
737
738         if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
739                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
740                             tagged_interface, vid);
741         else
742                 os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
743
744         clean = dyn_iface_put(hapd, vlan_ifname);
745
746         if (clean & DVLAN_CLEAN_VLAN_PORT)
747                 br_delif(br_name, vlan_ifname);
748
749         if (clean & DVLAN_CLEAN_VLAN) {
750                 ifconfig_down(vlan_ifname);
751                 vlan_rem(vlan_ifname);
752         }
753 }
754
755
756 static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd,
757                             int vid)
758 {
759         int clean;
760         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
761         int vlan_naming = hapd->conf->ssid.vlan_naming;
762
763         if (tagged_interface)
764                 vlan_dellink_tagged(vlan_naming, tagged_interface, br_name,
765                                     vid, hapd);
766
767         clean = dyn_iface_put(hapd, br_name);
768         if ((clean & DVLAN_CLEAN_BR) && br_getnumports(br_name) == 0) {
769                 ifconfig_down(br_name);
770                 br_delbr(br_name);
771         }
772 }
773
774
775 static void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
776 {
777         struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
778
779         wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
780
781         first = prev = vlan;
782
783         while (vlan) {
784                 if (os_strcmp(ifname, vlan->ifname) != 0) {
785                         prev = vlan;
786                         vlan = vlan->next;
787                         continue;
788                 }
789                 break;
790         }
791         if (!vlan)
792                 return;
793
794         if (vlan->configured) {
795                 int untagged = vlan->vlan_desc.untagged;
796                 int *tagged = vlan->vlan_desc.tagged;
797                 char br_name[IFNAMSIZ];
798                 int i;
799
800                 for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
801                         if (tagged[i] == untagged ||
802                             tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
803                             (i > 0 && tagged[i] == tagged[i - 1]))
804                                 continue;
805                         vlan_bridge_name(br_name, hapd, tagged[i]);
806                         vlan_dellink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
807                                             ifname, br_name, tagged[i], hapd);
808                         vlan_put_bridge(br_name, hapd, tagged[i]);
809                 }
810
811                 if (untagged > 0 && untagged <= MAX_VLAN_ID) {
812                         vlan_bridge_name(br_name, hapd, untagged);
813
814                         if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
815                                 br_delif(br_name, vlan->ifname);
816
817                         vlan_put_bridge(br_name, hapd, untagged);
818                 }
819         }
820
821         /*
822          * Ensure this VLAN interface is actually removed even if
823          * NEWLINK message is only received later.
824          */
825         if (if_nametoindex(vlan->ifname) && vlan_if_remove(hapd, vlan))
826                 wpa_printf(MSG_ERROR,
827                            "VLAN: Could not remove VLAN iface: %s: %s",
828                            vlan->ifname, strerror(errno));
829
830         if (vlan == first)
831                 hapd->conf->vlan = vlan->next;
832         else
833                 prev->next = vlan->next;
834
835         os_free(vlan);
836 }
837
838
839 static void
840 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
841                   struct hostapd_data *hapd)
842 {
843         struct ifinfomsg *ifi;
844         int attrlen, nlmsg_len, rta_len;
845         struct rtattr *attr;
846         char ifname[IFNAMSIZ + 1];
847
848         if (len < sizeof(*ifi))
849                 return;
850
851         ifi = NLMSG_DATA(h);
852
853         nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
854
855         attrlen = h->nlmsg_len - nlmsg_len;
856         if (attrlen < 0)
857                 return;
858
859         attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
860
861         os_memset(ifname, 0, sizeof(ifname));
862         rta_len = RTA_ALIGN(sizeof(struct rtattr));
863         while (RTA_OK(attr, attrlen)) {
864                 if (attr->rta_type == IFLA_IFNAME) {
865                         int n = attr->rta_len - rta_len;
866                         if (n < 0)
867                                 break;
868
869                         if ((size_t) n >= sizeof(ifname))
870                                 n = sizeof(ifname) - 1;
871                         os_memcpy(ifname, ((char *) attr) + rta_len, n);
872
873                 }
874
875                 attr = RTA_NEXT(attr, attrlen);
876         }
877
878         if (!ifname[0])
879                 return;
880         if (del && if_nametoindex(ifname)) {
881                  /* interface still exists, race condition ->
882                   * iface has just been recreated */
883                 return;
884         }
885
886         wpa_printf(MSG_DEBUG,
887                    "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
888                    del ? "DEL" : "NEW",
889                    ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
890                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
891                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
892                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
893                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
894
895         if (del)
896                 vlan_dellink(ifname, hapd);
897         else
898                 vlan_newlink(ifname, hapd);
899 }
900
901
902 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
903 {
904         char buf[8192];
905         int left;
906         struct sockaddr_nl from;
907         socklen_t fromlen;
908         struct nlmsghdr *h;
909         struct hostapd_data *hapd = eloop_ctx;
910
911         fromlen = sizeof(from);
912         left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
913                         (struct sockaddr *) &from, &fromlen);
914         if (left < 0) {
915                 if (errno != EINTR && errno != EAGAIN)
916                         wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
917                                    __func__, strerror(errno));
918                 return;
919         }
920
921         h = (struct nlmsghdr *) buf;
922         while (NLMSG_OK(h, left)) {
923                 int len, plen;
924
925                 len = h->nlmsg_len;
926                 plen = len - sizeof(*h);
927                 if (len > left || plen < 0) {
928                         wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
929                                    "message: len=%d left=%d plen=%d",
930                                    len, left, plen);
931                         break;
932                 }
933
934                 switch (h->nlmsg_type) {
935                 case RTM_NEWLINK:
936                         vlan_read_ifnames(h, plen, 0, hapd);
937                         break;
938                 case RTM_DELLINK:
939                         vlan_read_ifnames(h, plen, 1, hapd);
940                         break;
941                 }
942
943                 h = NLMSG_NEXT(h, left);
944         }
945
946         if (left > 0) {
947                 wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
948                            "netlink message", __func__, left);
949         }
950 }
951
952
953 static struct full_dynamic_vlan *
954 full_dynamic_vlan_init(struct hostapd_data *hapd)
955 {
956         struct sockaddr_nl local;
957         struct full_dynamic_vlan *priv;
958
959         priv = os_zalloc(sizeof(*priv));
960         if (priv == NULL)
961                 return NULL;
962
963 #ifndef CONFIG_VLAN_NETLINK
964         vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
965                            DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
966                            VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
967                            VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
968 #endif /* CONFIG_VLAN_NETLINK */
969
970         priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
971         if (priv->s < 0) {
972                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
973                            "NETLINK_ROUTE) failed: %s",
974                            __func__, strerror(errno));
975                 os_free(priv);
976                 return NULL;
977         }
978
979         os_memset(&local, 0, sizeof(local));
980         local.nl_family = AF_NETLINK;
981         local.nl_groups = RTMGRP_LINK;
982         if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
983                 wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
984                            __func__, strerror(errno));
985                 close(priv->s);
986                 os_free(priv);
987                 return NULL;
988         }
989
990         if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
991         {
992                 close(priv->s);
993                 os_free(priv);
994                 return NULL;
995         }
996
997         return priv;
998 }
999
1000
1001 static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
1002 {
1003         if (priv == NULL)
1004                 return;
1005         eloop_unregister_read_sock(priv->s);
1006         close(priv->s);
1007         os_free(priv);
1008 }
1009 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1010
1011
1012 static int vlan_dynamic_add(struct hostapd_data *hapd,
1013                             struct hostapd_vlan *vlan)
1014 {
1015         while (vlan) {
1016                 if (vlan->vlan_id != VLAN_ID_WILDCARD) {
1017                         if (vlan_if_add(hapd, vlan, 1)) {
1018                                 wpa_printf(MSG_ERROR,
1019                                            "VLAN: Could not add VLAN %s: %s",
1020                                            vlan->ifname, strerror(errno));
1021                                 return -1;
1022                         }
1023 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1024                         vlan_newlink(vlan->ifname, hapd);
1025 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1026                 }
1027
1028                 vlan = vlan->next;
1029         }
1030
1031         return 0;
1032 }
1033
1034
1035 static void vlan_dynamic_remove(struct hostapd_data *hapd,
1036                                 struct hostapd_vlan *vlan)
1037 {
1038         struct hostapd_vlan *next;
1039
1040         while (vlan) {
1041                 next = vlan->next;
1042
1043 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1044                 /* vlan_dellink() takes care of cleanup and interface removal */
1045                 if (vlan->vlan_id != VLAN_ID_WILDCARD)
1046                         vlan_dellink(vlan->ifname, hapd);
1047 #else /* CONFIG_FULL_DYNAMIC_VLAN */
1048                 if (vlan->vlan_id != VLAN_ID_WILDCARD &&
1049                     vlan_if_remove(hapd, vlan)) {
1050                         wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
1051                                    "iface: %s: %s",
1052                                    vlan->ifname, strerror(errno));
1053                 }
1054 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1055
1056                 vlan = next;
1057         }
1058 }
1059
1060
1061 int vlan_init(struct hostapd_data *hapd)
1062 {
1063 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1064         hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
1065 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1066
1067         if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
1068             !hapd->conf->vlan) {
1069                 /* dynamic vlans enabled but no (or empty) vlan_file given */
1070                 struct hostapd_vlan *vlan;
1071                 vlan = os_zalloc(sizeof(*vlan));
1072                 if (vlan == NULL) {
1073                         wpa_printf(MSG_ERROR, "Out of memory while assigning "
1074                                    "VLAN interfaces");
1075                         return -1;
1076                 }
1077
1078                 vlan->vlan_id = VLAN_ID_WILDCARD;
1079                 os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
1080                             hapd->conf->iface);
1081                 vlan->next = hapd->conf->vlan;
1082                 hapd->conf->vlan = vlan;
1083         }
1084
1085         if (vlan_dynamic_add(hapd, hapd->conf->vlan))
1086                 return -1;
1087
1088         return 0;
1089 }
1090
1091
1092 void vlan_deinit(struct hostapd_data *hapd)
1093 {
1094         vlan_dynamic_remove(hapd, hapd->conf->vlan);
1095
1096 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1097         full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
1098         hapd->full_dynamic_vlan = NULL;
1099 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1100 }
1101
1102
1103 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
1104                                        struct hostapd_vlan *vlan,
1105                                        int vlan_id,
1106                                        struct vlan_description *vlan_desc)
1107 {
1108         struct hostapd_vlan *n = NULL;
1109         char *ifname, *pos;
1110
1111         if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
1112                 return NULL;
1113
1114         wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
1115                    __func__, vlan_id, vlan->ifname);
1116         ifname = os_strdup(vlan->ifname);
1117         if (ifname == NULL)
1118                 return NULL;
1119         pos = os_strchr(ifname, '#');
1120         if (pos == NULL)
1121                 goto free_ifname;
1122         *pos++ = '\0';
1123
1124         n = os_zalloc(sizeof(*n));
1125         if (n == NULL)
1126                 goto free_ifname;
1127
1128         n->vlan_id = vlan_id;
1129         if (vlan_desc)
1130                 n->vlan_desc = *vlan_desc;
1131         n->dynamic_vlan = 1;
1132
1133         os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
1134                     pos);
1135
1136         n->next = hapd->conf->vlan;
1137         hapd->conf->vlan = n;
1138
1139         /* hapd->conf->vlan needs this new VLAN here for WPA setup */
1140         if (vlan_if_add(hapd, n, 0)) {
1141                 hapd->conf->vlan = n->next;
1142                 os_free(n);
1143                 n = NULL;
1144                 goto free_ifname;
1145         }
1146
1147 free_ifname:
1148         os_free(ifname);
1149         return n;
1150 }
1151
1152
1153 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
1154 {
1155         struct hostapd_vlan *vlan;
1156
1157         if (vlan_id <= 0)
1158                 return 1;
1159
1160         wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
1161                    __func__, hapd->conf->iface, vlan_id);
1162
1163         vlan = hapd->conf->vlan;
1164         while (vlan) {
1165                 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
1166                         vlan->dynamic_vlan--;
1167                         break;
1168                 }
1169                 vlan = vlan->next;
1170         }
1171
1172         if (vlan == NULL)
1173                 return 1;
1174
1175         if (vlan->dynamic_vlan == 0) {
1176                 vlan_if_remove(hapd, vlan);
1177 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1178                 vlan_dellink(vlan->ifname, hapd);
1179 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1180         }
1181
1182         return 0;
1183 }