blob: 0086016800a0632d7022efc9bbdd5c5aae87fa92 [file] [log] [blame]
Rich Lanecc327672014-04-10 13:37:35 -07001:: # Copyright 2014, Big Switch Networks, Inc.
2:: #
3:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4:: # the following special exception:
5:: #
6:: # LOXI Exception
7:: #
8:: # As a special exception to the terms of the EPL, you may distribute libraries
9:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
11:: # from the LoxiGen Libraries and the notice provided below is (i) included in
12:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13:: # documentation for the LoxiGen Libraries, if distributed in binary form.
14:: #
15:: # Notice: "Copyright 2014, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16:: #
17:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18:: # a copy of the EPL at:
19:: #
20:: # http://www.eclipse.org/legal/epl-v10.html
21:: #
22:: # Unless required by applicable law or agreed to in writing, software
23:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25:: # EPL for the specific language governing permissions and limitations
26:: # under the EPL.
27::
28:: include('_copyright.c')
29:: import loxi_globals
Rich Lane18391592014-04-10 15:27:00 -070030:: from loxi_ir import *
Rich Lanecc327672014-04-10 13:37:35 -070031
32/**
33 *
34 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
35 *
36 * Source file for OpenFlow message validation.
37 *
38 */
39
40#include "loci_log.h"
41#include <loci/loci.h>
42#include <loci/loci_validator.h>
43
44#define VALIDATOR_LOG(...) LOCI_LOG_ERROR("Validator Error: " __VA_ARGS__)
45
Rich Laned7692fc2014-04-10 16:21:38 -070046:: raw_validator_name = lambda cls, version: "loci_validate_%s_%s" % (cls, version.constant_version(prefix='OF_VERSION_'))
Rich Lane18391592014-04-10 15:27:00 -070047:: validator_name = lambda ofclass: "loci_validate_%s_%s" % (ofclass.name, ofclass.protocol.version.constant_version(prefix='OF_VERSION_'))
48
49/* Forward declarations */
50:: for version, proto in loxi_globals.ir.items():
51:: for ofclass in proto.classes:
Rich Laned7692fc2014-04-10 16:21:38 -070052static int __attribute__((unused)) ${validator_name(ofclass)}(uint8_t *data, int len, int *out_len);
Rich Lane18391592014-04-10 15:27:00 -070053:: #endfor
54:: #endfor
55
56:: readers = { 1: 'buf_u8_get', 2: 'buf_u16_get', 4: 'buf_u32_get' }
57:: types = { 1: 'uint8_t', 2: 'uint16_t', 4: 'uint32_t' }
58
59:: for version, proto in loxi_globals.ir.items():
Rich Laned7692fc2014-04-10 16:21:38 -070060
61:: # Identify classes in lists and generate list validators
62:: seen_lists = set()
63:: for ofclass in proto.classes:
64:: for m in ofclass.members:
65:: if type(m) == OFDataMember and m.oftype.startswith('list'):
66:: element_name = m.oftype[8:-3]
67:: if element_name in seen_lists:
68:: continue
69:: #endif
70:: seen_lists.add(element_name)
71:: list_validator_name = raw_validator_name('of_list_' + element_name, version)
72static int __attribute__((unused))
73${list_validator_name}(uint8_t *data, int len, int *out_len)
74{
75 while (len > 0) {
76 int cur_len = 0xffff;
77 if (${raw_validator_name('of_' + element_name, version)}(data, len, &cur_len) < 0) {
78 return -1;
79 }
80 len -= cur_len;
81 data += cur_len;
82 }
83
84 return 0;
85}
86
87:: #endif
88:: #endfor
89:: #endfor
90
Rich Lane18391592014-04-10 15:27:00 -070091:: for ofclass in proto.classes:
92static int
Rich Laned7692fc2014-04-10 16:21:38 -070093${validator_name(ofclass)}(uint8_t *data, int len, int *out_len)
Rich Lane18391592014-04-10 15:27:00 -070094{
95 if (len < ${ofclass.base_length}) {
96 return -1;
97 }
98
Rich Laned7692fc2014-04-10 16:21:38 -070099:: if ofclass.is_fixed_length:
100 len = ${ofclass.base_length};
101:: #endif
102
Rich Lane18391592014-04-10 15:27:00 -0700103:: # Read and validate length fields
Rich Laned7692fc2014-04-10 16:21:38 -0700104:: field_length_members = {}
Rich Lane18391592014-04-10 15:27:00 -0700105:: for m in ofclass.members:
106:: if type(m) == OFLengthMember:
107 ${types[m.length]} wire_len;
108 ${readers[m.length]}(data + ${m.offset}, &wire_len);
109 if (wire_len > len || wire_len < ${ofclass.base_length}) {
110 return -1;
111 }
112
113 len = wire_len;
Rich Lanef3575712014-04-10 17:37:05 -0700114
Rich Laned7692fc2014-04-10 16:21:38 -0700115:: elif type(m) == OFFieldLengthMember:
Rich Lanef3575712014-04-10 17:37:05 -0700116:: # Read field length members
Rich Laned7692fc2014-04-10 16:21:38 -0700117:: field_length_members[m.field_name] = m
Rich Lanef3575712014-04-10 17:37:05 -0700118 ${types[m.length]} wire_len_${m.field_name};
119 ${readers[m.length]}(data + ${m.offset}, &wire_len_${m.field_name});
120
Rich Lane18391592014-04-10 15:27:00 -0700121:: #endif
122:: #endfor
123
124:: # Dispatch to subclass validators
125:: if ofclass.virtual:
126:: discriminator = ofclass.discriminator
127 ${types[discriminator.length]} wire_type;
128 ${readers[discriminator.length]}(data + ${discriminator.offset}, &wire_type);
129 switch (wire_type) {
130:: for subclass in proto.classes:
131:: if subclass.superclass == ofclass:
132 case ${subclass.member_by_name(discriminator.name).value}:
Rich Laned7692fc2014-04-10 16:21:38 -0700133 return ${validator_name(subclass)}(data, len, out_len);
Rich Lane18391592014-04-10 15:27:00 -0700134:: #endif
135:: #endfor
136 }
137:: #endif
138
Rich Laned7692fc2014-04-10 16:21:38 -0700139:: for m in ofclass.members:
Rich Lanef3575712014-04-10 17:37:05 -0700140:: # Validate field-length members
141:: if type(m) == OFDataMember and m.name in field_length_members and m.offset is not None:
142 if (${m.offset} + wire_len_${m.name} > len) {
143 return -1;
144 }
145
146:: #endif
Rich Laned7692fc2014-04-10 16:21:38 -0700147:: if type(m) == OFDataMember and m.oftype.startswith('list') and m.offset is not None:
Rich Lanef3575712014-04-10 17:37:05 -0700148:: # Validate fixed-offset lists
Rich Lane12181e12014-04-10 17:39:27 -0700149:: if not m.name in field_length_members:
150 int wire_len_${m.name} = len - ${m.offset};
Rich Laned7692fc2014-04-10 16:21:38 -0700151:: #endif
152:: element_name = m.oftype[8:-3]
153:: list_validator_name = raw_validator_name('of_list_' + element_name, version)
Rich Lane12181e12014-04-10 17:39:27 -0700154 if (${list_validator_name}(data + ${m.offset}, wire_len_${m.name}, out_len) < 0) {
Rich Laned7692fc2014-04-10 16:21:38 -0700155 return -1;
156 }
157
158:: #endif
159:: #endfor
160
161:: # TODO handle non-fixed-offset lists
162
163 *out_len = len;
Rich Lane18391592014-04-10 15:27:00 -0700164 return 0;
165}
166
167:: #endfor
168:: #endfor
169
Rich Lanecc327672014-04-10 13:37:35 -0700170int
171of_validate_message(of_message_t msg, int len)
172{
173 of_version_t version;
174 if (len < OF_MESSAGE_MIN_LENGTH ||
175 len != of_message_length_get(msg)) {
176 VALIDATOR_LOG("message length %d != %d", len,
177 of_message_length_get(msg));
178 return -1;
179 }
180
181 version = of_message_version_get(msg);
Rich Laned7692fc2014-04-10 16:21:38 -0700182 int out_len;
Rich Lanecc327672014-04-10 13:37:35 -0700183 switch (version) {
184:: for version, proto in loxi_globals.ir.items():
185 case ${version.constant_version(prefix='OF_VERSION_')}:
Rich Laned7692fc2014-04-10 16:21:38 -0700186 return ${validator_name(proto.class_by_name('of_header'))}(msg, len, &out_len);
Rich Lanecc327672014-04-10 13:37:35 -0700187:: #endfor
188 default:
189 VALIDATOR_LOG("Bad version %d", OF_VERSION_1_3);
190 return -1;
191 }
192}