e3df164e2083f163ad485acd8a8eb271ebf2ed5f
[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(char *ifname, struct hostapd_data *hapd)
627 {
628         char vlan_ifname[IFNAMSIZ];
629         char br_name[IFNAMSIZ];
630         struct hostapd_vlan *vlan = hapd->conf->vlan;
631         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
632         int vlan_naming = hapd->conf->ssid.vlan_naming;
633         int clean;
634
635         wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
636
637         while (vlan) {
638                 if (os_strcmp(ifname, vlan->ifname) == 0 && !vlan->configured) {
639                         vlan->configured = 1;
640
641                         if (hapd->conf->vlan_bridge[0]) {
642                                 os_snprintf(br_name, sizeof(br_name), "%s%d",
643                                             hapd->conf->vlan_bridge,
644                                             vlan->vlan_id);
645                         } else if (tagged_interface) {
646                                 os_snprintf(br_name, sizeof(br_name),
647                                             "br%s.%d", tagged_interface,
648                                             vlan->vlan_id);
649                         } else {
650                                 os_snprintf(br_name, sizeof(br_name),
651                                             "brvlan%d", vlan->vlan_id);
652                         }
653
654                         dyn_iface_get(hapd, br_name,
655                                       br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
656
657                         ifconfig_up(br_name);
658
659                         if (tagged_interface) {
660                                 if (vlan_naming ==
661                                     DYNAMIC_VLAN_NAMING_WITH_DEVICE)
662                                         os_snprintf(vlan_ifname,
663                                                     sizeof(vlan_ifname),
664                                                     "%s.%d", tagged_interface,
665                                                     vlan->vlan_id);
666                                 else
667                                         os_snprintf(vlan_ifname,
668                                                     sizeof(vlan_ifname),
669                                                     "vlan%d", vlan->vlan_id);
670
671                                 clean = 0;
672                                 ifconfig_up(tagged_interface);
673                                 if (!vlan_add(tagged_interface, vlan->vlan_id,
674                                               vlan_ifname))
675                                         clean |= DVLAN_CLEAN_VLAN;
676
677                                 if (!br_addif(br_name, vlan_ifname))
678                                         clean |= DVLAN_CLEAN_VLAN_PORT;
679
680                                 dyn_iface_get(hapd, vlan_ifname, clean);
681
682                                 ifconfig_up(vlan_ifname);
683                         }
684
685                         if (!br_addif(br_name, ifname))
686                                 vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
687
688                         ifconfig_up(ifname);
689
690                         break;
691                 }
692                 vlan = vlan->next;
693         }
694 }
695
696
697 static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
698 {
699         char vlan_ifname[IFNAMSIZ];
700         char br_name[IFNAMSIZ];
701         struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
702         char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
703         int vlan_naming = hapd->conf->ssid.vlan_naming;
704         int clean;
705
706         wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
707
708         first = prev = vlan;
709
710         while (vlan) {
711                 if (os_strcmp(ifname, vlan->ifname) == 0 &&
712                     vlan->configured) {
713                         if (hapd->conf->vlan_bridge[0]) {
714                                 os_snprintf(br_name, sizeof(br_name), "%s%d",
715                                             hapd->conf->vlan_bridge,
716                                             vlan->vlan_id);
717                         } else if (tagged_interface) {
718                                 os_snprintf(br_name, sizeof(br_name),
719                                             "br%s.%d", tagged_interface,
720                                             vlan->vlan_id);
721                         } else {
722                                 os_snprintf(br_name, sizeof(br_name),
723                                             "brvlan%d", vlan->vlan_id);
724                         }
725
726                         if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
727                                 br_delif(br_name, vlan->ifname);
728
729                         if (tagged_interface) {
730                                 if (vlan_naming ==
731                                     DYNAMIC_VLAN_NAMING_WITH_DEVICE)
732                                         os_snprintf(vlan_ifname,
733                                                     sizeof(vlan_ifname),
734                                                     "%s.%d", tagged_interface,
735                                                     vlan->vlan_id);
736                                 else
737                                         os_snprintf(vlan_ifname,
738                                                     sizeof(vlan_ifname),
739                                                     "vlan%d", vlan->vlan_id);
740
741                                 clean = dyn_iface_put(hapd, vlan_ifname);
742
743                                 if (clean & DVLAN_CLEAN_VLAN_PORT)
744                                         br_delif(br_name, vlan_ifname);
745
746                                 if (clean & DVLAN_CLEAN_VLAN) {
747                                         ifconfig_down(vlan_ifname);
748                                         vlan_rem(vlan_ifname);
749                                 }
750                         }
751
752                         clean = dyn_iface_put(hapd, br_name);
753                         if ((clean & DVLAN_CLEAN_BR) &&
754                             br_getnumports(br_name) == 0) {
755                                 ifconfig_down(br_name);
756                                 br_delbr(br_name);
757                         }
758                 }
759
760                 if (os_strcmp(ifname, vlan->ifname) == 0) {
761                         if (vlan == first) {
762                                 hapd->conf->vlan = vlan->next;
763                         } else {
764                                 prev->next = vlan->next;
765                         }
766                         os_free(vlan);
767
768                         break;
769                 }
770                 prev = vlan;
771                 vlan = vlan->next;
772         }
773 }
774
775
776 static void
777 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
778                   struct hostapd_data *hapd)
779 {
780         struct ifinfomsg *ifi;
781         int attrlen, nlmsg_len, rta_len;
782         struct rtattr *attr;
783         char ifname[IFNAMSIZ + 1];
784
785         if (len < sizeof(*ifi))
786                 return;
787
788         ifi = NLMSG_DATA(h);
789
790         nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
791
792         attrlen = h->nlmsg_len - nlmsg_len;
793         if (attrlen < 0)
794                 return;
795
796         attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
797
798         os_memset(ifname, 0, sizeof(ifname));
799         rta_len = RTA_ALIGN(sizeof(struct rtattr));
800         while (RTA_OK(attr, attrlen)) {
801                 if (attr->rta_type == IFLA_IFNAME) {
802                         int n = attr->rta_len - rta_len;
803                         if (n < 0)
804                                 break;
805
806                         if ((size_t) n >= sizeof(ifname))
807                                 n = sizeof(ifname) - 1;
808                         os_memcpy(ifname, ((char *) attr) + rta_len, n);
809
810                 }
811
812                 attr = RTA_NEXT(attr, attrlen);
813         }
814
815         if (!ifname[0])
816                 return;
817         if (del && if_nametoindex(ifname)) {
818                  /* interface still exists, race condition ->
819                   * iface has just been recreated */
820                 return;
821         }
822
823         wpa_printf(MSG_DEBUG,
824                    "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
825                    del ? "DEL" : "NEW",
826                    ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
827                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
828                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
829                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
830                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
831
832         if (del)
833                 vlan_dellink(ifname, hapd);
834         else
835                 vlan_newlink(ifname, hapd);
836 }
837
838
839 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
840 {
841         char buf[8192];
842         int left;
843         struct sockaddr_nl from;
844         socklen_t fromlen;
845         struct nlmsghdr *h;
846         struct hostapd_data *hapd = eloop_ctx;
847
848         fromlen = sizeof(from);
849         left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
850                         (struct sockaddr *) &from, &fromlen);
851         if (left < 0) {
852                 if (errno != EINTR && errno != EAGAIN)
853                         wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
854                                    __func__, strerror(errno));
855                 return;
856         }
857
858         h = (struct nlmsghdr *) buf;
859         while (NLMSG_OK(h, left)) {
860                 int len, plen;
861
862                 len = h->nlmsg_len;
863                 plen = len - sizeof(*h);
864                 if (len > left || plen < 0) {
865                         wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
866                                    "message: len=%d left=%d plen=%d",
867                                    len, left, plen);
868                         break;
869                 }
870
871                 switch (h->nlmsg_type) {
872                 case RTM_NEWLINK:
873                         vlan_read_ifnames(h, plen, 0, hapd);
874                         break;
875                 case RTM_DELLINK:
876                         vlan_read_ifnames(h, plen, 1, hapd);
877                         break;
878                 }
879
880                 h = NLMSG_NEXT(h, left);
881         }
882
883         if (left > 0) {
884                 wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
885                            "netlink message", __func__, left);
886         }
887 }
888
889
890 static struct full_dynamic_vlan *
891 full_dynamic_vlan_init(struct hostapd_data *hapd)
892 {
893         struct sockaddr_nl local;
894         struct full_dynamic_vlan *priv;
895
896         priv = os_zalloc(sizeof(*priv));
897         if (priv == NULL)
898                 return NULL;
899
900 #ifndef CONFIG_VLAN_NETLINK
901         vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
902                            DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
903                            VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
904                            VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
905 #endif /* CONFIG_VLAN_NETLINK */
906
907         priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
908         if (priv->s < 0) {
909                 wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
910                            "NETLINK_ROUTE) failed: %s",
911                            __func__, strerror(errno));
912                 os_free(priv);
913                 return NULL;
914         }
915
916         os_memset(&local, 0, sizeof(local));
917         local.nl_family = AF_NETLINK;
918         local.nl_groups = RTMGRP_LINK;
919         if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
920                 wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
921                            __func__, strerror(errno));
922                 close(priv->s);
923                 os_free(priv);
924                 return NULL;
925         }
926
927         if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
928         {
929                 close(priv->s);
930                 os_free(priv);
931                 return NULL;
932         }
933
934         return priv;
935 }
936
937
938 static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
939 {
940         if (priv == NULL)
941                 return;
942         eloop_unregister_read_sock(priv->s);
943         close(priv->s);
944         os_free(priv);
945 }
946 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
947
948
949 static int vlan_dynamic_add(struct hostapd_data *hapd,
950                             struct hostapd_vlan *vlan)
951 {
952         while (vlan) {
953                 if (vlan->vlan_id != VLAN_ID_WILDCARD) {
954                         if (vlan_if_add(hapd, vlan, 1)) {
955                                 wpa_printf(MSG_ERROR,
956                                            "VLAN: Could not add VLAN %s: %s",
957                                            vlan->ifname, strerror(errno));
958                                 return -1;
959                         }
960 #ifdef CONFIG_FULL_DYNAMIC_VLAN
961                         vlan_newlink(vlan->ifname, hapd);
962 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
963                 }
964
965                 vlan = vlan->next;
966         }
967
968         return 0;
969 }
970
971
972 static void vlan_dynamic_remove(struct hostapd_data *hapd,
973                                 struct hostapd_vlan *vlan)
974 {
975         struct hostapd_vlan *next;
976
977         while (vlan) {
978                 next = vlan->next;
979
980                 if (vlan->vlan_id != VLAN_ID_WILDCARD &&
981                     vlan_if_remove(hapd, vlan)) {
982                         wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
983                                    "iface: %s: %s",
984                                    vlan->ifname, strerror(errno));
985                 }
986 #ifdef CONFIG_FULL_DYNAMIC_VLAN
987                 if (vlan->clean)
988                         vlan_dellink(vlan->ifname, hapd);
989 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
990
991                 vlan = next;
992         }
993 }
994
995
996 int vlan_init(struct hostapd_data *hapd)
997 {
998 #ifdef CONFIG_FULL_DYNAMIC_VLAN
999         hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
1000 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1001
1002         if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
1003             !hapd->conf->vlan) {
1004                 /* dynamic vlans enabled but no (or empty) vlan_file given */
1005                 struct hostapd_vlan *vlan;
1006                 vlan = os_zalloc(sizeof(*vlan));
1007                 if (vlan == NULL) {
1008                         wpa_printf(MSG_ERROR, "Out of memory while assigning "
1009                                    "VLAN interfaces");
1010                         return -1;
1011                 }
1012
1013                 vlan->vlan_id = VLAN_ID_WILDCARD;
1014                 os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
1015                             hapd->conf->iface);
1016                 vlan->next = hapd->conf->vlan;
1017                 hapd->conf->vlan = vlan;
1018         }
1019
1020         if (vlan_dynamic_add(hapd, hapd->conf->vlan))
1021                 return -1;
1022
1023         return 0;
1024 }
1025
1026
1027 void vlan_deinit(struct hostapd_data *hapd)
1028 {
1029         vlan_dynamic_remove(hapd, hapd->conf->vlan);
1030
1031 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1032         full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
1033         hapd->full_dynamic_vlan = NULL;
1034 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1035 }
1036
1037
1038 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
1039                                        struct hostapd_vlan *vlan,
1040                                        int vlan_id)
1041 {
1042         struct hostapd_vlan *n = NULL;
1043         char *ifname, *pos;
1044
1045         if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
1046             vlan->vlan_id != VLAN_ID_WILDCARD)
1047                 return NULL;
1048
1049         wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
1050                    __func__, vlan_id, vlan->ifname);
1051         ifname = os_strdup(vlan->ifname);
1052         if (ifname == NULL)
1053                 return NULL;
1054         pos = os_strchr(ifname, '#');
1055         if (pos == NULL)
1056                 goto free_ifname;
1057         *pos++ = '\0';
1058
1059         n = os_zalloc(sizeof(*n));
1060         if (n == NULL)
1061                 goto free_ifname;
1062
1063         n->vlan_id = vlan_id;
1064         n->dynamic_vlan = 1;
1065
1066         os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
1067                     pos);
1068
1069         n->next = hapd->conf->vlan;
1070         hapd->conf->vlan = n;
1071
1072         /* hapd->conf->vlan needs this new VLAN here for WPA setup */
1073         if (vlan_if_add(hapd, n, 0)) {
1074                 hapd->conf->vlan = n->next;
1075                 os_free(n);
1076                 n = NULL;
1077                 goto free_ifname;
1078         }
1079
1080 free_ifname:
1081         os_free(ifname);
1082         return n;
1083 }
1084
1085
1086 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
1087 {
1088         struct hostapd_vlan *vlan;
1089
1090         if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
1091                 return 1;
1092
1093         wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
1094                    __func__, hapd->conf->iface, vlan_id);
1095
1096         vlan = hapd->conf->vlan;
1097         while (vlan) {
1098                 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
1099                         vlan->dynamic_vlan--;
1100                         break;
1101                 }
1102                 vlan = vlan->next;
1103         }
1104
1105         if (vlan == NULL)
1106                 return 1;
1107
1108         if (vlan->dynamic_vlan == 0) {
1109                 vlan_if_remove(hapd, vlan);
1110 #ifdef CONFIG_FULL_DYNAMIC_VLAN
1111                 vlan_dellink(vlan->ifname, hapd);
1112 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
1113         }
1114
1115         return 0;
1116 }