📄 vlan_init.c
字号:
/* * hostapd / VLAN initialization * Copyright 2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "hostapd.h"#include "driver.h"#include "vlan_init.h"#ifdef CONFIG_FULL_DYNAMIC_VLAN#include <net/if.h>#include <sys/ioctl.h>#include <linux/sockios.h>#include <linux/if_vlan.h>#include <linux/if_bridge.h>#include "priv_netlink.h"#include "eloop.h"struct full_dynamic_vlan { int s; /* socket on which to listen for new/removed interfaces. */};static int ifconfig_helper(const char *if_name, int up){ int fd; struct ifreq ifr; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); return -1; } os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ); if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { perror("ioctl[SIOCGIFFLAGS]"); close(fd); return -1; } if (up) ifr.ifr_flags |= IFF_UP; else ifr.ifr_flags &= ~IFF_UP; if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { perror("ioctl[SIOCSIFFLAGS]"); close(fd); return -1; } close(fd); return 0;}static int ifconfig_up(const char *if_name){ return ifconfig_helper(if_name, 1);}static int ifconfig_down(const char *if_name){ return ifconfig_helper(if_name, 0);}/* * These are only available in recent linux headers (without the leading * underscore). */#define _GET_VLAN_REALDEV_NAME_CMD 8#define _GET_VLAN_VID_CMD 9/* This value should be 256 ONLY. If it is something else, then hostapd * might crash!, as this value has been hard-coded in 2.4.x kernel * bridging code. */#define MAX_BR_PORTS 256static int br_delif(const char *br_name, const char *if_name){ int fd; struct ifreq ifr; unsigned long args[2]; int if_index; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); return -1; } if_index = if_nametoindex(if_name); if (if_index == 0) { printf("Failure determining interface index for '%s'\n", if_name); close(fd); return -1; } args[0] = BRCTL_DEL_IF; args[1] = if_index; os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); ifr.ifr_data = (__caddr_t) args; if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) { /* No error if interface already removed. */ perror("ioctl[SIOCDEVPRIVATE,BRCTL_DEL_IF]"); close(fd); return -1; } close(fd); return 0;}/* Add interface 'if_name' to the bridge 'br_name' returns -1 on error returns 1 if the interface is already part of the bridge returns 0 otherwise*/static int br_addif(const char *br_name, const char *if_name){ int fd; struct ifreq ifr; unsigned long args[2]; int if_index; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); return -1; } if_index = if_nametoindex(if_name); if (if_index == 0) { printf("Failure determining interface index for '%s'\n", if_name); close(fd); return -1; } args[0] = BRCTL_ADD_IF; args[1] = if_index; os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); ifr.ifr_data = (__caddr_t) args; if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { if (errno == EBUSY) { /* The interface is already added. */ close(fd); return 1; } perror("ioctl[SIOCDEVPRIVATE,BRCTL_ADD_IF]"); close(fd); return -1; } close(fd); return 0;}static int br_delbr(const char *br_name){ int fd; unsigned long arg[2]; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); return -1; } arg[0] = BRCTL_DEL_BRIDGE; arg[1] = (unsigned long) br_name; if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) { /* No error if bridge already removed. */ perror("ioctl[BRCTL_DEL_BRIDGE]"); close(fd); return -1; } close(fd); return 0;}/* Add a bridge with the name 'br_name'. returns -1 on error returns 1 if the bridge already exists returns 0 otherwise*/static int br_addbr(const char *br_name){ int fd; unsigned long arg[2]; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); return -1; } arg[0] = BRCTL_ADD_BRIDGE; arg[1] = (unsigned long) br_name; if (ioctl(fd, SIOCGIFBR, arg) < 0) { if (errno == EEXIST) { /* The bridge is already added. */ close(fd); return 1; } else { perror("ioctl[BRCTL_ADD_BRIDGE]"); close(fd); return -1; } } close(fd); return 0;}static int br_getnumports(const char *br_name){ int fd; int i; int port_cnt = 0; unsigned long arg[4]; int ifindices[MAX_BR_PORTS]; struct ifreq ifr; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); return -1; } arg[0] = BRCTL_GET_PORT_LIST; arg[1] = (unsigned long) ifindices; arg[2] = MAX_BR_PORTS; arg[3] = 0; os_memset(ifindices, 0, sizeof(ifindices)); os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); ifr.ifr_data = (__caddr_t) arg; if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { perror("ioctl[SIOCDEVPRIVATE,BRCTL_GET_PORT_LIST]"); close(fd); return -1; } for (i = 1; i < MAX_BR_PORTS; i++) { if (ifindices[i] > 0) { port_cnt++; } } close(fd); return port_cnt;}static int vlan_rem(const char *if_name){ int fd; struct vlan_ioctl_args if_request; if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { fprintf(stderr, "Interface name to long.\n"); return -1; } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); 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) { perror("ioctl[SIOCSIFVLAN,DEL_VLAN_CMD]"); 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*/static int vlan_add(const char *if_name, int vid){ int fd; struct vlan_ioctl_args if_request; ifconfig_up(if_name); if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { fprintf(stderr, "Interface name to long.\n"); return -1; } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); 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 (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); 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) { perror("ioctl[SIOCSIFVLAN,ADD_VLAN_CMD]"); close(fd); return -1; } close(fd); return 0;}static int vlan_set_name_type(unsigned int name_type){ int fd; struct vlan_ioctl_args if_request; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket[AF_INET,SOCK_STREAM]"); 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) { perror("ioctl[SIOCSIFVLAN,SET_VLAN_NAME_TYPE_CMD]"); close(fd); return -1; } close(fd); return 0;}static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -