def validate_members(self): if self.members.get(IFACE_KEY_INDEX) is None: exit_NaCl(self.ctx.value(), "An index needs to be specified for all Ifaces") config = self.members.get(IFACE_KEY_CONFIG) if config is not None and (config.value_name() is None or config.value_name().getText().lower() not in PREDEFINED_CONFIG_TYPES): exit_NaCl(config, "Invalid config value " + config.getText()) vlan = self.members.get(IFACE_KEY_VLAN) # If this is a vlan, require a network configuration: if vlan is not None: if (config is None or config.value_name().getText().lower() != DHCP_CONFIG) and \ (self.members.get(IFACE_KEY_ADDRESS) is None or \ self.members.get(IFACE_KEY_NETMASK) is None): exit_NaCl(self.ctx.value(), "The members " + IFACE_KEY_ADDRESS + " and " + IFACE_KEY_NETMASK + \ " must be set for every Iface if the Iface configuration hasn't been set to " + DHCP_CONFIG) elif config is not None and config.value_name().getText().lower() == DHCP_CONFIG and \ (self.members.get(IFACE_KEY_ADDRESS) is not None or \ self.members.get(IFACE_KEY_NETMASK) is not None or \ self.members.get(IFACE_KEY_GATEWAY) is not None or \ self.members.get(IFACE_KEY_DNS) is not None): exit_NaCl(config.value_name(), "An Iface with config set to dhcp should not specify " + IFACE_KEY_ADDRESS + \ ", " + IFACE_KEY_NETMASK + ", " + IFACE_KEY_GATEWAY + " or " + IFACE_KEY_DNS) # It is not allowed (yet) to set buffer_limit or send_queue_limit on a vlan if self.members.get(IFACE_KEY_BUFFER_LIMIT) is not None or self.members.get(IFACE_KEY_SEND_QUEUE_LIMIT) is not None: exit_NaCl(self.ctx.value(), "The members send_queue_limit and buffer_limit can not be set on an Iface that is a vlan")
def add_push(self, chain, functions): # chain: string with name of chain # functions: list containing value_name ctxs, where each name corresponds to the name of a NaCl function add_auto_natting = False function_names = [] num_functions = len(functions) for i, function in enumerate(functions): name = function.getText() element = self.nacl_state.elements.get(name) if element is None or element.base_type != BASE_TYPE_FUNCTION: exit_NaCl(function, "No function with the name " + name + " exists") # If a Nat function is pushed onto an Iface's chain, # push the snat_translate lambda in cpp_template.mustache # onto the same Iface's postrouting chain # and push the dnat_translate lambda in cpp_template.mustache # onto the same Iface's prerouting chain if element.type_t.lower() == TYPE_NAT: add_auto_natting = True function_names.append({TEMPLATE_KEY_FUNCTION_NAME: name, TEMPLATE_KEY_COMMA: (i < (num_functions - 1))}) if add_auto_natting: self.nacl_state.append_to_pystache_data_list(TEMPLATE_KEY_AUTO_NATTING_IFACES, { TEMPLATE_KEY_IFACE: self.name }) self.nacl_state.append_to_pystache_data_list(TEMPLATE_KEY_IFACE_PUSHES, { TEMPLATE_KEY_NAME: self.name, TEMPLATE_KEY_CHAIN: chain, TEMPLATE_KEY_FUNCTION_NAMES: function_names })
def transpile_body_elements(self, type_t, subtype, body_elements): content = "" for e in body_elements: if e.conditional() is not None: content += self.transpile_conditional(type_t, subtype, e.conditional()) elif e.action() is not None: content += self.action_transpiler.transpile( type_t, subtype, e.action()) elif e.function() is not None: # Validate if valid type_t and subtype nested_type_t = e.function().type_t().getText() nested_subtype = e.function().subtype().getText() # Can only nest functions of the same type_t if type_t.lower() != nested_type_t.lower(): exit_NaCl(e.function().type_t(), "You cannot create a function of type " + \ nested_type_t + " inside a function of type " + type_t) # If this is a function, we have to validate that the subtype is legal based on the subtype of # the parent function if nested_subtype.lower() not in legal_nested_subtypes[ subtype.lower()]: exit_NaCl(e.function().subtype(), "You cannot create a function of subtype " + \ nested_subtype + " inside a function of subtype " + subtype) content += self.transpile(nested_type_t, nested_subtype, e.function(), subtype) return content
def add_timer(self): pystache_obj = { TEMPLATE_KEY_INTERVAL: self.members.get(TIMER_KEY_INTERVAL) } data = self.members.get(TIMER_KEY_DATA) if not isinstance(data, list): exit_NaCl(self.ctx, "Invalid value of Timer member " + TIMER_KEY_DATA + \ ". It needs to be a list containing one or more of these values: " + ", ".join(VALID_TIMER_DATA)) for val in data: if val == TIMER_DATA_VALUE_TIMESTAMP: pystache_obj[TEMPLATE_KEY_HAS_TIMESTAMP] = True elif val == TIMER_DATA_VALUE_STATS: pystache_obj[TEMPLATE_KEY_HAS_STATS] = True elif val == TIMER_DATA_VALUE_MEMORY: pystache_obj[TEMPLATE_KEY_HAS_MEMORY] = True elif val == TIMER_DATA_VALUE_CPU: pystache_obj[TEMPLATE_KEY_HAS_CPU] = True # elif val == TIMER_DATA_VALUE_STORAGE: # pystache_obj[TEMPLATE_KEY_HAS_STORAGE] = True elif val == TIMER_DATA_VALUE_LB: pystache_obj[TEMPLATE_KEY_HAS_LB] = True elif val == TIMER_DATA_VALUE_STACK_SAMPLING: pystache_obj[TEMPLATE_KEY_HAS_STACK_SAMPLING] = True elif val == TIMER_DATA_VALUE_TIMERS: pystache_obj[TEMPLATE_KEY_TIMER_HAS_TIMERS] = True else: exit_NaCl(self.ctx, "Invalid value of Timer member " + TIMER_KEY_DATA + \ ". Valid values are: " + ", ".join(VALID_TIMER_DATA)) self.nacl_state.append_to_pystache_data_list(TEMPLATE_KEY_TIMERS, pystache_obj)
def transpile(self, type_t, subtype, action_ctx): # def transpile_action_cpp(self, type_t, subtype, action_ctx): parameters = [] if action_ctx.value_list( ) is None else action_ctx.value_list().value() # list name = action_ctx.name().getText() name_lower = name.lower() if name_lower not in self.actions: # Then the action name could be the name of a function element = self.nacl_state.elements.get(name) if element is None or element.base_type != BASE_TYPE_FUNCTION: exit_NaCl(action_ctx, "Couldn't identify action or function name " + name) return self.transpile_function_call(name, parameters, type_t, subtype, action_ctx) # If get here, name is the name of an action in self.actions actions = self.legal_actions[type_t.lower()] if name_lower not in actions: exit_NaCl(action_ctx, "Error transpiling action " + name + ": Legal actions for a function of type " + \ type_t + " are: " + ", ".join(actions)) return self.actions[name_lower](parameters, subtype, action_ctx)
def add_push(self, chain, functions): # chain: string with name of chain # functions: list containing value_name ctxs, where each name corresponds to the name of a NaCl function function_names = [] num_functions = len(functions) for i, function in enumerate(functions): name = function.getText() element = self.nacl_state.elements.get(name) if element is None or element.base_type != BASE_TYPE_FUNCTION: exit_NaCl(function, "No function with the name " + name + " exists") if element.type_t.lower() == TYPE_NAT: exit_NaCl( function, "A Nat function cannot be pushed onto a Gateway's forward chain" ) function_names.append({ TEMPLATE_KEY_FUNCTION_NAME: name, TEMPLATE_KEY_COMMA: (i < (num_functions - 1)) }) router_obj_name = INCLUDEOS_ROUTER_OBJ_NAME if self.nacl_state.language == CPP else exit_NaCl(self.ctx, \ "Gateway can not transpile to other languages than C++") self.pushes.append({ TEMPLATE_KEY_NAME: router_obj_name, TEMPLATE_KEY_CHAIN: chain, TEMPLATE_KEY_FUNCTION_NAMES: function_names })
def transpile_nat(self, type_nat, parameter_ctx_list, subtype, action_ctx): if type_nat != SNAT and type_nat != DNAT: exit_NaCl_internal_error( "Internal error in transpile_nat_cpp: Invalid NAT type " + type_nat) # pckt_name = self.nacl_state.subtranspilers[VALUE_TRANSPILER].get_pckt_name(subtype) parameters = "" num_params = len(parameter_ctx_list) if num_params == 1: first = self.nacl_state.transpile_value(parameter_ctx_list[0]) # parameters = pckt_name + ", " + INCLUDEOS_CT_ENTRY + ", " + str(first) parameters = INCLUDEOS_DEREFERENCE_OP + IP_PCKT + ", " + INCLUDEOS_CT_ENTRY + ", " + str( first) elif num_params > 1: first = self.nacl_state.transpile_value(parameter_ctx_list[0]) second = self.nacl_state.transpile_value(parameter_ctx_list[1]) # parameters = pckt_name + ", " + INCLUDEOS_CT_ENTRY + ", {" + str(first) + ", " + str(second) + "}" parameters = INCLUDEOS_DEREFERENCE_OP + IP_PCKT + ", " + INCLUDEOS_CT_ENTRY + ", {" + str( first) + ", " + str(second) + "}" else: exit_NaCl(action_ctx, "No arguments provided to " + type_nat) return INCLUDEOS_NAT_OBJ_NAME + ARROW + type_nat + "(" + parameters + ");\n" + \ self.transpile_accept([], subtype, action_ctx)
def transpile_log(self, parameter_ctx_list, subtype, action_ctx): content = "std::cout << " if len(parameter_ctx_list) > 0: for i, p in enumerate(parameter_ctx_list): if p.string() is not None: content += self.nacl_state.transpile_value(p, subtype) else: t = self.nacl_state.subtranspilers[ VALUE_TRANSPILER].get_cout_convert_to_type(p) if t == TO_UNSIGNED: content += "static_cast<unsigned>(" + self.nacl_state.transpile_value( p, subtype) + ")" elif t == TO_STRING: content += self.nacl_state.transpile_value( p, subtype) + ".to_string()" else: exit_NaCl( p, "Internal error: std::cout conversion for " + t + " has not been implemented") if i < (len(parameter_ctx_list) - 1): content += " << " return content + ";\n"
def validate_dictionary_key(self, key, parent_key, level, value_ctx): class_name = self.get_class_name() if level == 1: if key.lower() not in PREDEFINED_TIMER_KEYS: exit_NaCl(value_ctx, "Invalid " + class_name + " member " + key) else: exit_NaCl(value_ctx, "Invalid " + class_name + " member " + key)
def transpile_numeric_value(self, numeric_value): if numeric_value.ipv4_addr() is not None: return self.transpile_ip4_addr(numeric_value.ipv4_addr()) if numeric_value.integer() is not None or \ numeric_value.decimal() is not None: return numeric_value.getText() exit_NaCl(numeric_value, "Undefined numeric value " + numeric_value.getText())
def get_cast(self, cast_to_proto, pckt_name, ctx): proto = cast_to_proto.lower() if proto not in cpp_pckt_classes: exit_NaCl(ctx, "Invalid protocol " + cast_to_proto) cpp_pckt_class = cpp_pckt_classes[proto] if proto != ICMP and pckt_name != ICMP_PCKT: return "static_cast<" + cpp_pckt_class + INCLUDEOS_REFERENCE_OP + ">(" + INCLUDEOS_DEREFERENCE_OP + pckt_name + ");" else: return INCLUDEOS_ICMP_PCKT_CLASS + "(std::move(" + IP_PCKT + "));"
def validate_and_process_not_route_members(self): for key, value_ctx in self.not_route_members.iteritems(): if key == GATEWAY_KEY_SEND_TIME_EXCEEDED: resolved_value = self.nacl_state.transpile_value(value_ctx) self.not_route_members[key] = resolved_value if resolved_value != TRUE and resolved_value != FALSE: exit_NaCl(value_ctx, "Invalid value of " + key + " (" + resolved_value + \ "). Must be set to " + TRUE + " or " + FALSE) elif key == GATEWAY_KEY_FORWARD: self.process_push(key, value_ctx)
def add_syslog(self): addr = self.members.get(SYSLOG_KEY_ADDRESS) port = self.members.get(SYSLOG_KEY_PORT) if addr is None or port is None: exit_NaCl(self.ctx, "Syslog address and/or port have not been specified") self.nacl_state.append_to_pystache_data_list(TEMPLATE_KEY_SYSLOGS, { TEMPLATE_KEY_ADDRESS: addr, TEMPLATE_KEY_PORT: port })
def resolve_element_values(self, element, ctx): # value in a function is the name of an element - resolve all values in this element # Base types: # UNTYPED_INIT # TYPED_INIT # FUNCTION if element.base_type == BASE_TYPE_FUNCTION: exit_NaCl(ctx, "The name of a function (" + element.name + \ ") cannot be used as a value name in a comparison") return self.transpile(element.ctx.value())
def transpile(self, val_ctx, subtype=""): if val_ctx is None: return "" # value: primitive_type | rng | string | value_name | obj | list_t; val = val_ctx.getText() if val_ctx.value_name() is not None: return self.transpile_value_name(val_ctx, subtype) if val_ctx.primitive_type() is not None: if val_ctx.primitive_type().numeric_type() is not None: return self.transpile_numeric_value( val_ctx.primitive_type().numeric_type()) if val_ctx.primitive_type().bool_val() is not None: return val.lower() if val_ctx.primitive_type().ipv4_cidr() is not None: return self.transpile_ip4_cidr( val_ctx.primitive_type().ipv4_cidr()) if val_ctx.rng() is not None: numeric_vals = val_ctx.rng().numeric_type() # list from_val = numeric_vals[0] to_val = numeric_vals[1] # For now we have three numeric_types: ipv4_addr, integer, decimal if (from_val.ipv4_addr() is not None and to_val.ipv4_addr() is not None) or \ (from_val.integer() is not None and to_val.integer() is not None) or \ (from_val.decimal() is not None and to_val.decimal() is not None): from_transpiled = self.transpile_numeric_value(from_val) to_transpiled = self.transpile_numeric_value(to_val) return [from_transpiled, to_transpiled] else: exit_NaCl( val_ctx, "A range's values need to be of the same type (" + val + ")") if val_ctx.string() is not None: return val_ctx.parser.getTokenStream().getText( interval=(val_ctx.start.tokenIndex, val_ctx.stop.tokenIndex)) if val_ctx.obj() is not None: return self.resolve_object(val_ctx.obj()) if val_ctx.list_t() is not None: return self.resolve_list_t(val_ctx.list_t()) exit_NaCl(val_ctx, "Undefined value " + val_ctx.getText())
def process_assignment(self, element_key): # print "process assignment Common" element = self.nacl_state.elements.get(element_key) name_parts = element_key.split(DOT) orig_member = name_parts[1] member = orig_member.lower() if len(name_parts) != 2: exit_NaCl( element.ctx, "Invalid " + self.get_class_name() + " member " + element.name) try: self.validate_key(orig_member) except NaCl_exception as e: exit_NaCl(element.ctx, e.value) if self.members.get(member) is not None: exit_NaCl(element.ctx, "Member " + member + " has already been set") found_element_value = element.ctx.value() try: self.add_member(member, found_element_value) except NaCl_exception as e: exit_NaCl(element.ctx, e.value)
def transpile_function_call(self, name, parameter_ctx_list, type_t, subtype, action_ctx): # This was the name of a function, and a function takes no parameters: if len(parameter_ctx_list) > 0: exit_NaCl(action_ctx, "A function call takes no parameters") element = self.nacl_state.elements.get(name) if element is None or element.base_type != BASE_TYPE_FUNCTION: exit_NaCl(action_ctx, "No function with the name " + name + " exists") # element is a Function # A function of type Filter can only call functions of type Filter, # a function of type Nat can only call functions of type Nat, etc. if element.type_t.lower() != type_t.lower(): exit_NaCl( action_ctx, "Error transpiling call to " + name + ": A function of type " + type_t + " can only call functions of the same type") if element.subtype.lower() not in legal_nested_subtypes[ subtype.lower()]: exit_NaCl( action_ctx, "Cannot call a function of subtype " + element.subtype + " inside a function of subtype " + subtype) # return e.process() # Cannot call this and use the element's process method and res attribute because # the pckt name will be affected of/be different based on the subtype of the parent function # Therefore: return self.nacl_state.subtranspilers[FUNCTION_TRANSPILER].transpile( element.type_t, element.subtype, element.ctx, subtype)
def add_conntrack(self): timeout = self.members.get(CONNTRACK_KEY_TIMEOUT) timeouts = [] if timeout is not None: class_name = self.get_class_name() if not isinstance(timeout, dict): exit_NaCl( self.ctx, "Invalid " + CONNTRACK_KEY_TIMEOUT + " value of " + class_name + " (needs to be an object)") for conntrack_type in timeout: t = timeout.get(conntrack_type) if not isinstance(t, dict): exit_NaCl( self.ctx, "Invalid " + conntrack_type + " value of " + class_name + " (needs to be an object)") tcp_timeout = t.get(TCP) udp_timeout = t.get(UDP) icmp_timeout = t.get(ICMP) timeouts.append({ TEMPLATE_KEY_CONNTRACK_TYPE: conntrack_type, TCP: tcp_timeout, UDP: udp_timeout, ICMP: icmp_timeout }) stateful = False stateful_tcp = self.members.get(CONNTRACK_KEY_STATEFUL_TCP) if stateful_tcp is not None and stateful_tcp == TRUE: stateful = True self.nacl_state.append_to_pystache_data_list( TEMPLATE_KEY_CONNTRACKS, { TEMPLATE_KEY_NAME: self.name, TEMPLATE_KEY_CONNTRACK_LIMIT: self.members.get(CONNTRACK_KEY_LIMIT), TEMPLATE_KEY_CONNTRACK_RESERVE: self.members.get(CONNTRACK_KEY_RESERVE), TEMPLATE_KEY_CONNTRACK_STATEFUL: stateful, TEMPLATE_KEY_CONNTRACK_TIMEOUTS: timeouts })
def transpile_ip4_addr(self, ip_addr_ctx): parts = ip_addr_ctx.Number() # list part0 = parts[0].getText() part1 = parts[1].getText() part2 = parts[2].getText() part3 = parts[3].getText() if int(part0) > BYTE_LIMIT or int(part1) > BYTE_LIMIT or int( part2) > BYTE_LIMIT or int(part3) > BYTE_LIMIT: exit_NaCl( ip_addr_ctx, "IPv4 addr " + ip_addr_ctx.getText() + " contains bytes greater than " + str(BYTE_LIMIT)) return INCLUDEOS_IP4_ADDR_CLASS + "{" + ip_addr_ctx.getText().replace( ".", ",") + "}"
def process_push(self, chain, value_ctx): functions = [] if value_ctx.list_t() is not None: # More than one function pushed onto chain for list_value in value_ctx.list_t().value_list().value(): if list_value.value_name() is None: exit_NaCl(list_value, "This is not supported: " + value_ctx.getText()) functions.append(list_value.value_name()) elif value_ctx.value_name() is not None: # Only one function pushed onto chain functions = [value_ctx.value_name()] else: exit_NaCl(value_ctx, "This is not supported: " + value_ctx.getText()) self.add_push(chain, functions)
def get_pckt_cast(self, subtype, ctx): subtype_lower = subtype.lower() if subtype_lower == IP: return "" # Already have (IP) pckt as input to Filter's operator() method pckt_name = pckt_names.get(subtype_lower) if pckt_name is not None: if pckt_name != ICMP_PCKT: return AUTO + INCLUDEOS_REFERENCE_OP + " " + pckt_name + " = " + self.get_cast( subtype_lower, IP_PCKT, ctx) else: return AUTO + " " + pckt_name + " = " + self.get_cast( subtype_lower, IP_PCKT, ctx) else: exit_NaCl( ctx, "Invalid subtype " + subtype + ", or pckt name or cpp pckt name not found")
def validate_dictionary_key(self, key, parent_key, level, value_ctx): if level == 1: if key not in predefined_lb_keys: exit_NaCl(value_ctx, "Invalid Load_balancer member " + key) elif level == 2: if parent_key == "": exit_NaCl( value_ctx, "Internal error: Parent key of " + key + " has not been given") if parent_key == LB_KEY_CLIENTS and key not in predefined_lb_clients_keys: exit_NaCl( value_ctx, "Invalid Load_balancer member " + key + " in " + self.name + "." + parent_key) if parent_key == LB_KEY_SERVERS and key not in predefined_lb_servers_keys: exit_NaCl( value_ctx, "Invalid Load_balancer member " + key + " in " + self.name + "." + parent_key) else: exit_NaCl(value_ctx, "Invalid Load_balancer member " + key)
def transpile_ip4_cidr(self, ip_cidr_ctx): parts = ip_cidr_ctx.ipv4_addr().Number() # list part0 = parts[0].getText() part1 = parts[1].getText() part2 = parts[2].getText() part3 = parts[3].getText() if int(part0) > BYTE_LIMIT or int(part1) > BYTE_LIMIT or int( part2) > BYTE_LIMIT or int(part3) > BYTE_LIMIT: exit_NaCl( ip_cidr_ctx, "IPv4 cidr " + ip_cidr_ctx.getText() + " contains bytes greater than " + str(BYTE_LIMIT)) mask = ip_cidr_ctx.cidr_mask().integer().getText() if int(mask) > MASK_LIMIT: exit_NaCl( ip_cidr_ctx, "IPv4 cidr mask in " + ip_cidr_ctx.getText() + " is greater than " + str(MASK_LIMIT)) return INCLUDEOS_IP4_CIDR_CLASS + "{" + part0 + "," + part1 + "," + part2 + "," + part3 + "," + mask + "}"
def construct_comparison(self, comp_ctx, resolved_lhs, resolved_rhs, comparison_op, op): lhs_is_list = True if isinstance(resolved_lhs, list) else False rhs_is_list = True if isinstance(resolved_rhs, list) else False result = "" # If none of these are lists, we have the resolved values if not lhs_is_list and not rhs_is_list: if INCLUDEOS_IP4_CIDR_CLASS in str(resolved_rhs): if comparison_op.lower() != IN: exit_NaCl(comp_ctx.comparison_operator(), "Invalid operator (" + comparison_op + "). Only the 'in' " + \ "operator is valid when comparing a property to a range, cidr, list or object") result = str(resolved_rhs) + ".contains(" + str( resolved_lhs) + ")" else: if comparison_op.lower() == IN: exit_NaCl(comp_ctx.comparison_operator(), "The 'in' operator can only be used when comparing a property to " + \ "a range, cidr, list or object") result = str(resolved_lhs) + " " + comparison_op + " " + str( resolved_rhs) if op != "": result = "(" + result + ") " + op + " " return result # If any of the resolved sides is a list, the 'in' operator should have been used # (rng, ip4_cidr, list_t, obj) if comparison_op != IN: exit_NaCl(comp_ctx.comparison_operator(), "Invalid operator (" + comparison_op + \ "). Only the 'in' operator is valid when comparing a value to a range, cidr, list or object") # If the 'in' operator has been used, only the resolved_rhs should be a list, not # the resolved_lhs if lhs_is_list: exit_NaCl(comp_ctx.lhs().value(), "The left hand side of a comparison can not resolve to a set " + \ "of values, e.g. a range, cidr, list or object") if rhs_is_list: result = self.construct_comparisons_from_list( resolved_rhs, resolved_lhs) if op != "": return "(" + result + ") " + op + " " return result
def transpile_conditional(self, type_t, subtype, cond): content = "" bodies = cond.body() num_bodies = len(bodies) if hasattr(cond, 'If') and cond.If() is not None: if num_bodies < 1: exit_NaCl(cond, "Invalid syntax") # If-body is always first (index 0) content += cond.If().getText() + " " + self.transpile_bool_expr(type_t, subtype, cond) + \ " {\n" + self.transpile_body_elements(type_t, subtype, bodies[0].body_element()) + "}\n" if hasattr(cond, 'Else') and cond.Else() is not None: if num_bodies < 2: exit_NaCl(cond, "Invalid syntax") # Else-body is always second/last (index 1) content += cond.Else().getText() + " {\n" + \ self.transpile_body_elements(type_t, subtype, bodies[1].body_element()) + "}\n" return content
def process_members(self): # Loop through self.members and transpile the values for key, member in self.members.iteritems(): if key != IFACE_KEY_CONFIG and key != IFACE_KEY_MASQUERADE: self.members[key] = self.nacl_state.transpile_value(member) # Validate that an Iface with this Iface's index has not already been defined if key == IFACE_KEY_INDEX: for key, el in self.nacl_state.elements.iteritems(): if isinstance(el, Iface) and key != self.name: el_idx = el.members.get(IFACE_KEY_INDEX) el_vlan = el.members.get(IFACE_KEY_VLAN) # If another Iface has been defined with the same index and neither this nor that Iface is a vlan # (has a vlan member), display an error if el_idx is not None and el_idx == self.members.get(IFACE_KEY_INDEX) and el_vlan is None and self.members.get(IFACE_KEY_VLAN) is None: exit_NaCl(member, "Another Iface has been defined with index " + el_idx) elif key == IFACE_KEY_CONFIG: self.members[IFACE_KEY_CONFIG] = member.value_name().getText().lower() else: masq_val = self.nacl_state.transpile_value(member) if not isinstance(masq_val, basestring) or (masq_val.lower() != TRUE and masq_val.lower() != FALSE): exit_NaCl(member, "Invalid masquerade value. Must be set to true or false") if masq_val == TRUE: self.nacl_state.append_to_pystache_data_list(TEMPLATE_KEY_MASQUERADES, { TEMPLATE_KEY_IFACE: self.name }) # Update config members config = self.members.get(IFACE_KEY_CONFIG) if config == DHCP_CONFIG: self.config_is_dhcp = True elif config == DHCP_FALLBACK_CONFIG: self.config_is_dhcp_fallback = True else: self.config_is_static = True
def get_pystache_route_obj(self, name, route_ctx): route_obj = {"ctx": route_ctx} pairs = route_ctx.key_value_list().key_value_pair() for pair in pairs: orig_key = pair.key().getText() key = orig_key.lower() if route_obj.get(key) is not None: exit_NaCl( pair.key(), "Member " + key + " has already been set for route " + name) if key not in PREDEFINED_GATEWAY_ROUTE_KEYS: exit_NaCl(pair.key(), orig_key + " is not a valid Gateway route member. " + \ "Valid members are: " + ", ".join(PREDEFINED_GATEWAY_ROUTE_KEYS)) if key != GATEWAY_KEY_IFACE: route_obj[key] = self.nacl_state.transpile_value(pair.value()) else: # Then the Iface element's name is to be added to the route_obj, # not the transpiled Iface iface_name = pair.value().getText() if pair.value().value_name() is None: exit_NaCl( pair.value(), "Gateway route member iface contains an invalid value (" + iface_name + ")") element = self.nacl_state.elements.get(iface_name) if element is None or (hasattr(element, 'type_t') and element.type_t.lower() != TYPE_IFACE): exit_NaCl( pair.value(), "No Iface with the name " + iface_name + " exists") route_obj[key] = iface_name return route_obj
def get_cout_convert_to_type(self, val_ctx): if val_ctx.value_name() is None: exit_NaCl(val_ctx, "This value can not be printed") name_parts = val_ctx.value_name().getText().split(DOT) name = name_parts[0] if len(name_parts) == 1: exit_NaCl(val_ctx, "This value can not be printed") if name.lower() not in proto_objects: exit_NaCl(val_ctx, name + " is not a valid protocol") name_parts.pop(0) properties = name_parts if len(properties) > 1: exit_NaCl( val_ctx, "Undefined protocol object properties: " + val_ctx.value_name().getText()) return proto_objects[name.lower()].get_cout_convert_to_type_cpp( properties[0].lower(), val_ctx)
def validate_members(self): if self.members.get(IFACE_KEY_INDEX) is None: exit_NaCl(self.ctx.value(), "An index needs to be specified for all Ifaces") config = self.members.get(IFACE_KEY_CONFIG) if config is not None and (config.value_name() is None or config.value_name().getText().lower() not in PREDEFINED_CONFIG_TYPES): exit_NaCl(config, "Invalid config value " + config.getText()) if (config is None or config.value_name().getText().lower() != DHCP_CONFIG) and \ (self.members.get(IFACE_KEY_ADDRESS) is None or \ self.members.get(IFACE_KEY_NETMASK) is None): exit_NaCl(self.ctx.value(), "The members " + IFACE_KEY_ADDRESS + " and " + IFACE_KEY_NETMASK + \ " must be set for every Iface if the Iface configuration hasn't been set to " + DHCP_CONFIG) elif config is not None and config.value_name().getText().lower() == DHCP_CONFIG and \ (self.members.get(IFACE_KEY_ADDRESS) is not None or \ self.members.get(IFACE_KEY_NETMASK) is not None or \ self.members.get(IFACE_KEY_GATEWAY) is not None or \ self.members.get(IFACE_KEY_DNS) is not None): exit_NaCl(config.value_name(), "An Iface with config set to dhcp should not specify " + IFACE_KEY_ADDRESS + \ ", " + IFACE_KEY_NETMASK + ", " + IFACE_KEY_GATEWAY + " or " + IFACE_KEY_DNS)
def validate_members(self): vlan_index = self.members.get(VLAN_KEY_INDEX) vlan_address = self.members.get(VLAN_KEY_ADDRESS) vlan_netmask = self.members.get(VLAN_KEY_NETMASK) if vlan_index is None or vlan_address is None or vlan_netmask is None: exit_NaCl( self.ctx, "The members index, address and netmask must be set for every Vlan" ) if vlan_index.obj() is not None or vlan_index.list_t() is not None: exit_NaCl( vlan_index, "The Vlan member " + VLAN_KEY_INDEX + " can not be an object") if vlan_address.obj() is not None or vlan_address.list_t() is not None: exit_NaCl( vlan_address, "The Vlan member " + VLAN_KEY_ADDRESS + " can not be an object") if vlan_netmask.obj() is not None or vlan_netmask.list_t() is not None: exit_NaCl( vlan_netmask, "The Vlan member " + VLAN_KEY_NETMASK + " can not be an object")