summaryrefslogtreecommitdiffstats
path: root/nest/a-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/a-path.c')
-rw-r--r--nest/a-path.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/nest/a-path.c b/nest/a-path.c
index d808bc9..3468e4a 100644
--- a/nest/a-path.c
+++ b/nest/a-path.c
@@ -99,3 +99,70 @@ as_path_getlen(struct adata *path)
}
return res;
}
+
+#define MASK_PLUS do { mask = mask->next; if (!mask) return next == q; \
+ asterix = (mask->val == PM_ANY); \
+ if (asterix) { mask = mask->next; if (!mask) { return 1; } } \
+ } while(0)
+
+int
+as_path_match(struct adata *path, struct f_path_mask *mask)
+{
+ int i;
+ int asterix = 0;
+ u8 *p = path->data;
+ u8 *q = p+path->length;
+ int len;
+ u8 *next;
+
+ asterix = (mask->val == PM_ANY);
+ if (asterix) { mask = mask->next; if (!mask) { return 1; } }
+
+ while (p<q) {
+ switch (*p++) {
+ case 1: /* This is a set */
+ len = *p++;
+ {
+ u8 *p_save = p;
+ next = p_save + 2*len;
+ retry:
+ p = p_save;
+ for (i=0; i<len; i++) {
+ if (asterix && (get_u16(p) == mask->val)) {
+ MASK_PLUS;
+ goto retry;
+ }
+ if (!asterix && (get_u16(p) == mask->val)) {
+ p = next;
+ MASK_PLUS;
+ goto okay;
+ }
+ p+=2;
+ }
+ if (!asterix)
+ return 0;
+ okay:
+ }
+ break;
+
+ case 2: /* This is a sequence */
+ len = *p++;
+ for (i=0; i<len; i++) {
+ next = p+2;
+ if (asterix && (get_u16(p) == mask->val))
+ MASK_PLUS;
+ else if (!asterix) {
+ if (get_u16(p) != mask->val)
+ return 0;
+ MASK_PLUS;
+ }
+ p+=2;
+ }
+ break;
+
+ default:
+ bug("This should not be in path");
+ }
+ }
+ return 0;
+}