/* * Parse numbers */ static int string_to_number_ll(struct ipset_session *session, const char *str, unsigned long long min, unsigned long long max, unsigned long long *ret) { unsigned long long number = 0; char *end; /* Handle hex, octal, etc. */ errno = 0; number = strtoull(str, &end, 0); if (*end == '\0' && end != str && errno != ERANGE) { /* we parsed a number, let's see if we want this */ if (min <= number && (!max || number <= max)) { *ret = number; return 0; } else errno = ERANGE; } if (errno == ERANGE && max) return syntax_err("'%s' is out of range %llu-%llu", str, min, max); else if (errno == ERANGE) return syntax_err("'%s' is out of range %llu-%llu", str, min, ULLONG_MAX); else return syntax_err("'%s' is invalid as number", str); }
Tuple remove_duplicate_labels(Tuple label_list) /*;remove_duplicate_labels*/ { Tuple new_label_list = tup_new(0), label_id_set = tup_new(0); Fortup ft1, ft2; Node tmp_node, tmp_node2, node, label; FORTUP(tmp_node = (Node), label_list, ft1); if (N_KIND((node = tmp_node)) == as_simple_name) { if (in_label_set(node, label_id_set)) syntax_err(SPAN(node),"Duplicate label name"); else { /* new_label_list = concatl(new_label_list,initlist(node)); */ label_id_set = tup_with(label_id_set, (char *)node); } new_label_list = tup_with(new_label_list, (char *)node); } else { FORTUP(tmp_node2 = (Node), N_LIST(node), ft2); label = tmp_node2; if (in_label_set(label,label_id_set)) syntax_err(SPAN(label),"Duplicate label name"); else label_id_set = tup_with(label_id_set, (char *)label); ENDFORTUP(ft2); } ENDFORTUP(ft1) /* if (label_id_set != (struct two_pool *)0) TFREE(label_id_set->link,label_id_set); if (label_list != (struct two_pool *)0) TFREE(label_list->link,label_list); */ return(new_label_list); }
// Obtain the name of the RegMask for an InstructForm const char *ArchDesc::reg_mask(InstructForm &inForm) { const char *result = inForm.reduce_result(); if (result == NULL) { syntax_err(inForm._linenum, "Did not find result operand or RegMask" " for this instruction: %s", inForm._ident); abort(); } // Instructions producing 'Universe' use RegMask::Empty if( strcmp(result,"Universe")==0 ) { return "RegMask::Empty"; } // Lookup this result operand and get its register class Form *form = (Form*)_globalNames[result]; if (form == NULL) { syntax_err(inForm._linenum, "Did not find result operand for result: %s", result); abort(); } OperandForm *oper = form->is_operand(); if (oper == NULL) { syntax_err(inForm._linenum, "Form is not an OperandForm:"); form->dump(); abort(); } return reg_mask( *oper ); }
/** * ipset_parse_iptimeout - parse IPv4|IPv6 address and timeout * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as an IPv4|IPv6 address and timeout parameter. * If family is not set yet in the data blob, INET is assumed. * The value is stored in the data blob of the session. * * Compatibility parser. * * Returns 0 on success or a negative error code. */ int ipset_parse_iptimeout(struct ipset_session *session, enum ipset_opt opt, const char *str) { char *tmp, *saved, *a; int err; assert(session); assert(opt == IPSET_OPT_IP); assert(str); /* IP,timeout */ if (ipset_data_flags_test(ipset_session_data(session), IPSET_FLAG(IPSET_OPT_TIMEOUT))) return syntax_err("mixed syntax, timeout already specified"); tmp = saved = strdup(str); if (saved == NULL) return ipset_err(session, "Cannot allocate memory to duplicate %s.", str); a = elem_separator(tmp); if (a == NULL) { free(saved); return syntax_err("Missing separator from %s", str); } *a++ = '\0'; err = parse_ip(session, opt, tmp, IPADDR_ANY); if (!err) err = ipset_parse_uint32(session, IPSET_OPT_TIMEOUT, a); free(saved); return err; }
/** * ipset_parse_family - parse INET|INET6 family names * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as an INET|INET6 family name. * The value is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_family(struct ipset_session *session, enum ipset_opt opt, const char *str) { struct ipset_data *data; uint8_t family; assert(session); assert(opt == IPSET_OPT_FAMILY); assert(str); data = ipset_session_data(session); if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FAMILY))) syntax_err("protocol family may not be specified " "multiple times"); if (STREQ(str, "inet") || STREQ(str, "ipv4") || STREQ(str, "-4")) family = AF_INET; else if (STREQ(str, "inet6") || STREQ(str, "ipv6") || STREQ(str, "-6")) family = AF_INET6; else if (STREQ(str, "any") || STREQ(str, "unspec")) family = AF_UNSPEC; else return syntax_err("unknown INET family %s", str); return ipset_data_set(data, opt, &family); }
// Build MatchList structures for instructions void ArchDesc::inspectInstructions() { // Iterate through all instructions _instructions.reset(); InstructForm *instr; for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) { // Construct list of top-level operands (components) instr->build_components(); // Ensure that match field is defined. if ( instr->_matrule == NULL ) continue; MatchRule &mrule = *instr->_matrule; Predicate *pred = instr->build_predicate(); // Grab the machine type of the operand const char *rootOp = instr->_ident; mrule._machType = rootOp; // Cost for this match const char *costStr = instr->cost(); const char *defaultCost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef; const char *cost = costStr? costStr : defaultCost; // Find result type for match const char *result = instr->reduce_result(); if ( (instr->is_ideal_branch() && instr->label_position() == -1) || (!instr->is_ideal_branch() && instr->label_position() != -1)) { syntax_err(instr->_linenum, "%s: Only branches to a label are supported\n", rootOp); } Attribute *attr = instr->_attribs; while (attr != NULL) { if (strcmp(attr->_ident,"ins_short_branch") == 0 && attr->int_val(*this) != 0) { if (!instr->is_ideal_branch() || instr->label_position() == -1) { syntax_err(instr->_linenum, "%s: Only short branch to a label is supported\n", rootOp); } instr->set_short_branch(true); } else if (strcmp(attr->_ident,"ins_alignment") == 0 && attr->int_val(*this) != 0) { instr->set_alignment(attr->int_val(*this)); } attr = (Attribute *)attr->_next; } if (!instr->is_short_branch()) { buildMatchList(instr->_matrule, result, mrule._machType, pred, cost); } } }
void check_choices(Node alt_node, char *source) /*;check_choices*/ { Tuple choice_list, others_indices = tup_new(0); Node tmp_node, tmp_node2, last_alt = (Node) 0; Fortup ft1, ft2; int choice_flag = 0; FORTUP(tmp_node = (Node), N_LIST(alt_node), ft1); if (N_KIND(tmp_node) != as_pragma) { choice_list = N_LIST(N_AST1(tmp_node)); if (tup_size(choice_list) > 1) { FORTUP(tmp_node2 = (Node), choice_list, ft2); if (N_KIND(tmp_node2) == as_others || N_KIND(tmp_node2) == as_others_choice) { char msg[90]; sprintf(msg,"The choice OTHERS must appear alone in %s", source); syntax_err(SPAN(tmp_node2),msg); choice_flag = 1; break; } ENDFORTUP(ft2); } if (!choice_flag) { if (N_KIND((Node)choice_list[1]) == as_others || N_KIND((Node)choice_list[1]) == as_others_choice) others_indices = tup_with(others_indices, (char *)tmp_node); } else choice_flag = 0; last_alt = tmp_node; } ENDFORTUP(ft1); FORTUP(tmp_node = (Node), others_indices, ft1); { Node choice; char msg[90]; if (tmp_node == last_alt) continue; choice = (Node)N_LIST(N_AST1(tmp_node))[1]; sprintf(msg,"The choice OTHERS must appear last in %s",source); syntax_err(SPAN(choice),msg); } ENDFORTUP(ft1); /* if (others_indices != (struct two_pool *)0 ) TFREE(others_indices->link,others_indices); */ }
/** * ipset_parse_netmask - parse string as a CIDR netmask value * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as a CIDR netmask value, depending on family type. * If family is not set yet, INET is assumed. * The value is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_netmask(struct ipset_session *session, enum ipset_opt opt, const char *str) { uint8_t family, cidr; struct ipset_data *data; int err = 0; assert(session); assert(opt == IPSET_OPT_NETMASK); assert(str); data = ipset_session_data(session); family = ipset_data_family(data); if (family == AF_UNSPEC) { family = AF_INET; ipset_data_set(data, IPSET_OPT_FAMILY, &family); } err = string_to_cidr(session, str, family == AF_INET ? 1 : 4, family == AF_INET ? 31 : 124, &cidr); if (err) return syntax_err("netmask is out of the inclusive range " "of %u-%u", family == AF_INET ? 1 : 4, family == AF_INET ? 31 : 124); return ipset_data_set(data, opt, &cidr); }
/** * ipset_parse_ether - parse ethernet address * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as an ethernet address. The parsed ethernet * address is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_ether(struct ipset_session *session, enum ipset_opt opt, const char *str) { unsigned int i = 0; unsigned char ether[ETH_ALEN]; assert(session); assert(opt == IPSET_OPT_ETHER); assert(str); if (strlen(str) != ETH_ALEN * 3 - 1) goto error; for (i = 0; i < ETH_ALEN; i++) { long number; char *end; number = strtol(str + i * 3, &end, 16); if (end == str + i * 3 + 2 && (*end == ':' || *end == '\0') && number >= 0 && number <= 255) ether[i] = number; else goto error; } return ipset_session_data_set(session, opt, ether); error: return syntax_err("cannot parse '%s' as ethernet address", str); }
static int get_addrinfo(struct ipset_session *session, enum ipset_opt opt, const char *str, struct addrinfo **info, uint8_t family) { struct addrinfo *i; size_t addrlen = family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); int found, err = 0; if ((*info = call_getaddrinfo(session, str, family)) == NULL) { syntax_err("cannot parse %s: resolving to %s address failed", str, family == AF_INET ? "IPv4" : "IPv6"); return EINVAL; } for (i = *info, found = 0; i != NULL; i = i->ai_next) { if (i->ai_family != family || i->ai_addrlen != addrlen) continue; if (found == 0) { if (family == AF_INET) { /* Workaround: direct cast increases required alignment on Sparc */ const struct sockaddr_in *saddr = (void *)i->ai_addr; err = ipset_session_data_set(session, opt, &saddr->sin_addr); } else { /* Workaround: direct cast increases required alignment on Sparc */ const struct sockaddr_in6 *saddr = (void *)i->ai_addr; err = ipset_session_data_set(session, opt, &saddr->sin6_addr); } } else if (found == 1) { ipset_warn(session, "%s resolves to multiple addresses: " "using only the first one returned " "by the resolver", str); } found++; } if (found == 0) return syntax_err("cannot parse %s: " "%s address could not be resolved", str, family == AF_INET ? "IPv4" : "IPv6"); return err; }
static int string_to_cidr(struct ipset_session *session, const char *str, uint8_t min, uint8_t max, uint8_t *ret) { int err = string_to_u8(session, str, ret); if (!err && (*ret < min || *ret > max)) return syntax_err("'%s' is out of range %u-%u", str, min, max); return err; }
/** * ipset_parse_name_compat - parse setname as element * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as a setname or a setname element to add to a set. * The pattern "setname,before|after,setname" is recognized and * parsed. * The value is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_name_compat(struct ipset_session *session, enum ipset_opt opt, const char *str) { char *saved; char *a = NULL, *b = NULL, *tmp; int err, before = 0; const char *sep = IPSET_ELEM_SEPARATOR; struct ipset_data *data; assert(session); assert(opt == IPSET_OPT_NAME); assert(str); data = ipset_session_data(session); if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF))) syntax_err("mixed syntax, before|after option already used"); tmp = saved = strdup(str); if (saved == NULL) return ipset_err(session, "Cannot allocate memory to duplicate %s.", str); if ((a = elem_separator(tmp)) != NULL) { /* setname,[before|after,setname */ *a++ = '\0'; if ((b = elem_separator(a)) != NULL) *b++ = '\0'; if (b == NULL || !(STREQ(a, "before") || STREQ(a, "after"))) { err = ipset_err(session, "you must specify elements " "as setname%s[before|after]%ssetname", sep, sep); goto out; } before = STREQ(a, "before"); } check_setname(tmp, saved); if ((err = ipset_data_set(data, opt, tmp)) != 0 || b == NULL) goto out; check_setname(b, saved); if ((err = ipset_data_set(data, IPSET_OPT_NAMEREF, b)) != 0) goto out; if (before) err = ipset_data_set(data, IPSET_OPT_BEFORE, &before); out: free(saved); return err; }
/** * ipset_parse_ipnet - parse IPv4|IPv6 address or address/cidr pattern * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as an IPv4|IPv6 address or address/cidr pattern. * If family is not set yet in the data blob, INET is assumed. * The value is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_ipnet(struct ipset_session *session, enum ipset_opt opt, const char *str) { assert(session); assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2); assert(str); if (range_separator(str)) return syntax_err("IP address or IP/cidr must be specified: %s", str); return parse_ip(session, opt, str, IPADDR_ANY); }
/** * ipset_parse_proto - parse protocol name * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as a protocol name. * The parsed protocol is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_proto(struct ipset_session *session, enum ipset_opt opt, const char *str) { const struct protoent *protoent; uint8_t proto = 0; assert(session); assert(opt == IPSET_OPT_PROTO); assert(str); protoent = getprotobyname(strcasecmp(str, "icmpv6") == 0 ? "ipv6-icmp" : str); if (protoent == NULL) return syntax_err("cannot parse '%s' " "as a protocol name", str); proto = protoent->p_proto; if (!proto) return syntax_err("Unsupported protocol '%s'", str); return ipset_session_data_set(session, opt, &proto); }
/* * Parse TCP service names or port numbers */ static int parse_portname(struct ipset_session *session, const char *str, uint16_t *port, const char *proto) { struct servent *service; if ((service = getservbyname(str, proto)) != NULL) { *port = ntohs((uint16_t) service->s_port); return 0; } return syntax_err("cannot parse '%s' as a %s port", str, proto); }
void check_discrete_range(Node discrete_range) /*;check_discrete_range*/ { /* Check whether a discrete range node is valid. */ switch (N_KIND(discrete_range)) { case as_range_expression : #define name (N_AST1(discrete_range)) if (!check_expanded_name(name)) syntax_err(SPAN(discrete_range), "Invalid discrete_range specification"); else N_KIND(discrete_range) = as_name; break; #undef name case as_range_attribute : case as_subtype : break; default : syntax_err(SPAN(discrete_range), "Invalid discrete_range specification"); } }
static int parse_ip(struct ipset_session *session, enum ipset_opt opt, const char *str, enum ipaddr_type addrtype) { struct ipset_data *data = ipset_session_data(session); uint8_t family = ipset_data_family(data); if (family == AF_UNSPEC) { family = AF_INET; ipset_data_set(data, IPSET_OPT_FAMILY, &family); } switch (addrtype) { case IPADDR_PLAIN: if (range_separator(str) || (cidr_separator(str) && !cidr_hostaddr(str, family))) return syntax_err("plain IP address must be supplied: %s", str); break; case IPADDR_NET: if (!cidr_separator(str) || range_separator(str)) return syntax_err("IP/netblock must be supplied: %s", str); break; case IPADDR_RANGE: if (!range_separator(str) || cidr_separator(str)) return syntax_err("IP-IP range must supplied: %s", str); break; case IPADDR_ANY: default: break; } return parse_ipaddr(session, opt, str, family); }
// Convert a register class name to its register mask. const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) { const char *reg_mask = "RegMask::Empty"; if( _register ) { RegClass *reg_class = _register->getRegClass(rc_name); if (reg_class == NULL) { syntax_err(0, "Use of an undefined register class %s", rc_name); return reg_mask; } // Construct the name of the register mask. reg_mask = getRegMask(rc_name); } return reg_mask; }
// Obtain the name of the RegMask for an OperandForm const char *ArchDesc::reg_mask(OperandForm &opForm) { const char *regMask = "RegMask::Empty"; // Check constraints on result's register class const char *result_class = opForm.constrained_reg_class(); if (result_class == NULL) { opForm.dump(); syntax_err(opForm._linenum, "Use of an undefined result class for operand: %s", opForm._ident); abort(); } regMask = reg_class_to_reg_mask( result_class ); return regMask; }
/** * ipset_parse_after - parse string as "after" reference setname * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as a "after" reference setname for list:set * type of sets. The value is stored in the data blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_after(struct ipset_session *session, enum ipset_opt opt, const char *str) { struct ipset_data *data; assert(session); assert(opt == IPSET_OPT_NAMEREF); assert(str); data = ipset_session_data(session); if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF))) syntax_err("mixed syntax, before|after option already used"); check_setname(str, NULL); return ipset_data_set(data, opt, str); }
// Obtain the STACK_OR_reg_mask name for an OperandForm char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) { // name of cisc_spillable version const char *reg_mask_name = reg_mask(opForm); if (reg_mask_name == NULL) { syntax_err(opForm._linenum, "Did not find reg_mask for opForm: %s", opForm._ident); abort(); } const char *stack_or = "STACK_OR_"; int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1; char *result = new char[length]; sprintf(result,"%s%s", stack_or, reg_mask_name); return result; }
static struct addrinfo * call_getaddrinfo(struct ipset_session *session, const char *str, uint8_t family) { struct addrinfo hints; struct addrinfo *res; int err; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = family; hints.ai_socktype = SOCK_RAW; hints.ai_protocol = 0; hints.ai_next = NULL; if ((err = getaddrinfo(str, NULL, &hints, &res)) != 0) { syntax_err("cannot resolve '%s' to an %s address: %s", str, family == AF_INET6 ? "IPv6" : "IPv4", gai_strerror(err)); return NULL; } else return res; }
/** * ipset_parse_proto_port - parse (optional) protocol and a single port * @session: session structure * @opt: option kind of the data * @str: string to parse * * Parse string as a protocol and port, separated by a colon. * The protocol part is optional. * The parsed protocol and port numbers are stored in the data * blob of the session. * * Returns 0 on success or a negative error code. */ int ipset_parse_proto_port(struct ipset_session *session, enum ipset_opt opt, const char *str) { struct ipset_data *data; char *a, *saved, *tmp; const char *proto; uint8_t p = IPPROTO_TCP; int err = 0; assert(session); assert(opt == IPSET_OPT_PORT); assert(str); data = ipset_session_data(session); saved = tmp = strdup(str); if (tmp == NULL) return ipset_err(session, "Cannot allocate memory to duplicate %s.", str); a = proto_separator(tmp); if (a != NULL) { uint8_t family = ipset_data_family(data); /* proto:port */ *a++ = '\0'; err = ipset_parse_proto(session, IPSET_OPT_PROTO, tmp); if (err) goto error; p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO); switch (p) { case IPPROTO_TCP: proto = tmp; tmp = a; goto parse_port; case IPPROTO_UDP: proto = tmp; tmp = a; goto parse_port; case IPPROTO_ICMP: if (family != AF_INET) { syntax_err("Protocol ICMP can be used with family INET only"); goto error; } err = ipset_parse_icmp(session, opt, a); break; case IPPROTO_ICMPV6: if (family != AF_INET6) { syntax_err("Protocol ICMPv6 can be used with family INET6 only"); goto error; } err = ipset_parse_icmpv6(session, opt, a); break; default: if (!STREQ(a, "0")) { syntax_err("Protocol %s can be used with pseudo port value 0 only."); goto error; } ipset_data_flags_set(data, IPSET_FLAG(opt)); } goto error; } else { proto = "TCP"; err = ipset_data_set(data, IPSET_OPT_PROTO, &p); if (err) goto error; } parse_port: err = ipset_parse_tcpudp_port(session, opt, tmp, proto); error: free(saved); return err; }