Blame iscsiuio/src/unix/nic_vlan.c

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
}