xref: /plan9/sys/src/cmd/ip/snoopy/icmp.c (revision e4556204f7a17d35312ca6493b4391646c5ea7a2)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "protos.h"
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier typedef struct Hdr	Hdr;
89a747e4fSDavid du Colombier struct Hdr
99a747e4fSDavid du Colombier {	uchar	type;
109a747e4fSDavid du Colombier 	uchar	code;
119a747e4fSDavid du Colombier 	uchar	cksum[2];	/* Checksum */
129a747e4fSDavid du Colombier 	uchar	data[1];
139a747e4fSDavid du Colombier };
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier enum
169a747e4fSDavid du Colombier {
179a747e4fSDavid du Colombier 	ICMPLEN=	4,
189a747e4fSDavid du Colombier };
199a747e4fSDavid du Colombier 
209a747e4fSDavid du Colombier enum
219a747e4fSDavid du Colombier {
229a747e4fSDavid du Colombier 	Ot,	/* type */
239a747e4fSDavid du Colombier 	Op,	/* next protocol */
249a747e4fSDavid du Colombier };
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier static Field p_fields[] =
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier 	{"t",		Fnum,	Ot,	"type",	} ,
299a747e4fSDavid du Colombier 	{0}
309a747e4fSDavid du Colombier };
319a747e4fSDavid du Colombier 
329a747e4fSDavid du Colombier enum
339a747e4fSDavid du Colombier {
349a747e4fSDavid du Colombier 	EchoRep=	0,
359a747e4fSDavid du Colombier 	Unreachable=	3,
369a747e4fSDavid du Colombier 	SrcQuench=	4,
379a747e4fSDavid du Colombier 	Redirect=	5,
389a747e4fSDavid du Colombier 	EchoReq=	8,
399a747e4fSDavid du Colombier 	TimeExceed=	11,
409a747e4fSDavid du Colombier 	ParamProb=	12,
419a747e4fSDavid du Colombier 	TSreq=		13,
429a747e4fSDavid du Colombier 	TSrep=		14,
439a747e4fSDavid du Colombier 	InfoReq=	15,
449a747e4fSDavid du Colombier 	InfoRep=	16,
459a747e4fSDavid du Colombier };
469a747e4fSDavid du Colombier 
479a747e4fSDavid du Colombier static Mux p_mux[] =
489a747e4fSDavid du Colombier {
499a747e4fSDavid du Colombier 	{"ip",	Unreachable, },
509a747e4fSDavid du Colombier 	{"ip",	SrcQuench, },
519a747e4fSDavid du Colombier 	{"ip",	Redirect, },
529a747e4fSDavid du Colombier 	{"ip",	TimeExceed, },
539a747e4fSDavid du Colombier 	{"ip",	ParamProb, },
549a747e4fSDavid du Colombier 	{0},
559a747e4fSDavid du Colombier };
569a747e4fSDavid du Colombier 
57*e4556204SDavid du Colombier char *icmpmsg[256] =
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier [EchoRep]	"EchoRep",
609a747e4fSDavid du Colombier [Unreachable]	"Unreachable",
619a747e4fSDavid du Colombier [SrcQuench]	"SrcQuench",
629a747e4fSDavid du Colombier [Redirect]	"Redirect",
639a747e4fSDavid du Colombier [EchoReq]	"EchoReq",
649a747e4fSDavid du Colombier [TimeExceed]	"TimeExceed",
659a747e4fSDavid du Colombier [ParamProb]	"ParamProb",
669a747e4fSDavid du Colombier [TSreq]		"TSreq",
679a747e4fSDavid du Colombier [TSrep]		"TSrep",
689a747e4fSDavid du Colombier [InfoReq]	"InfoReq",
699a747e4fSDavid du Colombier [InfoRep]	"InfoRep",
709a747e4fSDavid du Colombier };
719a747e4fSDavid du Colombier 
729a747e4fSDavid du Colombier static void
p_compile(Filter * f)739a747e4fSDavid du Colombier p_compile(Filter *f)
749a747e4fSDavid du Colombier {
759a747e4fSDavid du Colombier 	if(f->op == '='){
760b9a5132SDavid du Colombier 		compile_cmp(icmp.name, f, p_fields);
779a747e4fSDavid du Colombier 		return;
789a747e4fSDavid du Colombier 	}
799a747e4fSDavid du Colombier 	if(strcmp(f->s, "ip") == 0){
809a747e4fSDavid du Colombier 		f->pr = p_mux->pr;
819a747e4fSDavid du Colombier 		f->subop = Op;
829a747e4fSDavid du Colombier 		return;
839a747e4fSDavid du Colombier 	}
849a747e4fSDavid du Colombier 	sysfatal("unknown icmp field or protocol: %s", f->s);
859a747e4fSDavid du Colombier }
869a747e4fSDavid du Colombier 
879a747e4fSDavid du Colombier static int
p_filter(Filter * f,Msg * m)889a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m)
899a747e4fSDavid du Colombier {
909a747e4fSDavid du Colombier 	Hdr *h;
919a747e4fSDavid du Colombier 
929a747e4fSDavid du Colombier 	if(m->pe - m->ps < ICMPLEN)
939a747e4fSDavid du Colombier 		return 0;
949a747e4fSDavid du Colombier 
959a747e4fSDavid du Colombier 	h = (Hdr*)m->ps;
969a747e4fSDavid du Colombier 	m->ps += ICMPLEN;
979a747e4fSDavid du Colombier 
989a747e4fSDavid du Colombier 	switch(f->subop){
999a747e4fSDavid du Colombier 	case Ot:
1009a747e4fSDavid du Colombier 		if(h->type == f->ulv)
1019a747e4fSDavid du Colombier 			return 1;
1029a747e4fSDavid du Colombier 		break;
1039a747e4fSDavid du Colombier 	case Op:
1049a747e4fSDavid du Colombier 		switch(h->type){
1059a747e4fSDavid du Colombier 		case Unreachable:
1069a747e4fSDavid du Colombier 		case TimeExceed:
1079a747e4fSDavid du Colombier 		case SrcQuench:
1089a747e4fSDavid du Colombier 		case Redirect:
1099a747e4fSDavid du Colombier 		case ParamProb:
1109a747e4fSDavid du Colombier 			m->ps += 4;
1119a747e4fSDavid du Colombier 			return 1;
1129a747e4fSDavid du Colombier 		}
1139a747e4fSDavid du Colombier 	}
1149a747e4fSDavid du Colombier 	return 0;
1159a747e4fSDavid du Colombier }
1169a747e4fSDavid du Colombier 
1179a747e4fSDavid du Colombier static int
p_seprint(Msg * m)1189a747e4fSDavid du Colombier p_seprint(Msg *m)
1199a747e4fSDavid du Colombier {
1209a747e4fSDavid du Colombier 	Hdr *h;
1219a747e4fSDavid du Colombier 	char *tn;
1229a747e4fSDavid du Colombier 	char *p = m->p;
1239a747e4fSDavid du Colombier 	char *e = m->e;
1249a747e4fSDavid du Colombier 	ushort cksum2, cksum;
1259a747e4fSDavid du Colombier 
1269a747e4fSDavid du Colombier 	h = (Hdr*)m->ps;
1279a747e4fSDavid du Colombier 	m->ps += ICMPLEN;
1289a747e4fSDavid du Colombier 	m->pr = &dump;
1299a747e4fSDavid du Colombier 
1309a747e4fSDavid du Colombier 	if(m->pe - m->ps < ICMPLEN)
1319a747e4fSDavid du Colombier 		return -1;
1329a747e4fSDavid du Colombier 
1339a747e4fSDavid du Colombier 	tn = icmpmsg[h->type];
1349a747e4fSDavid du Colombier 	if(tn == nil)
1359a747e4fSDavid du Colombier 		p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
1369a747e4fSDavid du Colombier 			h->code, (ushort)NetS(h->cksum));
1379a747e4fSDavid du Colombier 	else
1389a747e4fSDavid du Colombier 		p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
1399a747e4fSDavid du Colombier 			h->code, (ushort)NetS(h->cksum));
1409a747e4fSDavid du Colombier 	if(Cflag){
1419a747e4fSDavid du Colombier 		cksum = NetS(h->cksum);
1429a747e4fSDavid du Colombier 		h->cksum[0] = 0;
1439a747e4fSDavid du Colombier 		h->cksum[1] = 0;
1449a747e4fSDavid du Colombier 		cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMPLEN) & 0xffff;
1459a747e4fSDavid du Colombier 		if(cksum != cksum2)
1469a747e4fSDavid du Colombier 			p = seprint(p,e, " !ck=%4.4ux", cksum2);
1479a747e4fSDavid du Colombier 	}
1489a747e4fSDavid du Colombier 	switch(h->type){
1499a747e4fSDavid du Colombier 	case EchoRep:
1509a747e4fSDavid du Colombier 	case EchoReq:
1519a747e4fSDavid du Colombier 		m->ps += 4;
1529a747e4fSDavid du Colombier 		p = seprint(p, e, " id=%ux seq=%ux",
1539a747e4fSDavid du Colombier 			NetS(h->data), NetS(h->data+2));
1549a747e4fSDavid du Colombier 		break;
1559a747e4fSDavid du Colombier 	case TSreq:
1569a747e4fSDavid du Colombier 	case TSrep:
1579a747e4fSDavid du Colombier 		m->ps += 12;
1589a747e4fSDavid du Colombier 		p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
1599a747e4fSDavid du Colombier 			NetL(h->data), NetL(h->data+4),
1609a747e4fSDavid du Colombier 			NetL(h->data+8));
1619a747e4fSDavid du Colombier 		m->pr = nil;
1629a747e4fSDavid du Colombier 		break;
1639a747e4fSDavid du Colombier 	case InfoReq:
1649a747e4fSDavid du Colombier 	case InfoRep:
1659a747e4fSDavid du Colombier 		break;
1669a747e4fSDavid du Colombier 	case Unreachable:
1679a747e4fSDavid du Colombier 	case TimeExceed:
1689a747e4fSDavid du Colombier 	case SrcQuench:
1699a747e4fSDavid du Colombier 		m->ps += 4;
1709a747e4fSDavid du Colombier 		m->pr = &ip;
1719a747e4fSDavid du Colombier 		break;
1729a747e4fSDavid du Colombier 	case Redirect:
1739a747e4fSDavid du Colombier 		m->ps += 4;
1749a747e4fSDavid du Colombier 		m->pr = &ip;
1759a747e4fSDavid du Colombier 		p = seprint(p, e, "gw=%V", h->data);
1769a747e4fSDavid du Colombier 		break;
1779a747e4fSDavid du Colombier 	case ParamProb:
1789a747e4fSDavid du Colombier 		m->ps += 4;
1799a747e4fSDavid du Colombier 		m->pr = &ip;
1809a747e4fSDavid du Colombier 		p = seprint(p, e, "ptr=%2.2ux", h->data[0]);
1819a747e4fSDavid du Colombier 		break;
1829a747e4fSDavid du Colombier 	}
1839a747e4fSDavid du Colombier 	m->p = p;
1849a747e4fSDavid du Colombier 	return 0;
1859a747e4fSDavid du Colombier }
1869a747e4fSDavid du Colombier 
1879a747e4fSDavid du Colombier Proto icmp =
1889a747e4fSDavid du Colombier {
1899a747e4fSDavid du Colombier 	"icmp",
1909a747e4fSDavid du Colombier 	p_compile,
1919a747e4fSDavid du Colombier 	p_filter,
1929a747e4fSDavid du Colombier 	p_seprint,
1939a747e4fSDavid du Colombier 	p_mux,
194ed397113SDavid du Colombier 	"%lud",
1959a747e4fSDavid du Colombier 	p_fields,
1963ff48bf5SDavid du Colombier 	defaultframer,
1979a747e4fSDavid du Colombier };
198