void prefix_increment_t(void) { struct prefix px; sput_fail_unless(prefix_increment(&px, &p1, 8) == 0, "Ret is 0"); sput_fail_if(prefix_cmp(&px, &p2), "px == p2"); sput_fail_unless(prefix_increment(&px, &p10, 8) == 0, "Ret is 0"); sput_fail_if(prefix_cmp(&px, &p11), "px == p11"); sput_fail_unless(prefix_increment(&px, &p10, 16) == 1, "Single possibility"); sput_fail_if(prefix_cmp(&px, &p10), "px == p10"); sput_fail_unless(prefix_increment(&px, &p1f, 12) == 1, "Looping"); sput_fail_if(prefix_cmp(&px, &p10), "px == p10"); sput_fail_unless(prefix_increment(&px, &p1f, 120) == -1, "Forbidden"); px.plen = 120; sput_fail_unless(prefix_increment(&px, &px, 4) == -1, "Forbidden"); px.plen = 42; sput_fail_unless(prefix_increment(&px, &px, 10) == 0, "32 bits authorized"); px.plen = 43; sput_fail_unless(prefix_increment(&px, &px, 10) == -1, "33 bits forbidden"); }
/* fill zone with rt cap rt1, and returns a pointer to zone, or NULL if the intersection is empty. */ static const struct zone* inter(const struct babel_route *rt, const struct babel_route *rt1, struct zone *zone) { enum prefix_status dst_st, src_st; const struct source *r = rt->src, *r1 = rt1->src; dst_st = prefix_cmp(r->prefix, r->plen, r1->prefix, r1->plen); if(dst_st == PST_DISJOINT) return NULL; src_st = prefix_cmp(r->src_prefix, r->src_plen, r1->src_prefix, r1->src_plen); if(src_st == PST_DISJOINT) return NULL; if(dst_st == PST_MORE_SPECIFIC || dst_st == PST_EQUALS) { zone->dst_prefix = r->prefix; zone->dst_plen = r->plen; } else { zone->dst_prefix = r1->prefix; zone->dst_plen = r1->plen; } if(src_st == PST_MORE_SPECIFIC || src_st == PST_EQUALS) { zone->src_prefix = r->src_prefix; zone->src_plen = r->src_plen; } else { zone->src_prefix = r1->src_prefix; zone->src_plen = r1->src_plen; } return zone; }
static int conflicts(const struct babel_route *rt, const struct babel_route *rt1) { enum prefix_status dst_st, src_st; const struct source *r = rt->src, *r1 = rt1->src; dst_st = prefix_cmp(r->prefix, r->plen, r1->prefix, r1->plen); if(dst_st == PST_DISJOINT || dst_st == PST_EQUALS) return 0; src_st = prefix_cmp(r->src_prefix, r->src_plen, r1->src_prefix, r1->src_plen); return ((dst_st == PST_LESS_SPECIFIC && src_st == PST_MORE_SPECIFIC) || (dst_st == PST_MORE_SPECIFIC && src_st == PST_LESS_SPECIFIC)); }
void prefix_number_t() { struct prefix p; prefix_number(&p, &p10, 0, 1); sput_fail_if(prefix_cmp(&p, &p10), "Correct prefix"); prefix_number(&p, &p10, 1, 1); sput_fail_if(prefix_cmp(&p, &p11), "Correct prefix"); prefix_number(&p, &p10, 1, 0); sput_fail_if(prefix_cmp(&p, &p10), "Correct prefix"); prefix_number(&p, &p10, 0xf, 1); sput_fail_if(prefix_cmp(&p, &p11), "Correct prefix"); prefix_number(&p, &p10, 0xf, 4); sput_fail_if(prefix_cmp(&p, &p1f), "Correct prefix"); }
void prefix_cmp_t(void) { sput_fail_unless(prefix_cmp(&p1, &p11) > 0, "Prefix compare diff. plen (1)"); sput_fail_unless(prefix_cmp(&p11, &p1) < 0, "Prefix compare diff. plen (2)"); sput_fail_unless(prefix_cmp(&p_allones_67, &p_allones_128) > 0, "Prefix compare diff. plen (3)"); sput_fail_unless(prefix_cmp(&p2, &p1) > 0, "Prefix compare value (1)"); sput_fail_unless(prefix_cmp(&p10, &p11) < 0, "Prefix compare value (2)"); }
void prefix_last_t(void) { struct prefix px; sput_fail_unless(prefix_last(&px, &p10, 18) == -1, "Forbidden arg"); sput_fail_unless(prefix_last(&px, &p10, 16) == 0, "Ret is 0"); sput_fail_if(prefix_cmp(&px, &p10), "Unmodified"); sput_fail_unless(prefix_last(&px, &p10, 12) == 0, "Ret is 0"); sput_fail_if(prefix_cmp(&px, &p1f), "px == p1f"); sput_fail_unless(prefix_last(&px, &p11, 12) == 0, "Ret is 0"); sput_fail_if(prefix_cmp(&px, &p1f), "px == p1f"); }
/* * Find the correct place to insert the prefix in the prefix list. * If the active prefix has changed we need to send an update. * The to evaluate prefix must not be in the prefix list. */ void prefix_evaluate(struct prefix *p, struct rib_entry *re) { struct prefix *xp; if (re->flags & F_RIB_NOEVALUATE || rde_noevaluate()) { /* decision process is turned off */ if (p != NULL) LIST_INSERT_HEAD(&re->prefix_h, p, rib_l); if (re->active != NULL) { re->active->aspath->active_cnt--; re->active = NULL; } return; } if (p != NULL) { if (LIST_EMPTY(&re->prefix_h)) LIST_INSERT_HEAD(&re->prefix_h, p, rib_l); else { LIST_FOREACH(xp, &re->prefix_h, rib_l) if (prefix_cmp(p, xp) > 0) { LIST_INSERT_BEFORE(xp, p, rib_l); break; } else if (LIST_NEXT(xp, rib_l) == NULL) { /* if xp last element ... */ LIST_INSERT_AFTER(xp, p, rib_l); break; } } } xp = LIST_FIRST(&re->prefix_h); if (xp == NULL || xp->aspath->flags & F_ATTR_LOOP || (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state != NEXTHOP_REACH)) /* xp is ineligible */ xp = NULL; if (re->active != xp) { /* need to generate an update */ if (re->active != NULL) re->active->aspath->active_cnt--; /* * Send update with remove for re->active and add for xp * but remember that xp may be NULL aka ineligible. * Additional decision may be made by the called functions. */ rde_generate_updates(re->ribid, xp, re->active); if ((re->flags & F_RIB_NOFIB) == 0) rde_send_kroute(xp, re->active); re->active = xp; if (xp != NULL) xp->aspath->active_cnt++; } }
/* This function assumes rt1 and rt2 non disjoint. */ static int rt_cmp(const struct babel_route *rt1, const struct babel_route *rt2) { enum prefix_status dst_st, src_st; const struct source *r1 = rt1->src, *r2 = rt2->src; dst_st = prefix_cmp(r1->prefix, r1->plen, r2->prefix, r2->plen); if(dst_st == PST_MORE_SPECIFIC) return -1; else if(dst_st == PST_LESS_SPECIFIC) return 1; src_st = prefix_cmp(r1->src_prefix, r1->src_plen, r2->src_prefix, r2->src_plen); if(src_st == PST_MORE_SPECIFIC) return -1; else if(src_st == PST_LESS_SPECIFIC) return 1; return 0; }
/* Lookup interface by prefix */ struct interface *if_lookup_prefix(struct prefix *prefix) { struct listnode *node; struct listnode *cnode; struct interface *ifp; struct connected *c; for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { if (prefix_cmp(c->address, prefix) == 0) { return ifp; } } } return NULL; }
void prefix_pton_t(void) { struct prefix p; struct prefix p4_1 = { .prefix = { .s6_addr = { 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0xff,0xff, 0x0a }}, .plen = 104 }; struct prefix p4_2 = { .prefix = { .s6_addr = { 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0xff,0xff, 0xc0,0xa8, 0x00,0x01 }}, .plen = 128 }; sput_fail_unless(prefix_pton(p_allones_67_s, &p) == 1, "Parse 1"); sput_fail_unless(!prefix_cmp(&p, &p_allones_67), "Parse value 1"); sput_fail_unless(prefix_pton(p1_s, &p) == 1, "Parse 2"); sput_fail_unless(!prefix_cmp(&p, &p1), "Parse value 2"); sput_fail_unless(prefix_pton(px_s, &p) == 1, "Parse 3"); sput_fail_unless(!prefix_cmp(&p, &px), "Parse value 3"); sput_fail_unless(prefix_pton("10::/rrx", &p) == 0, "Parse error 1"); sput_fail_unless(prefix_pton("10::/129", &p) == 0, "Parse error 2"); sput_fail_unless(prefix_pton("10::/-1", &p) == 0, "Parse error 3"); sput_fail_unless(prefix_pton("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255./10", &px) == 0, "Parse error 4"); sput_fail_unless(prefix_pton("10.0.0.0/64", &px) == 0, "Parse error 5"); sput_fail_unless(prefix_pton("blah-chombier/64", &px) == 0, "Parse error 6"); /* Parsing IPv4 */ sput_fail_unless(prefix_pton("10.0.0.0/8", &p) == 1, "Parse v4 1"); sput_fail_unless(!prefix_cmp(&p, &p4_1), "Parse v4 value 1"); sput_fail_unless(prefix_pton("192.168.0.1/32", &p) == 1, "Parse v4 2"); sput_fail_unless(!prefix_cmp(&p, &p4_2), "Parse v4 value 2"); /* Parsing without slash */ sput_fail_unless(prefix_pton("192.168.0.1", &p) == 1, "Parse v4 without /"); sput_fail_unless(!prefix_cmp(&p, &p4_2), "Parse v4 without /"); sput_fail_unless(prefix_pton("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &p) == 1, "Parse v6 without /"); sput_fail_unless(!prefix_cmp(&p, &p_allones_128), "Parse v6 without /"); }
void prefix_equal_t(void) { sput_fail_if(prefix_cmp(&p_allones_67, &p_allones_67), "Same prefixes should be equal (1)"); sput_fail_if(prefix_cmp(&p_allones_67_can, &p_allones_67_can), "Same prefixes should be equal (2)"); sput_fail_if(prefix_cmp(&p1, &p1), "Same prefixes should be equal (3)"); sput_fail_if(prefix_cmp(&p_allones_67, &p_allones_67_can), "Canonical prefix should equal non-canonical one"); sput_fail_unless(prefix_cmp(&p1, &p10), "Different prefix length should imply not equal"); sput_fail_unless(prefix_cmp(&p1, &p_allones_67), "Different prefixes should not be equal"); }
void prefix_random_t(void) { int i; struct prefix p; sput_fail_unless(prefix_random(&p_allones_67, &p, 60), "Too short plen for random prefix"); prefix_random(&p_allones_67_can, &p, 67); sput_fail_if(prefix_cmp(&p_allones_67_can, &p), "Only one possible random prefix"); bool success = true; for(i = 0; i < 20; i++) { prefix_random(&p_allones_67, &p, 70); if(!prefix_contains(&p_allones_67, &p)) { success = false; break; } } sput_fail_unless(success, "Random prefix is in src prefix"); }
static int argparse_long_opt(struct argparse *this_, const struct argparse_option *options) { for (; options->type != ARGPARSE_OPT_END; options++) { const char *rest; int opt_flags = 0; if (!options->long_name) continue; rest = prefix_skip(this_->argv[0] + 2, options->long_name); if (!rest) { // Negation allowed? if (options->flags & OPT_NONEG) { continue; } // Only boolean/bit allow negation. if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != ARGPARSE_OPT_BIT) { continue; } if (!prefix_cmp(this_->argv[0] + 2, "no-")) { rest = prefix_skip(this_->argv[0] + 2 + 3, options->long_name); if (!rest) continue; opt_flags |= OPT_UNSET; } else { continue; } } if (*rest) { if (*rest != '=') continue; this_->optvalue = rest + 1; } return argparse_getvalue(this_, options, opt_flags); } return -2; }
static int argparse_long_opt(struct argparse *self, const struct argparse_option *options) { for (; options->type != ARGPARSE_OPT_END; options++) { const char *rest; int opt_flags = 0; if (!options->long_name) continue; rest = prefix_skip(self->argv[0] + 2, options->long_name); if (!rest) { // negation disabled? if (options->flags & OPT_NONEG) { continue; } // only OPT_BOOLEAN/OPT_BIT supports negation if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != ARGPARSE_OPT_BIT) { continue; } if (prefix_cmp(self->argv[0] + 2, "no-")) { continue; } rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name); if (!rest) continue; opt_flags |= OPT_UNSET; } if (*rest) { if (*rest != '=') continue; self->optvalue = rest + 1; } return argparse_getvalue(self, options, opt_flags | OPT_LONG); } return -2; }
void iface_test_new_managed(void) { struct in_addr v4source = {INADDR_LOOPBACK}; iface_register_user(&user_mock); struct prefix p = {IN6ADDR_LOOPBACK_INIT, 0}; char test[] = "test"; struct iface *iface00 = iface_create("test00", "test00", 0); iface_update_ipv4_uplink(iface00); iface_set_ipv4_uplink(iface00, &v4source, 24); iface_commit_ipv4_uplink(iface00); /* smock_pull_bool_is("test00", false); */ /* this was removed in the commit a5293745c235a057b6a477ffbd817937eaa9bc12 at 5/2015(!); */ struct iface *iface = iface_create("test0", "test0", 0); iface->carrier = true; iface_discover_border(iface); sput_fail_unless(!!iface, "alloc managed"); struct iface *iface2 = iface_get("test0"); sput_fail_unless(iface == iface2, "get after create"); struct iface *iface3 = iface_create("test0", "test0", 0); sput_fail_unless(iface == iface3, "create after create"); /* smock_pull_bool_is("test0", false); */ /* this was removed in the commit a5293745c235a057b6a477ffbd817937eaa9bc12 at 5/2015(!); */ uloop_cancelled = false; uloop_run(); smock_pull_bool_is("test0", true); iface_update_ipv4_uplink(iface); iface_set_ipv4_uplink(iface, &v4source, 24); iface_commit_ipv4_uplink(iface); smock_pull_bool_is("test0", false); iface_update_ipv4_uplink(iface); iface_commit_ipv4_uplink(iface); uloop_cancelled = false; uloop_run(); smock_pull_bool_is("test0", true); iface_update_ipv6_uplink(iface); iface_add_delegated(iface, &p, NULL, HNETD_TIME_MAX, 0, test, sizeof(test)); iface_commit_ipv6_uplink(iface); smock_pull_bool_is("test0", false); sput_fail_unless(!prefix_cmp(&p, (struct prefix *)smock_pull("prefix_prefix")), "prefix address"); smock_pull_int64_is("prefix_valid", HNETD_TIME_MAX); smock_pull_int64_is("prefix_preferred", 0); sput_fail_unless(!strcmp(smock_pull("dhcpv6_data"), "test"), "dhcpv6_data"); smock_pull_int_is("dhcpv6_len", sizeof(test)); iface_update_ipv4_uplink(iface); iface_set_ipv4_uplink(iface, &v4source, 24); iface_commit_ipv4_uplink(iface); iface_update_ipv6_uplink(iface); iface_commit_ipv6_uplink(iface); smock_pull_bool_is("prefix_remove", true); iface_update_ipv4_uplink(iface); iface_commit_ipv4_uplink(iface); uloop_cancelled = false; uloop_run(); smock_pull_bool_is("test0", true); iface_remove(iface); sput_fail_unless(!iface_get("test0"), "delete"); smock_pull_bool_is("test0", false); smock_is_empty(); iface_unregister_user(&user_mock); }
/* 0 failure, 1 success */ static int regmatch(regex_t *preg, int prog) { int scan; /* Current node. */ int next; /* Next node. */ const char *save; scan = prog; #ifdef DEBUG if (scan != 0 && regnarrate) fprintf(stderr, "%s(\n", regprop(scan)); #endif while (scan != 0) { int n; int c; #ifdef DEBUG if (regnarrate) { fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); /* Where, what. */ } #endif next = regnext(preg, scan); n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); switch (OP(preg, scan)) { case BOL: if (preg->reginput != preg->regbol) return(0); break; case EOL: if (!reg_iseol(preg, c)) { return(0); } break; case WORDA: /* Must be looking at a letter, digit, or _ */ if ((!isalnum(UCHAR(c))) && c != '_') return(0); /* Prev must be BOL or nonword */ if (preg->reginput > preg->regbol && (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) return(0); break; case WORDZ: /* Can't match at BOL */ if (preg->reginput > preg->regbol) { /* Current must be EOL or nonword */ if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { c = preg->reginput[-1]; /* Previous must be word */ if (isalnum(UCHAR(c)) || c == '_') { break; } } } /* No */ return(0); case ANY: if (reg_iseol(preg, c)) return 0; preg->reginput += n; break; case EXACTLY: { int opnd; int len; int slen; opnd = OPERAND(scan); len = str_int_len(preg->program + opnd); slen = prefix_cmp(preg->program + opnd, len, preg->reginput, preg->cflags & REG_ICASE); if (slen < 0) { return(0); } preg->reginput += slen; } break; case ANYOF: if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) == 0) { return(0); } preg->reginput += n; break; case ANYBUT: if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) != 0) { return(0); } preg->reginput += n; break; case NOTHING: break; case BACK: break; case BRANCH: if (OP(preg, next) != BRANCH) /* No choice. */ next = OPERAND(scan); /* Avoid recursion. */ else { do { save = preg->reginput; if (regmatch(preg, OPERAND(scan))) { return(1); } preg->reginput = save; scan = regnext(preg, scan); } while (scan != 0 && OP(preg, scan) == BRANCH); return(0); /* NOTREACHED */ } break; case REP: case REPMIN: return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); case REPX: case REPXMIN: return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); case END: return 1; /* Success! */ case OPENNC: case CLOSENC: return regmatch(preg, next); default: if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { save = preg->reginput; if (regmatch(preg, next)) { if (OP(preg, scan) < CLOSE) { int no = OP(preg, scan) - OPEN; if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { preg->pmatch[no].rm_so = save - preg->start; } } else { int no = OP(preg, scan) - CLOSE; if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { preg->pmatch[no].rm_eo = save - preg->start; } } return(1); } return(0); } return REG_ERR_INTERNAL; } scan = next; } /* * We get here only if there's trouble -- normally "case END" is * the terminating point. */ return REG_ERR_INTERNAL; }
/* - regexec - match a regexp against a string */ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { const char *s; int scan; /* Be paranoid... */ if (preg == NULL || preg->program == NULL || string == NULL) { return REG_ERR_NULL_ARGUMENT; } /* Check validity of program. */ if (*preg->program != REG_MAGIC) { return REG_ERR_CORRUPTED; } #ifdef DEBUG fprintf(stderr, "regexec: %s\n", string); regdump(preg); #endif preg->eflags = eflags; preg->pmatch = pmatch; preg->nmatch = nmatch; preg->start = string; /* All offsets are computed from here */ /* Must clear out the embedded repeat counts of REPX and REPXMIN opcodes */ for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { int op = OP(preg, scan); if (op == END) break; if (op == REPX || op == REPXMIN) preg->program[scan + 4] = 0; } /* If there is a "must appear" string, look for it. */ if (preg->regmust != 0) { s = string; while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { break; } s++; } if (s == NULL) /* Not present. */ return REG_NOMATCH; } /* Mark beginning of line for ^ . */ preg->regbol = string; /* Simplest case: anchored match need be tried only once (maybe per line). */ if (preg->reganch) { if (eflags & REG_NOTBOL) { /* This is an anchored search, but not an BOL, so possibly skip to the next line */ goto nextline; } while (1) { if (regtry(preg, string)) { return REG_NOERROR; } if (*string) { nextline: if (preg->cflags & REG_NEWLINE) { /* Try the next anchor? */ string = strchr(string, '\n'); if (string) { preg->regbol = ++string; continue; } } } return REG_NOMATCH; } } /* Messy cases: unanchored match. */ s = string; if (preg->regstart != '\0') { /* We know what char it must start with. */ while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { if (regtry(preg, s)) return REG_NOERROR; s++; } } else /* We don't -- general case. */ while (1) { if (regtry(preg, s)) return REG_NOERROR; if (*s == '\0') { break; } else { int c; s += utf8_tounicode(s, &c); } } /* Failure. */ return REG_NOMATCH; }