plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

icmp.c (2963B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <ip.h>
      4 #include "dat.h"
      5 #include "protos.h"
      6 
      7 typedef struct Hdr	Hdr;
      8 struct Hdr
      9 {	uchar	type;
     10 	uchar	code;
     11 	uchar	cksum[2];	/* Checksum */
     12 	uchar	data[1];
     13 };
     14 
     15 enum
     16 {
     17 	ICMPLEN=	4
     18 };
     19 
     20 enum
     21 {
     22 	Ot,	/* type */
     23 	Op,	/* next protocol */
     24 };
     25 
     26 static Field p_fields[] =
     27 {
     28 	{"t",		Fnum,	Ot,	"type",	} ,
     29 	{0}
     30 };
     31 
     32 enum
     33 {
     34 	EchoRep=	0,
     35 	Unreachable=	3,
     36 	SrcQuench=	4,
     37 	Redirect=	5,
     38 	EchoReq=	8,
     39 	TimeExceed=	11,
     40 	ParamProb=	12,
     41 	TSreq=		13,
     42 	TSrep=		14,
     43 	InfoReq=	15,
     44 	InfoRep=	16
     45 };
     46 
     47 static Mux p_mux[] =
     48 {
     49 	{"ip",	Unreachable, },
     50 	{"ip",	SrcQuench, },
     51 	{"ip",	Redirect, },
     52 	{"ip",	TimeExceed, },
     53 	{"ip",	ParamProb, },
     54 	{0}
     55 };
     56 
     57 char *icmpmsg[256] =
     58 {
     59 [EchoRep]	"EchoRep",
     60 [Unreachable]	"Unreachable",
     61 [SrcQuench]	"SrcQuench",
     62 [Redirect]	"Redirect",
     63 [EchoReq]	"EchoReq",
     64 [TimeExceed]	"TimeExceed",
     65 [ParamProb]	"ParamProb",
     66 [TSreq]		"TSreq",
     67 [TSrep]		"TSrep",
     68 [InfoReq]	"InfoReq",
     69 [InfoRep]	"InfoRep"
     70 };
     71 
     72 static void
     73 p_compile(Filter *f)
     74 {
     75 	if(f->op == '='){
     76 		compile_cmp(udp.name, f, p_fields);
     77 		return;
     78 	}
     79 	if(strcmp(f->s, "ip") == 0){
     80 		f->pr = p_mux->pr;
     81 		f->subop = Op;
     82 		return;
     83 	}
     84 	sysfatal("unknown icmp field or protocol: %s", f->s);
     85 }
     86 
     87 static int
     88 p_filter(Filter *f, Msg *m)
     89 {
     90 	Hdr *h;
     91 
     92 	if(m->pe - m->ps < ICMPLEN)
     93 		return 0;
     94 
     95 	h = (Hdr*)m->ps;
     96 	m->ps += ICMPLEN;
     97 
     98 	switch(f->subop){
     99 	case Ot:
    100 		if(h->type == f->ulv)
    101 			return 1;
    102 		break;
    103 	case Op:
    104 		switch(h->type){
    105 		case Unreachable:
    106 		case TimeExceed:
    107 		case SrcQuench:
    108 		case Redirect:
    109 		case ParamProb:
    110 			m->ps += 4;
    111 			return 1;
    112 		}
    113 	}
    114 	return 0;
    115 }
    116 
    117 static int
    118 p_seprint(Msg *m)
    119 {
    120 	Hdr *h;
    121 	char *tn;
    122 	char *p = m->p;
    123 	char *e = m->e;
    124 	ushort cksum2, cksum;
    125 
    126 	h = (Hdr*)m->ps;
    127 	m->ps += ICMPLEN;
    128 	m->pr = &dump;
    129 
    130 	if(m->pe - m->ps < ICMPLEN)
    131 		return -1;
    132 
    133 	tn = icmpmsg[h->type];
    134 	if(tn == nil)
    135 		p = seprint(p, e, "t=%ud c=%d ck=%4.4ux", h->type,
    136 			h->code, (ushort)NetS(h->cksum));
    137 	else
    138 		p = seprint(p, e, "t=%s c=%d ck=%4.4ux", tn,
    139 			h->code, (ushort)NetS(h->cksum));
    140 	if(Cflag){
    141 		cksum = NetS(h->cksum);
    142 		h->cksum[0] = 0;
    143 		h->cksum[1] = 0;
    144 		cksum2 = ~ptclbsum((uchar*)h, m->pe - m->ps + ICMPLEN) & 0xffff;
    145 		if(cksum != cksum2)
    146 			p = seprint(p,e, " !ck=%4.4ux", cksum2);
    147 	}
    148 	switch(h->type){
    149 	case EchoRep:
    150 	case EchoReq:
    151 		m->ps += 4;
    152 		p = seprint(p, e, " id=%ux seq=%ux",
    153 			NetS(h->data), NetS(h->data+2));
    154 		break;
    155 	case TSreq:
    156 	case TSrep:
    157 		m->ps += 12;
    158 		p = seprint(p, e, " orig=%ud rcv=%ux xmt=%ux",
    159 			NetL(h->data), NetL(h->data+4),
    160 			NetL(h->data+8));
    161 		m->pr = nil;
    162 		break;
    163 	case InfoReq:
    164 	case InfoRep:
    165 		break;
    166 	case Unreachable:
    167 	case TimeExceed:
    168 	case SrcQuench:
    169 		m->ps += 4;
    170 		m->pr = &ip;
    171 		break;
    172 	case Redirect:
    173 		m->ps += 4;
    174 		m->pr = &ip;
    175 		p = seprint(p, e, "gw=%V", h->data);
    176 		break;
    177 	case ParamProb:
    178 		m->ps += 4;
    179 		m->pr = &ip;
    180 		p = seprint(p, e, "ptr=%2.2ux", h->data[0]);
    181 		break;
    182 	}
    183 	m->p = p;
    184 	return 0;
    185 }
    186 
    187 Proto icmp =
    188 {
    189 	"icmp",
    190 	p_compile,
    191 	p_filter,
    192 	p_seprint,
    193 	p_mux,
    194 	"%lud",
    195 	p_fields,
    196 	defaultframer
    197 };