]> git.ipfire.org Git - thirdparty/bird.git/blob - nest/a-path.c
Whitespace changes.
[thirdparty/bird.git] / nest / a-path.c
1 /*
2 * BIRD -- Path Operations
3 *
4 * (c) 2000 Martin Mares <mj@ucw.cz>
5 * (c) 2000 Pavel Machek <pavel@ucw.cz>
6 *
7 * Can be freely distributed and used under the terms of the GNU GPL.
8 */
9
10 #include "nest/bird.h"
11 #include "nest/route.h"
12 #include "nest/attrs.h"
13 #include "lib/resource.h"
14 #include "lib/unaligned.h"
15 #include "lib/string.h"
16
17 struct adata *
18 as_path_prepend(struct linpool *pool, struct adata *olda, int as)
19 {
20 struct adata *newa;
21
22 if (olda->length && olda->data[0] == AS_PATH_SEQUENCE &&
23 olda->data[1] < 255) /* Starting with sequence => just prepend the AS number */
24 {
25 newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 2);
26 newa->length = olda->length + 2;
27 newa->data[0] = 2;
28 newa->data[1] = olda->data[1] + 1;
29 memcpy(newa->data+4, olda->data+2, olda->length-2);
30 }
31 else /* Create new path segment */
32 {
33 newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 4);
34 newa->length = olda->length + 4;
35 newa->data[0] = 2;
36 newa->data[1] = 1;
37 memcpy(newa->data+4, olda->data, olda->length);
38 }
39 put_u16(newa->data+2, as);
40 return newa;
41 }
42
43 void
44 as_path_format(struct adata *path, byte *buf, unsigned int size)
45 {
46 byte *p = path->data;
47 byte *e = p + path->length - 8;
48 byte *end = buf + size;
49 int sp = 1;
50 int l, type, isset, as;
51
52 while (p < e)
53 {
54 if (buf > end)
55 {
56 strcpy(buf, " ...");
57 return;
58 }
59 isset = (*p++ == AS_PATH_SET);
60 l = *p++;
61 if (isset)
62 {
63 if (!sp)
64 *buf++ = ' ';
65 *buf++ = '{';
66 sp = 0;
67 }
68 while (l-- && buf <= end)
69 {
70 if (!sp)
71 *buf++ = ' ';
72 buf += bsprintf(buf, "%d", get_u16(p));
73 p += 2;
74 sp = 0;
75 }
76 if (isset)
77 {
78 *buf++ = ' ';
79 *buf++ = '}';
80 sp = 0;
81 }
82 }
83 *buf = 0;
84 }
85
86 int
87 as_path_getlen(struct adata *path)
88 {
89 int res = 0;
90 u8 *p = path->data;
91 u8 *q = p+path->length;
92 int len;
93
94 while (p<q)
95 {
96 switch (*p++)
97 {
98 case AS_PATH_SET: len = *p++; res++; p += 2*len; break;
99 case AS_PATH_SEQUENCE: len = *p++; res+=len; p += 2*len; break;
100 default: bug("as_path_getlen: Invalid path segment");
101 }
102 }
103 return res;
104 }
105
106 #define MASK_PLUS do { mask = mask->next; if (!mask) return next == q; \
107 asterisk = (mask->val == PM_ANY); \
108 if (asterisk) { mask = mask->next; if (!mask) { return 1; } } \
109 } while(0)
110
111 int
112 as_path_match(struct adata *path, struct f_path_mask *mask)
113 {
114 int i;
115 int asterisk = 0;
116 u8 *p = path->data;
117 u8 *q = p+path->length;
118 int len;
119 u8 *next;
120
121 asterisk = (mask->val == PM_ANY);
122 if (asterisk)
123 { mask = mask->next; if (!mask) return 1; }
124
125 while (p<q) {
126 switch (*p++) {
127 case AS_PATH_SET:
128 len = *p++;
129 {
130 u8 *p_save = p;
131 next = p_save + 2*len;
132 retry:
133 p = p_save;
134 for (i=0; i<len; i++) {
135 if (asterisk && (get_u16(p) == mask->val)) {
136 MASK_PLUS;
137 goto retry;
138 }
139 if (!asterisk && (get_u16(p) == mask->val)) {
140 p = next;
141 MASK_PLUS;
142 goto okay;
143 }
144 p+=2;
145 }
146 if (!asterisk)
147 return 0;
148 okay:
149 }
150 break;
151
152 case AS_PATH_SEQUENCE:
153 len = *p++;
154 for (i=0; i<len; i++) {
155 next = p+2;
156 if (asterisk && (get_u16(p) == mask->val))
157 MASK_PLUS;
158 else if (!asterisk) {
159 if (get_u16(p) != mask->val)
160 return 0;
161 MASK_PLUS;
162 }
163 p+=2;
164 }
165 break;
166
167 default:
168 bug("as_path_match: Invalid path component");
169 }
170 }
171 return 0;
172 }
173