1 /* rapd.c -- Reverse APD, from ARS packet to APD string description.
2  * Copyright (C) 2003 Salvatore Sanfilippo
3  * All rights reserved. */
4 
5 /* $Id: rapd.c,v 1.7 2004/04/10 00:45:11 antirez Exp $ */
6 
7 #include <sys/types.h>
8 #include <netinet/in.h>
9 #include <ctype.h>
10 
11 #include "ars.h"
12 
trimlastchar(char * s)13 void trimlastchar(char *s)
14 {
15 	int len = strlen(s);
16 	s[len-1] = '\0';
17 }
18 
ars_d_from_ars(char * dest,size_t len,struct ars_packet * pkt)19 int ars_d_from_ars(char *dest, size_t len, struct ars_packet *pkt)
20 {
21 	int j, err;
22 	struct adbuf buf;
23 
24 	if (len <= 0)
25 		return -ARS_OK;
26 	if (adbuf_init(&buf))
27 		return -ARS_NOMEM;
28 	for (j = 0; j < pkt->p_layer_nr; j++) {
29 		__D(printf("ReverseAPD-ing layer %d\n", j);)
30 		/* Skip NULL compilers */
31 		if (ars_linfo[pkt->p_layer[j].l_type].li_rapd != NULL) {
32 			/* Call the layer to string converter */
33 			err = ars_linfo[pkt->p_layer[j].l_type].li_rapd(&buf, pkt, j);
34 			if (err != -ARS_OK) {
35 				adbuf_free(&buf);
36 				return err;
37 			}
38 		}
39 	}
40 	adbuf_rtrim(&buf, 1);
41 	strlcpy(dest, adbuf_ptr(&buf), len);
42 	adbuf_free(&buf);
43 	return -ARS_OK;
44 }
45 
46 /* layer rapd methods */
ars_rapd_ip(struct adbuf * dest,struct ars_packet * pkt,int layer)47 int ars_rapd_ip(struct adbuf *dest, struct ars_packet *pkt, int layer)
48 {
49 	struct ars_iphdr *ip = pkt->p_layer[layer].l_data;
50 	struct ars_iphdr *defip = pkt->p_default[pkt->p_layer[layer].l_type];
51 	adbuf_printf(dest, "ip(");
52 	if (!defip || ip->ihl != defip->ihl)
53 		adbuf_printf(dest, "ihl=0x%1x,", ip->ihl);
54 	if (!defip || ip->version != defip->version)
55 		adbuf_printf(dest, "ver=0x%1x,", ip->version);
56 	if (!defip || ip->tos != defip->tos)
57 		adbuf_printf(dest, "tos=0x%02x,", ip->tos);
58 	adbuf_printf(dest, "totlen=%u,", ntohs(ip->tot_len));
59 	if (!defip || ip->id != defip->id)
60 		adbuf_printf(dest, "id=%u,", ntohs(ip->id));
61 	adbuf_printf(dest, "fragoff=%u,",
62 			(ntohs(ip->frag_off) & 0x1FFF) << 3);
63 	if (!defip ||
64 	    (ip->frag_off & ARS_IP_MF) != (defip->frag_off & ARS_IP_MF))
65 		adbuf_printf(dest, "mf=%d,",
66 				(htons(ip->frag_off) & ARS_IP_MF) != 0);
67 	if (!defip ||
68 	    (ip->frag_off & ARS_IP_DF) != (defip->frag_off & ARS_IP_DF))
69 		adbuf_printf(dest, "df=%d,",
70 				(htons(ip->frag_off) & ARS_IP_DF) != 0);
71 	if (!defip ||
72 	    (ip->frag_off & ARS_IP_RF) != (defip->frag_off & ARS_IP_RF))
73 		adbuf_printf(dest, "rf=%d,",
74 				(htons(ip->frag_off) & ARS_IP_RF) != 0);
75 	if (!defip || ip->ttl != defip->ttl)
76 		adbuf_printf(dest, "ttl=%u,", ip->ttl);
77 	/* TODO: the 'proto' field may not be added if the protocl
78 	 * that follows this layer looks as specified. */
79 	adbuf_printf(dest, "proto=%u,", ip->protocol);
80 	adbuf_printf(dest, "cksum=0x%04x,", ip->check);
81 	{
82 		unsigned char *x = (unsigned char*) &ip->saddr;
83 		adbuf_printf(dest, "saddr=%u.%u.%u.%u,",
84 				x[0], x[1], x[2], x[3]);
85 		x = (unsigned char*) &ip->daddr;
86 		adbuf_printf(dest, "daddr=%u.%u.%u.%u",
87 				x[0], x[1], x[2], x[3]);
88 	}
89 	adbuf_printf(dest, ")+");
90 	return -ARS_OK;
91 }
92 
ars_rapd_ipopt(struct adbuf * dest,struct ars_packet * pkt,int layer)93 int ars_rapd_ipopt(struct adbuf *dest, struct ars_packet *pkt, int layer)
94 {
95 	struct ars_ipopt ipopt;
96 	int len = pkt->p_layer[layer].l_size;
97 	unsigned char *optp = pkt->p_layer[layer].l_data;
98 	int optlen, i;
99 
100 	/* ip options may not be naturally aligned */
101 	memcpy(&ipopt, pkt->p_layer[layer].l_data, len);
102 	optlen = ipopt.len;
103 
104 	switch(ipopt.kind) {
105 	case ARS_IPOPT_EOL:
106 		adbuf_printf(dest, "ip.eol()+");
107 		break;
108 	case ARS_IPOPT_NOP:
109 		adbuf_printf(dest, "ip.nop()+");
110 		break;
111 	case ARS_IPOPT_RR:
112 	case ARS_IPOPT_LSRR:
113 	case ARS_IPOPT_SSRR:
114 		{
115 			int ptr = 4;
116 			char *optname = "";
117 
118 			switch(ipopt.kind) {
119 			case ARS_IPOPT_RR: optname="rr"; break;
120 			case ARS_IPOPT_LSRR: optname="lsrr"; break;
121 			case ARS_IPOPT_SSRR: optname="ssrr"; break;
122 			}
123 			adbuf_printf(dest, "ip.%s(ptr=%u,data=",
124 					optname, ipopt.un.rr.ptr);
125 			while(1) {
126 				unsigned char *x;
127 
128 				if (ptr > 37 ||
129 				    ptr > (optlen-3))
130 					break;
131 				x = optp + ptr - 1;
132 				adbuf_printf(dest, "%u.%u.%u.%u/",
133 						x[0],x[1],x[2],x[3]);
134 				ptr += 4;
135 			}
136 			if (ptr > 4)
137 				adbuf_rtrim(dest, 1);
138 			adbuf_printf(dest, ")+");
139 		}
140 		break;
141 	case ARS_IPOPT_TIMESTAMP:
142 		{
143 			int ptr = 5;
144 			int overflow = (ipopt.un.ts.flags & 0xF0)>>4;
145 			int flags = ipopt.un.ts.flags & 0xF;
146 			char *strflags;
147 			adbuf_printf(dest, "ip.ts(ptr=%u,", ipopt.un.ts.ptr);
148 			switch(flags) {
149 			case ARS_IPOPT_TS_TSONLY: strflags="tsonly"; break;
150 			case ARS_IPOPT_TS_TSANDADDR: strflags="tsandaddr"; break;
151 			case ARS_IPOPT_TS_PRESPEC: strflags="prespec"; break;
152 			default: strflags=NULL; break;
153 			}
154 			if (strflags) {
155 				adbuf_printf(dest, "flags=%s,", strflags);
156 			} else {
157 				adbuf_printf(dest, "flags=%u,", flags);
158 			}
159 			adbuf_printf(dest, "overflow=%u,data=", overflow);
160 			while(1) {
161 				unsigned char *x;
162 				__u32 ts;
163 
164 				if (ptr > 37 ||
165 				    ptr > (optlen-4))
166 					break;
167 				if (flags != ARS_IPOPT_TS_TSANDADDR &&
168 				    flags != ARS_IPOPT_TS_PRESPEC) {
169 					memcpy(&ts, optp+ptr-1, 4);
170 					ts = ntohl(ts);
171 					adbuf_printf(dest, "%u/", ts);
172 					ptr += 4;
173 				} else {
174 					x = optp + ptr - 1;
175 					memcpy(&ts, x+4, 4);
176 					adbuf_printf(dest, "%u@%u.%u.%u.%u/",
177 							ts,x[0],x[1],x[2],x[3]);
178 					ptr += 8;
179 				}
180 			}
181 			if (ptr > 5)
182 				adbuf_rtrim(dest, 1);
183 			adbuf_printf(dest, ")+");
184 		}
185 		break;
186 	default:
187 		adbuf_printf(dest, "ip.unknown(hex=");
188 		for (i = 0; i < optlen; i++) {
189 			adbuf_printf(dest, "0x%02x", optp[i]);
190 		}
191 		adbuf_printf(dest, ")+");
192 		break;
193 	}
194 	return -ARS_OK;
195 }
196 
ars_rapd_icmp(struct adbuf * dest,struct ars_packet * pkt,int layer)197 int ars_rapd_icmp(struct adbuf *dest, struct ars_packet *pkt, int layer)
198 {
199 	struct ars_icmphdr *icmp = pkt->p_layer[layer].l_data;
200 
201 	adbuf_printf(dest, "icmp(");
202 	adbuf_printf(dest, "type=%u,", icmp->type);
203 	adbuf_printf(dest, "code=%u,", icmp->code);
204 	if (icmp->type == ARS_ICMP_DEST_UNREACH ||
205 	    icmp->type == ARS_ICMP_TIME_EXCEEDED ||
206 	    icmp->type == ARS_ICMP_PARAMETERPROB ||
207 	    icmp->type == ARS_ICMP_SOURCE_QUENCH)
208 	{
209 		adbuf_printf(dest, "unused=%lu,", (unsigned long)
210 				ntohl(icmp->un.gateway));
211 	}
212 	if (icmp->type == ARS_ICMP_ECHOREPLY ||
213 	    icmp->type == ARS_ICMP_ECHO ||
214 	    icmp->type == ARS_ICMP_TIMESTAMP ||
215 	    icmp->type == ARS_ICMP_TIMESTAMPREPLY ||
216 	    icmp->type == ARS_ICMP_INFO_REQUEST ||
217 	    icmp->type == ARS_ICMP_INFO_REPLY)
218 	{
219 		adbuf_printf(dest, "id=%u,", ntohs(icmp->un.echo.id));
220 		adbuf_printf(dest, "seq=%u,", ntohs(icmp->un.echo.sequence));
221 	}
222 	if (icmp->type == ARS_ICMP_REDIRECT) {
223 		unsigned char x[4];
224 		memcpy(x, &icmp->un.gateway, 4);
225 		adbuf_printf(dest, "gw=%u.%u.%u.%u,",
226 				x[0], x[1], x[2], x[3]);
227 	}
228 	adbuf_rtrim(dest, 1);
229 	adbuf_printf(dest, ")+");
230 	return -ARS_OK;
231 }
232 
ars_rapd_udp(struct adbuf * dest,struct ars_packet * pkt,int layer)233 int ars_rapd_udp(struct adbuf *dest, struct ars_packet *pkt, int layer)
234 {
235 	struct ars_udphdr *udp = pkt->p_layer[layer].l_data;
236 	//struct ars_udphdr *defudp = pkt->p_default[pkt->p_layer[layer].l_type];
237 	adbuf_printf(dest, "udp(");
238 	adbuf_printf(dest, "sport=%u,", ntohs(udp->uh_sport));
239 	adbuf_printf(dest, "dport=%u,", ntohs(udp->uh_dport));
240 	adbuf_printf(dest, "len=%u,", ntohs(udp->uh_ulen));
241 	adbuf_printf(dest, "cksum=0x%04x", ntohs(udp->uh_sum));
242 	adbuf_printf(dest, ")+");
243 	return -ARS_OK;
244 }
245 
ars_rapd_tcp(struct adbuf * dest,struct ars_packet * pkt,int layer)246 int ars_rapd_tcp(struct adbuf *dest, struct ars_packet *pkt, int layer)
247 {
248 	struct ars_tcphdr *tcp = pkt->p_layer[layer].l_data;
249 	struct ars_tcphdr *deftcp = pkt->p_default[pkt->p_layer[layer].l_type];
250 	adbuf_printf(dest, "tcp(");
251 	adbuf_printf(dest, "sport=%u,", ntohs(tcp->th_sport));
252 	adbuf_printf(dest, "dport=%u,", ntohs(tcp->th_dport));
253 	adbuf_printf(dest, "seq=%lu,", ntohl(tcp->th_seq));
254 	adbuf_printf(dest, "ack=%lu,", ntohl(tcp->th_ack));
255 	if (!deftcp || tcp->th_x2 != deftcp->th_x2)
256 		adbuf_printf(dest, "x2=0x%1x,", tcp->th_x2);
257 	if (!deftcp || tcp->th_off != deftcp->th_off)
258 		adbuf_printf(dest, "off=%u,", tcp->th_off);
259 	adbuf_printf(dest, "flags=");
260 	if (tcp->th_flags & ARS_TCP_TH_FIN) adbuf_printf(dest, "f");
261 	if (tcp->th_flags & ARS_TCP_TH_SYN) adbuf_printf(dest, "s");
262 	if (tcp->th_flags & ARS_TCP_TH_RST) adbuf_printf(dest, "r");
263 	if (tcp->th_flags & ARS_TCP_TH_PUSH) adbuf_printf(dest, "p");
264 	if (tcp->th_flags & ARS_TCP_TH_ACK) adbuf_printf(dest, "a");
265 	if (tcp->th_flags & ARS_TCP_TH_URG) adbuf_printf(dest, "u");
266 	if (tcp->th_flags & ARS_TCP_TH_X) adbuf_printf(dest, "x");
267 	if (tcp->th_flags & ARS_TCP_TH_Y) adbuf_printf(dest, "y");
268 	adbuf_printf(dest, ",");
269 	adbuf_printf(dest, "win=%u,", ntohs(tcp->th_win));
270 	adbuf_printf(dest, "cksum=0x%04x,", ntohs(tcp->th_sum));
271 	if (!deftcp || tcp->th_urp != deftcp->th_urp)
272 		adbuf_printf(dest, "urp=%u,", ntohs(tcp->th_urp));
273 	adbuf_rtrim(dest, 1);
274 	adbuf_printf(dest, ")+");
275 	return -ARS_OK;
276 }
277 
ars_rapd_tcpopt(struct adbuf * dest,struct ars_packet * pkt,int layer)278 int ars_rapd_tcpopt(struct adbuf *dest, struct ars_packet *pkt, int layer)
279 {
280 	struct ars_tcpopt tcpopt;
281 	int len = pkt->p_layer[layer].l_size;
282 	unsigned char *optp = pkt->p_layer[layer].l_data;
283 	int optlen, i;
284 
285 	/* tcp options may not be naturally aligned */
286 	memcpy(&tcpopt, pkt->p_layer[layer].l_data, len);
287 	optlen = tcpopt.len;
288 
289 	switch(tcpopt.kind) {
290 	case ARS_TCPOPT_EOL:
291 		adbuf_printf(dest, "tcp.eol()+");
292 		break;
293 	case ARS_TCPOPT_NOP:
294 		adbuf_printf(dest, "tcp.nop()+");
295 		break;
296 	case ARS_TCPOPT_MAXSEG:
297 		adbuf_printf(dest, "tcp.mss(size=%u)+",
298 				ntohs(tcpopt.un.mss.size));
299 		break;
300 	case ARS_TCPOPT_WINDOW:
301 		adbuf_printf(dest, "tcp.wscale(shift=%u)+",
302 				tcpopt.un.win.shift);
303 		break;
304 	case ARS_TCPOPT_SACK_PERM:
305 		adbuf_printf(dest, "tcp.sackperm()+");
306 		break;
307 	case ARS_TCPOPT_SACK:
308 		adbuf_printf(dest, "tcp.sack(blocks=");
309 		{
310 			int blocks = (optlen-2)/8;
311 			for (i = 0; i < blocks; i++) {
312 				u_int32_t s_orig, s_size;
313 
314 				memcpy(&s_orig, tcpopt.un.sack[i].origin, 4);
315 				memcpy(&s_size, tcpopt.un.sack[i].size, 4);
316 				adbuf_printf(dest, "%lu-%lu",
317 					ntohl(s_orig),
318 					ntohl(s_size));
319 				if ((i+1) != blocks)
320 					adbuf_addchar(dest, '/');
321 			}
322 		}
323 		adbuf_printf(dest, ")+");
324 		break;
325 	case ARS_TCPOPT_ECHOREQUEST:
326 		{
327 			__u32 info;
328 			memcpy(&info, tcpopt.un.echo.info, 4);
329 			adbuf_printf(dest, "tcp.echoreq(info=%lu)+",
330 					(unsigned long) ntohl(info));
331 		}
332 		break;
333 	case ARS_TCPOPT_ECHOREPLY:
334 		{
335 			__u32 info;
336 			memcpy(&info, tcpopt.un.echo.info, 4);
337 			adbuf_printf(dest, "tcp.echoreply(info=%lu)+",
338 					(unsigned long) ntohl(info));
339 		}
340 		break;
341 	case ARS_TCPOPT_TIMESTAMP:
342 		{
343 			__u32 tsval, tsecr;
344 			memcpy(&tsval, tcpopt.un.timestamp.tsval, 4);
345 			memcpy(&tsecr, tcpopt.un.timestamp.tsecr, 4);
346 			adbuf_printf(dest, "tcp.timestamp(val=%lu,ecr=%lu)+",
347 				(unsigned long) ntohl(tsval),
348 				(unsigned long) ntohl(tsecr));
349 		}
350 		break;
351 	default:
352 		adbuf_printf(dest, "tcp.unknown(hex=");
353 		for (i = 0; i < optlen; i++) {
354 			adbuf_printf(dest, "%02x", optp[i]);
355 		}
356 		adbuf_printf(dest, ")+");
357 		break;
358 	}
359 	return -ARS_OK;
360 }
361 
ars_rapd_igrp(struct adbuf * dest,struct ars_packet * pkt,int layer)362 int ars_rapd_igrp(struct adbuf *dest, struct ars_packet *pkt, int layer)
363 {
364 	struct ars_igrphdr *igrp = pkt->p_layer[layer].l_data;
365 
366 	adbuf_printf(dest, "igrp(");
367 	adbuf_printf(dest, "version=%u,", igrp->version);
368 	if (igrp->opcode == ARS_IGRP_OPCODE_UPDATE) {
369 		adbuf_printf(dest, "opcode=update,", igrp->opcode);
370 	} else if (igrp->opcode == ARS_IGRP_OPCODE_REQUEST) {
371 		adbuf_printf(dest, "opcode=request,", igrp->opcode);
372 	} else {
373 		adbuf_printf(dest, "opcode=%u,", igrp->opcode);
374 	}
375 	adbuf_printf(dest, "edition=%u,", igrp->edition);
376 	adbuf_printf(dest, "autosys=%u,", htons(igrp->autosys));
377 	adbuf_printf(dest, "interior=%u,", htons(igrp->interior));
378 	adbuf_printf(dest, "system=%u,", htons(igrp->system));
379 	adbuf_printf(dest, "exterior=%u,", htons(igrp->exterior));
380 	adbuf_printf(dest, "cksum=0x%04x", ntohs(igrp->checksum));
381 	adbuf_printf(dest, ")+");
382 	return -ARS_OK;
383 }
384 
get_net_int24(void * ptr)385 static u_int32_t get_net_int24(void *ptr)
386 {
387 	unsigned char *x = (unsigned char*)ptr;
388 	u_int32_t u;
389 
390 	u = x[0] <<16 | x[1] << 8 | x[2];
391 	return u;
392 }
393 
ars_rapd_igrpentry(struct adbuf * dest,struct ars_packet * pkt,int layer)394 int ars_rapd_igrpentry(struct adbuf *dest, struct ars_packet *pkt, int layer)
395 {
396 	struct ars_igrpentry *entry = pkt->p_layer[layer].l_data;
397 	unsigned char *x = (unsigned char*) entry->destination;
398 
399 	adbuf_printf(dest, "igrp.entry(");
400 	adbuf_printf(dest, "dest=%u.%u.%u,", x[0], x[1], x[2]);
401 	adbuf_printf(dest, "delay=%u,", get_net_int24(entry->delay));
402 	adbuf_printf(dest, "bandwidth=%u,", get_net_int24(entry->bandwidth));
403 	adbuf_printf(dest, "mtu=%u,", entry->mtu[0] << 8 | entry->mtu[1]);
404 	adbuf_printf(dest, "reliability=%u,", entry->reliability);
405 	adbuf_printf(dest, "load=%u,", entry->load);
406 	adbuf_printf(dest, "hopcount=%u", entry->hopcount);
407 	adbuf_printf(dest, ")+");
408 	return -ARS_OK;
409 }
410 
ars_rapd_data(struct adbuf * dest,struct ars_packet * pkt,int layer)411 int ars_rapd_data(struct adbuf *dest, struct ars_packet *pkt, int layer)
412 {
413 	unsigned char *data = pkt->p_layer[layer].l_data;
414 	int dlen = pkt->p_layer[layer].l_size, i;
415 
416 	if (ars_test_option(pkt, ARS_OPT_RAPD_HEXDATA)) {
417 		adbuf_printf(dest, "data(hex=");
418 		for (i = 0; i < dlen; i++) {
419 			adbuf_printf(dest, "%02x", data[i]);
420 		}
421 		adbuf_printf(dest, ")+");
422 	} else {
423 		adbuf_printf(dest, "data(str=");
424 		for (i = 0; i < dlen; i++) {
425 			/* escape non-printable chars and chars
426 			 * having special meanings in APD packets. */
427 			if (isgraph(data[i]) &&
428 			    data[i] != '(' &&
429 			    data[i] != ')' &&
430 			    data[i] != '+' &&
431 			    data[i] != ',' &&
432 			    data[i] != '=')
433 				adbuf_printf(dest, "%c", data[i]);
434 			else
435 				adbuf_printf(dest, "\\%02x", data[i]);
436 		}
437 		adbuf_printf(dest, ")+");
438 	}
439 	return 0;
440 }
441