Merged the hostap_2.6 updates, and the Leap of Faith work, from the hostap_update...
[mech_eap.git] / libeap / src / ap / vlan_ioctl.c
diff --git a/libeap/src/ap/vlan_ioctl.c b/libeap/src/ap/vlan_ioctl.c
new file mode 100644 (file)
index 0000000..987b612
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * hostapd / VLAN ioctl API
+ * Copyright 2003, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <sys/ioctl.h>
+
+#include "utils/common.h"
+#include "common/linux_vlan.h"
+#include "vlan_util.h"
+
+
+int vlan_rem(const char *if_name)
+{
+       int fd;
+       struct vlan_ioctl_args if_request;
+
+       wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
+       if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
+               wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
+                          if_name);
+               return -1;
+       }
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+               wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+                          "failed: %s", __func__, strerror(errno));
+               return -1;
+       }
+
+       os_memset(&if_request, 0, sizeof(if_request));
+
+       os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
+       if_request.cmd = DEL_VLAN_CMD;
+
+       if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
+               wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
+                          "%s", __func__, if_name, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return 0;
+}
+
+
+/*
+       Add a vlan interface with VLAN ID 'vid' and tagged interface
+       'if_name'.
+
+       returns -1 on error
+       returns 1 if the interface already exists
+       returns 0 otherwise
+*/
+int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
+{
+       int fd;
+       struct vlan_ioctl_args if_request;
+
+       wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
+                  if_name, vid);
+       ifconfig_up(if_name);
+
+       if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
+               wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
+                          if_name);
+               return -1;
+       }
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+               wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+                          "failed: %s", __func__, strerror(errno));
+               return -1;
+       }
+
+       os_memset(&if_request, 0, sizeof(if_request));
+
+       /* Determine if a suitable vlan device already exists. */
+
+       os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
+                   vid);
+
+       if_request.cmd = GET_VLAN_VID_CMD;
+
+       if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
+           if_request.u.VID == vid) {
+               if_request.cmd = GET_VLAN_REALDEV_NAME_CMD;
+
+               if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
+                   os_strncmp(if_request.u.device2, if_name,
+                              sizeof(if_request.u.device2)) == 0) {
+                       close(fd);
+                       wpa_printf(MSG_DEBUG,
+                                  "VLAN: vlan_add: if_name %s exists already",
+                                  if_request.device1);
+                       return 1;
+               }
+       }
+
+       /* A suitable vlan device does not already exist, add one. */
+
+       os_memset(&if_request, 0, sizeof(if_request));
+       os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
+       if_request.u.VID = vid;
+       if_request.cmd = ADD_VLAN_CMD;
+
+       if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
+               wpa_printf(MSG_ERROR,
+                          "VLAN: %s: ADD_VLAN_CMD failed for %s: %s",
+                          __func__, if_request.device1, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return 0;
+}
+
+
+int vlan_set_name_type(unsigned int name_type)
+{
+       int fd;
+       struct vlan_ioctl_args if_request;
+
+       wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
+                  name_type);
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+               wpa_printf(MSG_ERROR,
+                          "VLAN: %s: socket(AF_INET,SOCK_STREAM) failed: %s",
+                          __func__, strerror(errno));
+               return -1;
+       }
+
+       os_memset(&if_request, 0, sizeof(if_request));
+
+       if_request.u.name_type = name_type;
+       if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
+       if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
+               wpa_printf(MSG_ERROR,
+                          "VLAN: %s: SET_VLAN_NAME_TYPE_CMD name_type=%u failed: %s",
+                          __func__, name_type, strerror(errno));
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return 0;
+}