1e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt/*
2e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * hostapd / VLAN ioctl API
3e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Copyright 2003, Instant802 Networks, Inc.
4e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Copyright 2005-2006, Devicescape Software, Inc.
5e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt *
7e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * This software may be distributed under the terms of the BSD license.
8e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * See README for more details.
9e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt */
10e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
11e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#include "utils/includes.h"
12e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#include <sys/ioctl.h>
13e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
14e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#include "utils/common.h"
15e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#include "common/linux_vlan.h"
16e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt#include "vlan_util.h"
17e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
18e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
19e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint vlan_rem(const char *if_name)
20e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{
21e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	int fd;
22e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	struct vlan_ioctl_args if_request;
23e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
24e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
25e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
26e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
27e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   if_name);
28e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
29e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
30e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
31e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
32e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
33e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   "failed: %s", __func__, strerror(errno));
34e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
35e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
36e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
37e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_memset(&if_request, 0, sizeof(if_request));
38e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
39e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
40e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if_request.cmd = DEL_VLAN_CMD;
41e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
42e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
43e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
44e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   "%s", __func__, if_name, strerror(errno));
45e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		close(fd);
46e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
47e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
48e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
49e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	close(fd);
50e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	return 0;
51e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt}
52e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
53e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
54e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt/*
55e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	Add a vlan interface with VLAN ID 'vid' and tagged interface
56e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	'if_name'.
57e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
58e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	returns -1 on error
59e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	returns 1 if the interface already exists
60e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	returns 0 otherwise
61e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt*/
62e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint vlan_add(const char *if_name, int vid, const char *vlan_if_name)
63e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{
64e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	int fd;
65e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	struct vlan_ioctl_args if_request;
66e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
67e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
68e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		   if_name, vid);
69e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	ifconfig_up(if_name);
70e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
71e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
72e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
73e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   if_name);
74e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
75e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
76e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
77e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
78e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
79e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   "failed: %s", __func__, strerror(errno));
80e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
81e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
82e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
83e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_memset(&if_request, 0, sizeof(if_request));
84e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
85e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	/* Determine if a suitable vlan device already exists. */
86e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
87e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
88e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		    vid);
89e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
90e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if_request.cmd = GET_VLAN_VID_CMD;
91e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
92e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
93e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	    if_request.u.VID == vid) {
94e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		if_request.cmd = GET_VLAN_REALDEV_NAME_CMD;
95e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
96e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
97e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		    os_strncmp(if_request.u.device2, if_name,
98e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			       sizeof(if_request.u.device2)) == 0) {
99e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			close(fd);
100e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			wpa_printf(MSG_DEBUG,
101e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt				   "VLAN: vlan_add: if_name %s exists already",
102e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt				   if_request.device1);
103e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			return 1;
104e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		}
105e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
106e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
107e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	/* A suitable vlan device does not already exist, add one. */
108e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
109e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_memset(&if_request, 0, sizeof(if_request));
110e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
111e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if_request.u.VID = vid;
112e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if_request.cmd = ADD_VLAN_CMD;
113e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
114e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
115e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR,
116e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   "VLAN: %s: ADD_VLAN_CMD failed for %s: %s",
117e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   __func__, if_request.device1, strerror(errno));
118e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		close(fd);
119e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
120e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
121e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
122e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	close(fd);
123e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	return 0;
124e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt}
125e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
126e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
127e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint vlan_set_name_type(unsigned int name_type)
128e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt{
129e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	int fd;
130e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	struct vlan_ioctl_args if_request;
131e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
132e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
133e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		   name_type);
134e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
135e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR,
136e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   "VLAN: %s: socket(AF_INET,SOCK_STREAM) failed: %s",
137e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   __func__, strerror(errno));
138e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
139e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
140e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
141e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	os_memset(&if_request, 0, sizeof(if_request));
142e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
143e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if_request.u.name_type = name_type;
144e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
145e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
146e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		wpa_printf(MSG_ERROR,
147e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   "VLAN: %s: SET_VLAN_NAME_TYPE_CMD name_type=%u failed: %s",
148e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			   __func__, name_type, strerror(errno));
149e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		close(fd);
150e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		return -1;
151e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	}
152e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
153e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	close(fd);
154e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	return 0;
155e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt}
156