|
Packit Service |
646995 |
/*
|
|
Packit Service |
646995 |
* Copyright (c) 2009-2011, Broadcom Corporation
|
|
Packit Service |
646995 |
* Copyright (c) 2014, QLogic Corporation
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* Written by: Benjamin Li (benli@broadcom.com)
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* All rights reserved.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
646995 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
646995 |
* are met:
|
|
Packit Service |
646995 |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit Service |
646995 |
* notice, this list of conditions and the following disclaimer.
|
|
Packit Service |
646995 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit Service |
646995 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit Service |
646995 |
* documentation and/or other materials provided with the distribution.
|
|
Packit Service |
646995 |
* 3. All advertising materials mentioning features or use of this software
|
|
Packit Service |
646995 |
* must display the following acknowledgement:
|
|
Packit Service |
646995 |
* This product includes software developed by Adam Dunkels.
|
|
Packit Service |
646995 |
* 4. The name of the author may not be used to endorse or promote
|
|
Packit Service |
646995 |
* products derived from this software without specific prior
|
|
Packit Service |
646995 |
* written permission.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
Packit Service |
646995 |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
Packit Service |
646995 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit Service |
646995 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
Packit Service |
646995 |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit Service |
646995 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
Packit Service |
646995 |
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit Service |
646995 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
Packit Service |
646995 |
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
Packit Service |
646995 |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
Packit Service |
646995 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* nic_vlan.c - uIP user space stack VLAN utilities
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
#define _GNU_SOURCE
|
|
Packit Service |
646995 |
#include <errno.h>
|
|
Packit Service |
646995 |
#include <fcntl.h>
|
|
Packit Service |
646995 |
#include <pthread.h>
|
|
Packit Service |
646995 |
#include <string.h>
|
|
Packit Service |
646995 |
#include <stdio.h>
|
|
Packit Service |
646995 |
#include <stdlib.h>
|
|
Packit Service |
646995 |
#include <unistd.h>
|
|
Packit Service |
646995 |
#include <sys/types.h>
|
|
Packit Service |
646995 |
#include <sys/stat.h>
|
|
Packit Service |
646995 |
#include <sys/stat.h>
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
#include <arpa/inet.h>
|
|
Packit Service |
646995 |
#include <sys/types.h>
|
|
Packit Service |
646995 |
#include <sys/socket.h>
|
|
Packit Service |
646995 |
#include <sys/un.h>
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
#include "logger.h"
|
|
Packit Service |
646995 |
#include "nic.h"
|
|
Packit Service |
646995 |
#include "nic_utils.h"
|
|
Packit Service |
646995 |
#include "nic_vlan.h"
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/*******************************************************************************
|
|
Packit Service |
646995 |
* Constants
|
|
Packit Service |
646995 |
******************************************************************************/
|
|
Packit Service |
646995 |
#define PFX "vlan"
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
static const char proc_vlan_config_path[] = "/proc/net/vlan/config";
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/*******************************************************************************
|
|
Packit Service |
646995 |
* Resolving Found VLAN's for CNIC
|
|
Packit Service |
646995 |
******************************************************************************/
|
|
Packit Service |
646995 |
int init_vlan_found_handle(struct vlan_found_handle *found_handle,
|
|
Packit Service |
646995 |
struct vlan_handle *handle)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
memset(found_handle, 0, sizeof(*found_handle));
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
found_handle->entries = malloc(found_handle->num_of_entries *
|
|
Packit Service |
646995 |
sizeof(struct vlan_found_entry));
|
|
Packit Service |
646995 |
if (found_handle->entries == NULL) {
|
|
Packit Service |
646995 |
LOG_ERR("Could not allocate space for found entries");
|
|
Packit Service |
646995 |
return -ENOMEM;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
found_handle->handle = handle;
|
|
Packit Service |
646995 |
found_handle->num_of_entries = handle->num_of_entries;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
memset(found_handle->entries, 0, found_handle->num_of_entries *
|
|
Packit Service |
646995 |
sizeof(struct vlan_found_entry));
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
handle->outstanding_found_handles++;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return 0;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
void release_vlan_found_handle(struct vlan_found_handle *found_handle)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
if (found_handle->entries != NULL) {
|
|
Packit Service |
646995 |
free(found_handle->entries);
|
|
Packit Service |
646995 |
found_handle->entries = NULL;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
found_handle->num_of_entries = 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
found_handle->handle->outstanding_found_handles--;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
found_handle->handle = NULL;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/*******************************************************************************
|
|
Packit Service |
646995 |
* Resolving VLAN's for CNIC
|
|
Packit Service |
646995 |
******************************************************************************/
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* init_vlan_handle() - Used to initialize struct ipv4_route_handle so
|
|
Packit Service |
646995 |
* that is can be used
|
|
Packit Service |
646995 |
* @param handle - Pointer to struct ipv4_route_handle to initialize
|
|
Packit Service |
646995 |
* @return 0 on success and <0 on failure
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
void init_vlan_table(struct vlan_handle *handle)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
handle->entries = NULL;
|
|
Packit Service |
646995 |
handle->num_of_entries = 0;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* parse_vlan_table() - Given the raw dump of a Linux vlan table, this
|
|
Packit Service |
646995 |
* function will parse the into entries held by
|
|
Packit Service |
646995 |
* struct vlan_handle
|
|
Packit Service |
646995 |
* @param handle - struct vlan_handle used to hold the parsed contents
|
|
Packit Service |
646995 |
* @param raw - buffer to parse the contents from
|
|
Packit Service |
646995 |
* @param raw_size - size of the buffer in bytes
|
|
Packit Service |
646995 |
* @return 0 on success, <0 on failure
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
int parse_vlan_table(struct vlan_handle *handle, char *raw, uint32_t raw_size)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
FILE *fp;
|
|
Packit Service |
646995 |
int i;
|
|
Packit Service |
646995 |
char *token;
|
|
Packit Service |
646995 |
size_t size;
|
|
Packit Service |
646995 |
int rc;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
token = raw;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/* determine the number of entries */
|
|
Packit Service |
646995 |
while (*token != '\0') {
|
|
Packit Service |
646995 |
if (*token == '\n')
|
|
Packit Service |
646995 |
handle->num_of_entries++;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
token++;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/* There are 2 lines which describe the vlan table
|
|
Packit Service |
646995 |
* This lines need to be skipped with counting */
|
|
Packit Service |
646995 |
handle->num_of_entries -= 2;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
LOG_INFO("Number of vlan entries: %d", handle->num_of_entries);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
size = handle->num_of_entries * sizeof(struct vlan_entry);
|
|
Packit Service |
646995 |
handle->entries = malloc(size);
|
|
Packit Service |
646995 |
if (handle->entries == NULL) {
|
|
Packit Service |
646995 |
LOG_ERR
|
|
Packit Service |
646995 |
("Couldn't malloc space to parse vlan table. entires: %d "
|
|
Packit Service |
646995 |
"size: %d",
|
|
Packit Service |
646995 |
handle->num_of_entries, size);
|
|
Packit Service |
646995 |
return -ENOMEM;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
fp = fmemopen(raw, raw_size, "r");
|
|
Packit Service |
646995 |
if (fp == NULL) {
|
|
Packit Service |
646995 |
LOG_ERR("Could not open raw dump of vlan table");
|
|
Packit Service |
646995 |
rc = errno;
|
|
Packit Service |
646995 |
goto fmemopen_error;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
|
|
Packit Service |
646995 |
LOG_ERR("Empty or missing line, or read error");
|
|
Packit Service |
646995 |
rc = -EIO;
|
|
Packit Service |
646995 |
goto error;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the second line. */
|
|
Packit Service |
646995 |
LOG_ERR("Empty or missing line, or read error");
|
|
Packit Service |
646995 |
rc = -EIO;
|
|
Packit Service |
646995 |
goto error;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
i = 0;
|
|
Packit Service |
646995 |
/* Time to parse the routing table */
|
|
Packit Service |
646995 |
while (1) {
|
|
Packit Service |
646995 |
struct vlan_entry *entry = &handle->entries[i];
|
|
Packit Service |
646995 |
int r;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
r = fscanf(fp, "%15s |%hu |%15s",
|
|
Packit Service |
646995 |
entry->vlan_iface_name,
|
|
Packit Service |
646995 |
&entry->vlan_id, entry->phy_iface_name);
|
|
Packit Service |
646995 |
if (r != 3) {
|
|
Packit Service |
646995 |
if (feof(fp)) { /* EOF with no (nonspace) chars read. */
|
|
Packit Service |
646995 |
break;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
LOG_WARN("Parsing error: parsed %d elements", r);
|
|
Packit Service |
646995 |
break;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
i++;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
LOG_DEBUG("Vlan %d: vlan iface:%s vlan id:%d phys iface:%s",
|
|
Packit Service |
646995 |
i,
|
|
Packit Service |
646995 |
entry->vlan_iface_name,
|
|
Packit Service |
646995 |
entry->vlan_id, entry->phy_iface_name);
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
fclose(fp);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
error:
|
|
Packit Service |
646995 |
fclose(fp);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
fmemopen_error:
|
|
Packit Service |
646995 |
if (handle->entries != NULL)
|
|
Packit Service |
646995 |
free(handle->entries);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return rc;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* capture_vlan_table() - This function will snapshot the Linux vlan
|
|
Packit Service |
646995 |
* routing table for further processing
|
|
Packit Service |
646995 |
* @param handle - struct vlan_handle used to hold the routing context
|
|
Packit Service |
646995 |
* @return 0 on success, <0 on failure
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
int capture_vlan_table(struct vlan_handle *handle)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
char *raw = NULL;
|
|
Packit Service |
646995 |
uint32_t raw_size = 0;
|
|
Packit Service |
646995 |
int rc;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
rc = capture_file(&raw, &raw_size, proc_vlan_config_path);
|
|
Packit Service |
646995 |
if (rc != 0)
|
|
Packit Service |
646995 |
goto error;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
rc = parse_vlan_table(handle, raw, raw_size);
|
|
Packit Service |
646995 |
if (rc != 0)
|
|
Packit Service |
646995 |
goto error;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
error:
|
|
Packit Service |
646995 |
if (raw != NULL)
|
|
Packit Service |
646995 |
free(raw);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return rc;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* release_vlan_table() - This function will free all resources used by
|
|
Packit Service |
646995 |
* the handle
|
|
Packit Service |
646995 |
* @param handle - struct vlan_handle used to hold the routing context
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
void release_vlan_table(struct vlan_handle *handle)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
if (handle->entries != NULL) {
|
|
Packit Service |
646995 |
free(handle->entries);
|
|
Packit Service |
646995 |
handle->entries = NULL;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
handle->num_of_entries = 0;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* find_phy_using_vlan_interface() - Given the interface name determine VLAN
|
|
Packit Service |
646995 |
* tag ID to match either the physical or VLAN interface name
|
|
Packit Service |
646995 |
* @param vlan_iface_name - VLAN interface used to find the physical
|
|
Packit Service |
646995 |
* interface
|
|
Packit Service |
646995 |
* @param phy_iface_name - returned value is the physical interface name
|
|
Packit Service |
646995 |
* @param vlan_id - returned value is the VLAN id
|
|
Packit Service |
646995 |
* @return 1 is returned if the interface is a VLAN, 0 if the interface is not
|
|
Packit Service |
646995 |
* <0 is returned if there is an error
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
int find_phy_using_vlan_interface(struct vlan_handle *handle,
|
|
Packit Service |
646995 |
char *vlan_iface_name,
|
|
Packit Service |
646995 |
char **phy_iface_name, uint16_t *vlan_id)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
int i, rc = 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
for (i = 0; i < handle->num_of_entries; i++) {
|
|
Packit Service |
646995 |
struct vlan_entry *entry = &handle->entries[i];
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/* Compare VLAN interface names to find a match */
|
|
Packit Service |
646995 |
if (strcmp(entry->vlan_iface_name, vlan_iface_name) == 0) {
|
|
Packit Service |
646995 |
*phy_iface_name = entry->phy_iface_name;
|
|
Packit Service |
646995 |
*vlan_id = entry->vlan_id;
|
|
Packit Service |
646995 |
rc = 1;
|
|
Packit Service |
646995 |
break;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return rc;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* find_vlans_using_phy_interface() - Given the physical interface name this
|
|
Packit Service |
646995 |
* function will determine the VLAN interface name and VLAN ID
|
|
Packit Service |
646995 |
* @param iface_name - physical interface used to find the vlan interface
|
|
Packit Service |
646995 |
* @param vlan_iface_name - returned value is the VLAN interface name
|
|
Packit Service |
646995 |
* @return The number of VLAN interfaces found
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
int find_vlans_using_phy_interface(struct vlan_handle *handle,
|
|
Packit Service |
646995 |
struct vlan_found_handle *found_handle,
|
|
Packit Service |
646995 |
char *phy_iface_name)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
int i, num_found = 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
for (i = 0; i < handle->num_of_entries; i++) {
|
|
Packit Service |
646995 |
struct vlan_entry *entry = &handle->entries[i];
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/* Compare interface names to find a match */
|
|
Packit Service |
646995 |
if (strcmp(entry->phy_iface_name, phy_iface_name) == 0) {
|
|
Packit Service |
646995 |
found_handle->entries[i].found = VLAN_ENTRY_FOUND;
|
|
Packit Service |
646995 |
num_found++;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return num_found;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/**
|
|
Packit Service |
646995 |
* valid_vlan() - determine if the vlan value which is passed is valid
|
|
Packit Service |
646995 |
* @param vlan - vlan value to test
|
|
Packit Service |
646995 |
* @return 0 - not valid, 1 - valid
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
int valid_vlan(short int vlan)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
/* Allow vlan 1 to connect */
|
|
Packit Service |
646995 |
if (vlan > 0 && vlan < 4095)
|
|
Packit Service |
646995 |
return 1;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return 0;
|
|
Packit Service |
646995 |
}
|