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