/*====================================================================*
*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted (subject to the limitations
* in the disclaimer below) provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* * Neither the name of Qualcomm Atheros nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
* COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*--------------------------------------------------------------------*/
/*====================================================================*
*
* signed ParseRule (int * argcp, char const * argvp [], struct rule * rule, struct cspec * cspec);
*
* rules.h
*
* This module takes an argument vector and an argument count
* and fills in a classification rule structure that is suitable for
* sending in a VS_CLASSIFICATION MME;
*
* This module is currently used by plcrule and pibruin;
*
*
* Contributor(s):
* Charles Maier <cmaier@qca.qualcomm.com>
* Nathaniel Houghton <nhoughto@qca.qualcomm.com>
*
*--------------------------------------------------------------------*/
#include <memory.h>
#include <errno.h>
#include "../tools/memory.h"
#include "../tools/number.h"
#include "../tools/error.h"
#include "../ether/ether.h"
#include "../plc/rules.h"
signed ParseRule (int * argcp, char const ** argvp [], struct MMERule * rule, struct cspec * cspec)
{
int argc = * argcp;
char const ** argv = * argvp;
union
{
uint32_t wide;
uint16_t word;
uint8_t byte [4];
}
temp;
signed code;
struct MMEClassifier * classifier = (struct MMEClassifier *) (& rule->CLASSIFIER);
if ((code = lookup (* argv++, actions, SIZEOF (actions))) == -1)
{
assist (* -- argv, CLASSIFIER_ACTION_NAME, actions, SIZEOF (actions));
}
rule->MACTION = (uint8_t) (code);
argc--;
if ((code = lookup (* argv++, operands, SIZEOF (operands))) == -1)
{
assist (* -- argv, CLASSIFIER_OPERAND_NAME, operands, SIZEOF (operands));
}
rule->MOPERAND = (uint8_t) (code);
argc--;
while ((* argv) && (lookup (* argv, controls, SIZEOF (controls)) == -1))
{
if ((code = lookup (* argv++, fields, SIZEOF (fields))) == -1)
{
assist (* -- argv, CLASSIFIER_FIELD_NAME, fields, SIZEOF (fields));
}
classifier->CR_PID = (uint8_t) (code);
argc--;
if ((code = lookup (* argv++, operators, SIZEOF (operators))) == -1)
{
assist (* -- argv, CLASSIFIER_OPERATOR_NAME, operators, SIZEOF (operators));
}
classifier->CR_OPERAND = (uint8_t) (code);
argc--;
if (! argc || ! * argv)
{
error (1, ENOTSUP, "I have %s '%s' but no value", CLASSIFIER_OPERATOR_NAME, * -- argv);
}
switch (classifier->CR_PID)
{
case FIELD_ETH_SA:
case FIELD_ETH_DA:
bytespec (* argv++, classifier->CR_VALUE, ETHER_ADDR_LEN);
break;
case FIELD_IPV4_SA:
case FIELD_IPV4_DA:
ipv4spec (* argv++, classifier->CR_VALUE);
break;
case FIELD_IPV6_SA:
case FIELD_IPV6_DA:
ipv6spec (* argv++, classifier->CR_VALUE);
break;
case FIELD_VLAN_UP:
case FIELD_IPV6_TC:
case FIELD_IPV4_TOS:
case FIELD_IPV4_PROT:
classifier->CR_VALUE [0] = (uint8_t) (basespec (* argv++, 0, sizeof (classifier->CR_VALUE [0])));
break;
case FIELD_VLAN_ID:
case FIELD_TCP_SP:
case FIELD_TCP_DP:
case FIELD_UDP_SP:
case FIELD_UDP_DP:
case FIELD_IP_SP:
case FIELD_IP_DP:
temp.word = (uint16_t) (basespec (* argv++, 0, sizeof (temp.word)));
temp.word = htons (temp.word);
memcpy (classifier->CR_VALUE, & temp, sizeof (temp.word));
break;
case FIELD_ETH_TYPE:
temp.word = (uint16_t) (basespec (* argv++, 0, sizeof (temp.word)));
temp.word = htons (temp.word);
memcpy (classifier->CR_VALUE, & temp, sizeof (temp.word));
break;
case FIELD_IPV6_FL:
temp.wide = (uint32_t) (basespec (* argv++, 0, sizeof (temp.wide))) & 0x000FFFFF;
temp.wide = htonl (temp.wide);
memcpy (classifier->CR_VALUE, & temp.byte [1], 3);
break;
case FIELD_HPAV_MME:
bytespec (* argv++, classifier->CR_VALUE, sizeof (uint16_t) + sizeof (uint8_t));
temp.byte [0] = classifier->CR_VALUE [1];
classifier->CR_VALUE [1] = classifier->CR_VALUE [2];
classifier->CR_VALUE [2] = temp.byte [0];
break;
case FIELD_TCP_ACK:
if ((code = lookup (* argv++, states, SIZEOF (states))) == -1)
{
assist (* -- argv, CLASSIFIER_STATE_NAME, states, SIZEOF (states));
}
memset (classifier->CR_VALUE, 0, sizeof (classifier->CR_VALUE));
break;
case FIELD_VLAN_TAG:
if ((code = lookup (* argv++, states, SIZEOF (states))) == -1)
{
assist (* -- argv, CLASSIFIER_STATE_NAME, states, SIZEOF (states));
}
memset (classifier->CR_VALUE, 0, sizeof (classifier->CR_VALUE));
classifier->CR_OPERAND ^= code;
break;
default:
error (1, ENOTSUP, "%s", argv [- 2]);
break;
}
rule->NUM_CLASSIFIERS++;
classifier++;
argc--;
}
memcpy (classifier, cspec, sizeof (* cspec));
if ((code = lookup (* argv++, controls, SIZEOF (controls))) == -1)
{
assist (* -- argv, CLASSIFIER_CONTROL_NAME, controls, SIZEOF (controls));
}
rule->MCONTROL = (uint8_t) (code);
argc--;
if ((code = lookup (* argv++, volatilities, SIZEOF (volatilities))) == -1)
{
assist (* -- argv, CLASSIFIER_VOLATILITY_NAME, volatilities, SIZEOF (volatilities));
}
rule->MVOLATILITY = (uint8_t) (code);
argc--;
* argcp = argc;
* argvp = argv;
return (0);
}