1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 2002-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * bgp method
23 *
24 * Glenn Fowler
25 * AT&T Research
26 */
27
28 static const char usage[] =
29 "[a:anonymize?Anonymize output data for \bbgp-*-anonymize\b formats.]"
30 ;
31
32 #include "bgplib.h"
33 #include "mrt.h"
34
35 #define BGP_path_len (((BGP_LAST+1)<<1)|1)
36 #define BGP_path16_len (((BGP_LAST+2)<<1)|1)
37 #define BGP_path32_len (((BGP_LAST+3)<<1)|1)
38 #define BGP_cluster_len (((BGP_LAST+4)<<1)|1)
39 #define BGP_community_len (((BGP_LAST+5)<<1)|1)
40 #define BGP_extended_len (((BGP_LAST+6)<<1)|1)
41 #define BGP_labels_len (((BGP_LAST+7)<<1)|1)
42
43 #define CXD(name,type,index,description) \
44 {name,description,{{0},CX_DEPRECATED},0,(Cxtype_t*)type,0,index},
45
46 Dssformat_t* bgp_formats = bgp_first_format;
47
48 static Cxvariable_t fields[] =
49 {
50 CXV("afi", "number", BGP_afi, "Announce address family identifier: 1:ipv4, 2:ipv6.")
51 CXV("agg_addr", "ipaddr_t", BGP_agg_addr, "Aggregator AS address.")
52 CXV("agg_addrv4", "ipv4addr_t", BGP_agg_addrv4, "Aggregator AS ipv4 address.")
53 CXV("agg_addrv6", "ipv6addr_t", BGP_agg_addrv6, "Aggregator AS ipv6 address.")
54 CXV("agg_addr32", "ipaddr_t", BGP_agg_addr32, "Aggregator AS32 address.")
55 CXV("agg_addr32v4", "ipv4addr_t", BGP_agg_addr32v4, "Aggregator AS32 ipv4 address.")
56 CXV("agg_addr32v6", "ipv6addr_t", BGP_agg_addr32v6, "Aggregator AS32 ipv6 address.")
57 CXV("agg_as", "as_t", BGP_agg_as, "Aggregator AS number.")
58 CXV("agg_as16", "as16_t", BGP_agg_as16, "Aggregator AS16 number.")
59 CXV("agg_as32", "as32_t", BGP_agg_as32, "Aggregator AS32 number.")
60 CXV("atomic", "number", BGP_atomic, "Atomic.")
61 CXV("best", "number", BGP_best, "Best route.")
62 CXV("bits", "number", BGP_bits, "Number of prefix mask bits.")
63 CXV("bitsv4", "number", BGP_bitsv4, "Number of ipv4 prefix mask bits.")
64 CXV("bitsv6", "number", BGP_bitsv6, "Number of ipv6 prefix mask bits.")
65 CXV("cluster", "cluster_t", BGP_cluster, "Cluster id list.")
66 CXV("community", "community_t", BGP_community, "Community of interest id list.")
67 CXV("damped", "number", BGP_damped, "Damped prefix.")
68 CXV("dpa_addr", "ipaddr_t", BGP_dpa_addr, "DPA address.")
69 CXV("dpa_addrv4", "ipv4addr_t", BGP_dpa_addrv4, "DPA ipv4 address.")
70 CXV("dpa_addrv6", "ipv6addr_t", BGP_dpa_addrv6, "DPA ipv6 address.")
71 CXV("dpa_as", "as_t", BGP_dpa_as, "DPA AS number.")
72 CXV("dpa_as16", "as16_t", BGP_dpa_as16, "DPA AS16 number.")
73 CXV("dpa_as32", "as32_t", BGP_dpa_as32, "DPA AS32 number.")
74 CXV("dst_addr", "ipaddr_t", BGP_dst_addr, "Destination address.")
75 CXV("dst_addrv4", "ipv4addr_t", BGP_dst_addrv4, "Destination ipv4 address.")
76 CXV("dst_addrv6", "ipv6addr_t", BGP_dst_addrv6, "Destination ipv6 address.")
77 CXV("dst_as", "as_t", BGP_dst_as, "Destination AS number.")
78 CXV("dst_as16", "as16_t", BGP_dst_as16, "Destination AS16 number.")
79 CXV("dst_as32", "as32_t", BGP_dst_as32, "Destination AS32 number.")
80 CXV("extended", "extended_t", BGP_extended, "Extended community list.")
81 CXV("flags", "number", BGP_flags, "Auxiliary flags.")
82 CXV("history", "number", BGP_history, "History prefix.")
83 CXV("hop", "ipaddr_t", BGP_hop, "Next hop address.")
84 CXV("hopv4", "ipv4addr_t", BGP_hopv4, "Next hop ipv4 address.")
85 CXV("hopv6", "ipv6addr_t", BGP_hopv6, "Next hop ipv6 address.")
86 CXV("id", "number", BGP_id, "Auxiliary id.")
87 CXV("internal", "number", BGP_internal, "Internal prefix.")
88 CXV("key", "bgp_t", BGP_key, "Route key NLRI.")
89 CXV("label", "number", BGP_label, "NLRI label.")
90 CXV("labels", "labels_t", BGP_labels, "NLRI label list; LHS is label, RHS is COS and end of stack bit.")
91 CXV("local", "number", BGP_local, "Local preference.")
92 CXV("med", "number", BGP_med, "Multi exit discriminator.")
93 CXV("message", "number", BGP_message, "Message group index.")
94 CXV("mvpn", "bgp_t", BGP_mvpn, "[Mcast vpn data using members of the main schema; access as \bmvpn\b.\amember\a:]{[+agg_addr?VPN_S_PMSI_A_D multicast address.][+key?Route key NLRI.][+originator?Originator ipv4 address.][+rd_addr?Route distinguisher address.][+rd_as?Route distinguisher AS number.][+rd_number?Route distinguisher assigned number.][+rd_type?Route distinguisher type.][+src_addr?Source address.][+src_as?Originator AS number.][+type?The route type index.]}")
95 CXV("new_state", "number", BGP_new_state, "STATE_CHANGE record new state.")
96 CXV("old_state", "number", BGP_old_state, "STATE_CHANGE record old state.")
97 CXV("origin", "number", BGP_origin, "Origin: 'i':igp, 'e':egp, '?':incomplete.")
98 CXV("originator", "ipv4addr_t", BGP_originator, "Originator ipv4 address.")
99 CXV("path", "aspath_t", BGP_path, "AS path.")
100 CXV("path16", "as16path_t", BGP_path16, "AS16 path.")
101 CXV("path32", "as32path_t", BGP_path32, "AS32 path.")
102 CXV("prefix", "ipprefix_t", BGP_prefix, "Routing ddress prefix and length.")
103 CXV("prefixv4", "ipv4prefix_t", BGP_prefixv4, "ipv4 routing prefix and length.")
104 CXV("prefixv6", "ipv6prefix_t", BGP_prefixv6, "ipv6 routing prefix and length.")
105 CXV("rd_addr", "ipaddr_t", BGP_rd_addr, "NLRI route distinguisher address.")
106 CXV("rd_as", "as_t", BGP_rd_as, "NLRI route distinguisher AS number.")
107 CXV("rd_number", "number", BGP_rd_number, "NLRI route distinguisher assigned number.")
108 CXV("rd_type", "number", BGP_rd_type, "NLRI route distinguisher type.")
109 CXV("rib_failure", "number", BGP_rib_failure, "RIB failure.")
110 CXV("safi", "number", BGP_safi, "Announce subsequent address family identifier bits: 1:unicast, 2:multicast, 4:MLPS-label, 5:MCAST-VPN, 128:MLPS-labeled-VPN.")
111 CXV("slot", "number", BGP_slot, "Slot.")
112 CXV("src_addr", "ipaddr_t", BGP_src_addr, "Source address.")
113 CXV("src_addrv4", "ipv4addr_t", BGP_src_addrv4, "Source ipv4 address.")
114 CXV("src_addrv6", "ipv6addr_t", BGP_src_addrv6, "Source ipv6 address.")
115 CXV("src_as", "as_t", BGP_src_as, "Source AS number.")
116 CXV("src_as16", "as16_t", BGP_src_as16, "Source AS16 number.")
117 CXV("src_as32", "as32_t", BGP_src_as32, "Source AS32 number.")
118 CXV("stale", "number", BGP_stale, "Stale.")
119 CXV("stamp", "time_t", BGP_stamp, "Data time stamp.")
120 CXV("suppressed", "number", BGP_suppressed, "Suppressed prefix.")
121 CXV("time", "time_t", BGP_time, "Packet event time stamp.")
122 CXV("type", "number", BGP_type, "Record type:: 'A':announce, 'K':keepalive, 'N':notification, 'O':open, 'S':state, 'T':table, 'W':withdraw.")
123 CXV("unknown", "string", BGP_unknown, "Unknown attributes in the form: \"<flag-i>:<type-i>:<size-i>:<hex-data-i>;...\".")
124 CXV("usec", "number", BGP_usec, "Packet event time stamp usec.")
125 CXV("valid", "number", BGP_valid, "Valid prefix.")
126 CXV("weight", "number", BGP_weight, "Router proprietary weight.")
127 CXV("MESSAGE", "number", BGP_MESSAGE, "Message group bit, toggled for each message.")
128 CXV("PART", "number", BGP_PART, "Message part bit, 0 for first part, 1 for remainder.")
129 CXD("cluster_len", "number", BGP_cluster_len, "DEPRECATED -- use sizeof(cluster). Cluster id list length.")
130 CXD("community_len", "number", BGP_community_len, "DEPRECATED -- use sizeof(community). Community of interest id list length.")
131 CXD("extended_len", "number", BGP_extended_len, "DEPRECATED -- use sizeof(extended). Extended community list length.")
132 CXD("labels_len", "number", BGP_labels_len, "DEPRECATED -- use sizeof(labels). NLRI label list length.")
133 CXD("path_len", "number", BGP_path_len, "DEPRECATED -- use sizeof(path). AS path length.")
134 CXD("path16_len", "number", BGP_path16_len, "DEPRECATED -- use sizeof(path16). AS16 path length.")
135 CXD("path32_len", "number", BGP_path32_len, "DEPRECATED -- use sizeof(path32). AS32 path length.")
136 {0}
137 };
138
139 static int
op_get(Cx_t * cx,Cxinstruction_t * pc,Cxoperand_t * r,Cxoperand_t * a,Cxoperand_t * b,void * data,Cxdisc_t * disc)140 op_get(Cx_t* cx, Cxinstruction_t* pc, Cxoperand_t* r, Cxoperand_t* a, Cxoperand_t* b, void* data, Cxdisc_t* disc)
141 {
142 Bgp_t* bgp = BGPDATA(data);
143 Bgproute_t* rp = (Bgproute_t*)DSSDATA(data);
144 Cxvariable_t* vp = (Cxvariable_t*)pc->data.variable;
145
146 static unsigned char noipv6[MRT_BITS_IPV6 + 1];
147
148 switch (vp->index)
149 {
150 case BGP_afi:
151 r->value.number = rp->afi ? rp->afi : MRT_AFI_IPV4;
152 break;
153 case BGP_agg_addr:
154 if (rp->set & BGP_SET_agg_addrv6)
155 {
156 r->value.buffer.data = rp->agg_addr.v6;
157 r->value.buffer.size = sizeof(rp->agg_addr.v6);
158 r->value.buffer.elements = 0;
159 r->type = bgp->type_ipv6addr;
160 }
161 else
162 {
163 r->value.number = rp->agg_addr.v4;
164 r->type = bgp->type_ipv4addr;
165 }
166 break;
167 case BGP_agg_addrv4:
168 r->value.number = (rp->set & BGP_SET_agg_addrv6) ? 0 : rp->agg_addr.v4;
169 break;
170 case BGP_agg_addrv6:
171 r->value.buffer.data = (rp->set & BGP_SET_agg_addrv6) ? rp->agg_addr.v6 : noipv6;
172 r->value.buffer.size = sizeof(rp->agg_addr.v6);
173 r->value.buffer.elements = 0;
174 break;
175 case BGP_agg_addr32:
176 if (rp->set & BGP_SET_agg_addr32v6)
177 {
178 r->value.buffer.data = rp->agg_addr32.v6;
179 r->value.buffer.size = sizeof(rp->agg_addr32.v6);
180 r->value.buffer.elements = 0;
181 r->type = bgp->type_ipv6addr;
182 }
183 else
184 {
185 r->value.number = rp->agg_addr32.v4;
186 r->type = bgp->type_ipv4addr;
187 }
188 break;
189 case BGP_agg_addr32v4:
190 r->value.number = (rp->set & BGP_SET_agg_addr32v6) ? 0 : rp->agg_addr32.v4;
191 break;
192 case BGP_agg_addr32v6:
193 r->value.buffer.data = (rp->set & BGP_SET_agg_addr32v6) ? rp->agg_addr32.v6 : noipv6;
194 r->value.buffer.size = sizeof(rp->agg_addr32.v6);
195 r->value.buffer.elements = 0;
196 break;
197 case BGP_agg_as:
198 r->value.number = rp->agg_as ? rp->agg_as : rp->agg_as32;
199 break;
200 case BGP_agg_as16:
201 r->value.number = rp->agg_as;
202 break;
203 case BGP_agg_as32:
204 r->value.number = rp->agg_as32;
205 break;
206 case BGP_bits:
207 r->value.number = (rp->set & BGP_SET_prefixv6) ? rp->prefixv6[IP6BITS] : rp->bits;
208 break;
209 case BGP_bitsv4:
210 r->value.number = rp->bits;
211 break;
212 case BGP_bitsv6:
213 r->value.number = rp->prefixv6[IP6BITS];
214 break;
215 case BGP_cluster:
216 r->value.buffer.data = rp->data + rp->cluster.offset;
217 r->value.buffer.size = rp->cluster.size * sizeof(Bgpnum_t);
218 r->value.buffer.elements = 0;
219 break;
220 case BGP_community:
221 r->value.buffer.data = rp->data + rp->community.offset;
222 r->value.buffer.size = rp->community.size * sizeof(Bgpasn_t);
223 r->value.buffer.elements = 0;
224 break;
225 case BGP_dpa_addr:
226 if (rp->set & BGP_SET_dpa_addrv6)
227 {
228 r->value.buffer.data = rp->dpa_addr.v6;
229 r->value.buffer.size = sizeof(rp->dpa_addr.v6);
230 r->value.buffer.elements = 0;
231 r->type = bgp->type_ipv6addr;
232 }
233 else
234 {
235 r->value.number = rp->dpa_addr.v4;
236 r->type = bgp->type_ipv4addr;
237 }
238 break;
239 case BGP_dpa_addrv4:
240 r->value.number = (rp->set & BGP_SET_dpa_addrv6) ? 0 : rp->dpa_addr.v4;
241 break;
242 case BGP_dpa_addrv6:
243 r->value.buffer.data = (rp->set & BGP_SET_dpa_addrv6) ? rp->dpa_addr.v6 : noipv6;
244 r->value.buffer.size = sizeof(rp->dpa_addr.v6);
245 r->value.buffer.elements = 0;
246 break;
247 case BGP_dpa_as:
248 r->value.number = rp->dpa_as ? rp->dpa_as : rp->dpa_as32;
249 break;
250 case BGP_dpa_as16:
251 r->value.number = rp->dpa_as;
252 break;
253 case BGP_dpa_as32:
254 r->value.number = rp->dpa_as32;
255 break;
256 case BGP_dst_addr:
257 if (rp->set & BGP_SET_dst_addrv6)
258 {
259 r->value.buffer.data = rp->dst_addr.v6;
260 r->value.buffer.size = sizeof(rp->dst_addr.v6);
261 r->value.buffer.elements = 0;
262 r->type = bgp->type_ipv6addr;
263 }
264 else
265 {
266 r->value.number = rp->dst_addr.v4;
267 r->type = bgp->type_ipv4addr;
268 }
269 break;
270 case BGP_dst_addrv4:
271 r->value.number = (rp->set & BGP_SET_dst_addrv6) ? 0 : rp->dst_addr.v4;
272 break;
273 case BGP_dst_addrv6:
274 r->value.buffer.data = (rp->set & BGP_SET_dst_addrv6) ? rp->dst_addr.v6 : noipv6;
275 r->value.buffer.size = sizeof(rp->dst_addr.v6);
276 r->value.buffer.elements = 0;
277 break;
278 case BGP_dst_as:
279 r->value.number = rp->dst_as ? rp->dst_as : rp->dst_as32;
280 break;
281 case BGP_dst_as16:
282 r->value.number = rp->dst_as;
283 break;
284 case BGP_dst_as32:
285 r->value.number = rp->dst_as32;
286 break;
287 case BGP_extended:
288 r->value.buffer.data = rp->data + rp->extended.offset;
289 r->value.buffer.size = rp->extended.size;
290 r->value.buffer.elements = 0;
291 break;
292 case BGP_flags:
293 r->value.number = rp->flags;
294 break;
295 case BGP_hop:
296 if (rp->set & BGP_SET_hopv6)
297 {
298 r->value.buffer.data = rp->hop.v6;
299 r->value.buffer.size = sizeof(rp->hop.v6);
300 r->value.buffer.elements = 0;
301 r->type = bgp->type_ipv6addr;
302 }
303 else
304 {
305 r->value.number = rp->hop.v4;
306 r->type = bgp->type_ipv4addr;
307 }
308 break;
309 case BGP_hopv4:
310 r->value.number = (rp->set & BGP_SET_hopv6) ? 0 : rp->hop.v4;
311 break;
312 case BGP_hopv6:
313 r->value.buffer.data = (rp->set & BGP_SET_hopv6) ? rp->hop.v6 : noipv6;
314 r->value.buffer.size = sizeof(rp->hop.v6);
315 r->value.buffer.elements = 0;
316 break;
317 case BGP_id:
318 r->value.number = rp->id;
319 break;
320 case BGP_label:
321 r->value.number = rp->label;
322 break;
323 case BGP_labels:
324 r->value.buffer.data = rp->data + rp->labels.offset;
325 r->value.buffer.size = rp->labels.size * sizeof(Bgpnum_t);
326 r->value.buffer.elements = 0;
327 break;
328 case BGP_local:
329 r->value.number = rp->local;
330 break;
331 case BGP_med:
332 r->value.number = rp->med;
333 break;
334 case BGP_message:
335 r->value.number = rp->message;
336 break;
337 case BGP_mvpn:
338 r->value.number = !!(rp->set & BGP_SET_mvpn);
339 break;
340 case BGP_new_state:
341 r->value.number = rp->type == BGP_TYPE_state_change ? rp->new_state : 0;
342 break;
343 case BGP_old_state:
344 r->value.number = rp->type == BGP_TYPE_state_change ? rp->old_state : 0;
345 break;
346 case BGP_origin:
347 r->value.number = rp->origin ? rp->origin : '0';
348 break;
349 case BGP_originator:
350 if (rp->set & BGP_SET_originatorv6)
351 {
352 r->value.buffer.data = rp->originator.v6;
353 r->value.buffer.size = sizeof(rp->originator.v6);
354 r->value.buffer.elements = 0;
355 r->type = bgp->type_ipv6addr;
356 }
357 else
358 {
359 r->value.number = rp->originator.v4;
360 r->type = bgp->type_ipv4addr;
361 }
362 break;
363 case BGP_path:
364 if (rp->path.size)
365 {
366 r->value.buffer.data = rp->data + rp->path.offset;
367 r->value.buffer.size = rp->path.size * sizeof(Bgpasn_t);
368 r->value.buffer.elements = rp->path.elements;
369 r->type = bgp->type_as16path;
370 }
371 else
372 {
373 r->value.buffer.data = rp->data + rp->path32.offset;
374 r->value.buffer.size = rp->path32.size * sizeof(Bgpnum_t);
375 r->value.buffer.elements = rp->path32.elements;
376 r->type = bgp->type_as32path;
377 }
378 break;
379 case BGP_path16:
380 r->value.buffer.data = rp->data + rp->path.offset;
381 r->value.buffer.size = rp->path.size * sizeof(Bgpasn_t);
382 r->value.buffer.elements = rp->path.elements;
383 break;
384 case BGP_path32:
385 r->value.buffer.data = rp->data + rp->path32.offset;
386 r->value.buffer.size = rp->path32.size * sizeof(Bgpnum_t);
387 r->value.buffer.elements = rp->path32.elements;
388 break;
389 case BGP_prefix:
390 if (rp->set & BGP_SET_prefixv6)
391 {
392 r->value.buffer.data = rp->prefixv6;
393 r->value.buffer.size = sizeof(rp->prefixv6);
394 r->value.buffer.elements = 0;
395 r->type = bgp->type_ipv6prefix;
396 }
397 else
398 {
399 r->value.number = (Cxnumber_t)rp->addr.v4 * 64 + rp->bits;
400 r->type = bgp->type_ipv4prefix;
401 }
402 break;
403 case BGP_prefixv4:
404 r->value.number = (rp->set & BGP_SET_prefixv6) ? 0 : ((Cxnumber_t)rp->addr.v4 * 64 + rp->bits);
405 break;
406 case BGP_prefixv6:
407 r->value.buffer.data = (rp->set & BGP_SET_prefixv6) ? rp->prefixv6 : noipv6;
408 r->value.buffer.size = sizeof(rp->prefixv6);
409 r->value.buffer.elements = 0;
410 break;
411 case BGP_rd_addr:
412 if (rp->afi == MRT_AFI_IPV6)
413 {
414 r->value.buffer.data = rp->rd_addr.v6;
415 r->value.buffer.size = sizeof(rp->rd_addr.v6);
416 r->value.buffer.elements = 0;
417 r->type = bgp->type_ipv6addr;
418 }
419 else
420 {
421 r->value.number = rp->rd_addr.v4;
422 r->type = bgp->type_ipv4addr;
423 }
424 break;
425 case BGP_rd_as:
426 r->value.number = rp->rd_as;
427 break;
428 case BGP_rd_number:
429 r->value.number = rp->rd_number;
430 break;
431 case BGP_rd_type:
432 r->value.number = rp->rd_type;
433 break;
434 case BGP_safi:
435 r->value.number = rp->safi ? rp->safi : MRT_SAFI_NLRI_UCAST_FORWARD;
436 break;
437 case BGP_src_addr:
438 if (rp->set & BGP_SET_src_addrv6)
439 {
440 r->value.buffer.data = rp->src_addr.v6;
441 r->value.buffer.size = sizeof(rp->src_addr.v6);
442 r->value.buffer.elements = 0;
443 r->type = bgp->type_ipv6addr;
444 }
445 else
446 {
447 r->value.number = rp->src_addr.v4;
448 r->type = bgp->type_ipv4addr;
449 }
450 break;
451 case BGP_src_addrv4:
452 r->value.number = (rp->set & BGP_SET_src_addrv6) ? 0 : rp->src_addr.v4;
453 break;
454 case BGP_src_addrv6:
455 r->value.buffer.data = (rp->set & BGP_SET_src_addrv6) ? rp->src_addr.v6 : noipv6;
456 r->value.buffer.size = sizeof(rp->src_addr.v6);
457 r->value.buffer.elements = 0;
458 break;
459 case BGP_src_as:
460 r->value.number = rp->src_as ? rp->src_as : rp->src_as32;
461 break;
462 case BGP_src_as16:
463 r->value.number = rp->src_as;
464 break;
465 case BGP_src_as32:
466 r->value.number = rp->src_as32;
467 break;
468 case BGP_stamp:
469 r->value.number = rp->stamp;
470 break;
471 case BGP_time:
472 r->value.number = rp->time ? rp->time : rp->stamp;
473 break;
474 case BGP_type:
475 r->value.number = rp->type;
476 break;
477 case BGP_unknown:
478 r->value.string.data = rp->data + rp->unknown.offset;
479 r->value.string.size = rp->unknown.size;
480 break;
481 case BGP_usec:
482 r->value.number = rp->usec;
483 break;
484 case BGP_weight:
485 r->value.number = rp->weight;
486 break;
487 /*DEPRECATED*/
488 case BGP_cluster_len:
489 r->value.number = rp->cluster.size;
490 break;
491 case BGP_community_len:
492 r->value.number = rp->community.size;
493 break;
494 case BGP_extended_len:
495 r->value.number = rp->extended.size / 8;
496 break;
497 case BGP_labels_len:
498 r->value.number = rp->labels.size / 2;
499 break;
500 case BGP_path_len:
501 r->value.number = rp->path.size ? rp->path.elements : rp->path32.size ? rp->path32.elements : 0;
502 break;
503 case BGP_path16_len:
504 r->value.number = rp->path.size ? rp->path.elements : 0;
505 break;
506 case BGP_path32_len:
507 r->value.number = rp->path32.size ? rp->path32.elements : 0;
508 break;
509 default:
510 r->value.number = (vp->index & 1) ? 0 : (rp->attr & vp->index) != 0;
511 break;
512 }
513 return 0;
514 }
515
516 static Cxcallout_t local_callouts[] =
517 {
518 CXC(CX_GET, "void", "void", op_get, 0)
519 };
520
521 static int
bgp_get(Cx_t * cx,Cxinstruction_t * pc,Cxoperand_t * r,Cxoperand_t * a,Cxoperand_t * b,void * data,Cxdisc_t * disc)522 bgp_get(Cx_t* cx, Cxinstruction_t* pc, Cxoperand_t* r, Cxoperand_t* a, Cxoperand_t* b, void* data, Cxdisc_t* disc)
523 {
524 Cxvariable_t* vp = (Cxvariable_t*)pc->data.variable;
525 void* save;
526 int i;
527
528 save = DSSRECORD(data)->data;
529 DSSRECORD(data)->data = &BGPDATA(data)->sub + (((Cxvariable_t*)pc->data.variable)->index == BGP_key);
530 i = op_get(cx, pc, r, a, b, data, disc);
531 DSSRECORD(data)->data = save;
532 return i;
533 }
534
535 static Cxmember_t bgp_member =
536 {
537 bgp_get,
538 0,
539 (Dt_t*)&fields[0]
540 };
541
542 static Cxtype_t types[] =
543 {
544 { "bgp_t", "BGP route data.", { { 0 }, CX_REFERENCED }, (Cxtype_t*)"number", 0, 0, 0, 0, 0, 0, 0, { 0, 0, CX_UNSIGNED|CX_INTEGER, 4 }, 0, &bgp_member },
545 { 0 }
546 };
547
548 /*
549 * methf
550 */
551
552 extern Dsslib_t dss_lib_bgp;
553
554 static Dssmeth_t*
bgpmeth(const char * name,const char * options,const char * schema,Dssdisc_t * disc,Dssmeth_t * meth)555 bgpmeth(const char* name, const char* options, const char* schema, Dssdisc_t* disc, Dssmeth_t* meth)
556 {
557 int i;
558 char* s;
559 Dssformat_t* fp;
560 Dssmeth_t* copy;
561
562 if (!dtsize(meth->formats))
563 {
564 cxaddvariable(meth->cx, NiL, disc);
565 for (i = 0; types[i].name; i++)
566 if (cxaddtype(meth->cx, &types[i], disc))
567 return 0;
568 for (i = 0; i < elementsof(local_callouts); i++)
569 if (cxaddcallout(meth->cx, &local_callouts[i], disc))
570 return 0;
571 for (i = 0; fields[i].name; i++)
572 if (cxaddvariable(meth->cx, &fields[i], disc))
573 return 0;
574 for (fp = bgp_formats; fp; fp = fp->next)
575 dtinsert(meth->formats, fp);
576 }
577 if (options)
578 {
579 if (dssoptlib(meth->cx->buf, &dss_lib_bgp, usage, disc))
580 return 0;
581 s = sfstruse(meth->cx->buf);
582 i = 0;
583 for (;;)
584 {
585 switch (optstr(options, s))
586 {
587 case 'a':
588 i |= BGP_METHOD_ANONYMIZE;
589 continue;
590 case '?':
591 if (disc->errorf)
592 (*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg);
593 return 0;
594 case ':':
595 if (disc->errorf)
596 (*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg);
597 return 0;
598 }
599 break;
600 }
601 if (i)
602 {
603 if (!(copy = newof(0, Dssmeth_t, 1, 0)))
604 {
605 if (disc->errorf)
606 (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
607 return 0;
608 }
609 *copy = *meth;
610 meth = copy;
611 meth->flags = i;
612 }
613 }
614 return meth;
615 }
616
617 /*
618 * openf
619 */
620
621 static int
bgpopen(Dss_t * dss,Dssdisc_t * disc)622 bgpopen(Dss_t* dss, Dssdisc_t* disc)
623 {
624 Bgp_t* bgp;
625
626 if (!(bgp = vmnewof(dss->vm, 0, Bgp_t, 1, 0)) ||
627 !(bgp->type_as16path = cxtype(dss->cx, "as16path_t", disc)) ||
628 !(bgp->type_as32path = cxtype(dss->cx, "as32path_t", disc)) ||
629 !(bgp->type_cluster = cxtype(dss->cx, "cluster_t", disc)) ||
630 !(bgp->type_community = cxtype(dss->cx, "community_t", disc)) ||
631 !(bgp->type_extended = cxtype(dss->cx, "extended_t", disc)) ||
632 !(bgp->type_ipv4addr = cxtype(dss->cx, "ipv4addr_t", disc)) ||
633 !(bgp->type_ipv4prefix = cxtype(dss->cx, "ipv4prefix_t", disc)) ||
634 !(bgp->type_ipv6addr = cxtype(dss->cx, "ipv6addr_t", disc)) ||
635 !(bgp->type_ipv6prefix = cxtype(dss->cx, "ipv6prefix_t", disc)) ||
636 !(bgp->tmp = sfstropen()))
637 {
638 if (bgp)
639 vmfree(dss->vm, bgp);
640 if (disc->errorf)
641 (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
642 return -1;
643 }
644 dss->data = bgp;
645 return 0;
646 }
647
648 /*
649 * closef
650 */
651
652 static int
bgpclose(Dss_t * dss,Dssdisc_t * disc)653 bgpclose(Dss_t* dss, Dssdisc_t* disc)
654 {
655 Bgp_t* bgp;
656
657 if (!(bgp = (Bgp_t*)dss->data) || !bgp->tmp)
658 return -1;
659 sfstrclose(bgp->tmp);
660 return 0;
661 }
662
663 static const char* libraries[] = { "time_t", "ip_t", 0 };
664
665 static Dssmeth_t method =
666 {
667 "bgp",
668 "BGP router dump and announce/withdraw messages",
669 CXH,
670 bgpmeth,
671 bgpopen,
672 bgpclose,
673 0
674 };
675
676 Dsslib_t dss_lib_bgp =
677 {
678 "bgp",
679 "bgp method"
680 "[-1ls5Pp0?\n@(#)$Id: dss bgp method (AT&T Research) 2012-06-14 $\n]"
681 USAGE_LICENSE,
682 CXH,
683 &libraries[0],
684 &method,
685 };
686