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 {
10 	uchar	vihl;		/* Version and header length */
11 	uchar	tos;		/* Type of service */
12 	uchar	length[2];	/* packet length */
13 	uchar	id[2];		/* ip->identification */
14 	uchar	frag[2];	/* Fragment information */
15 	uchar	ttl;		/* Time to live */
16 	uchar	proto;		/* Protocol */
17 	uchar	cksum[2];	/* Header checksum */
18 	uchar	src[4];		/* IP source */
19 	uchar	dst[4];		/* IP destination */
20 };
21 
22 enum
23 {
24 	IPHDR		= 20,		/* sizeof(Iphdr) */
25 	IP_VER		= 0x40,		/* Using IP version 4 */
26 	IP_DF		= 0x4000,	/* Don't fragment */
27 	IP_MF		= 0x2000,	/* More fragments */
28 };
29 
30 static Mux p_mux[] =
31 {
32 	{ "icmp", 1, },
33 	{ "igmp", 2, },
34 	{ "ggp", 3, },
35 	{ "ip", 4, },
36 	{ "st", 5, },
37 	{ "tcp", 6, },
38 	{ "ucl", 7, },
39 	{ "egp", 8, },
40 	{ "igp", 9, },
41 	{ "bbn-rcc-mon", 10, },
42 	{ "nvp-ii", 11, },
43 	{ "pup", 12, },
44 	{ "argus", 13, },
45 	{ "emcon", 14, },
46 	{ "xnet", 15, },
47 	{ "chaos", 16, },
48 	{ "udp", 17, },
49 	{ "mux", 18, },
50 	{ "dcn-meas", 19, },
51 	{ "hmp", 20, },
52 	{ "prm", 21, },
53 	{ "xns-idp", 22, },
54 	{ "trunk-1", 23, },
55 	{ "trunk-2", 24, },
56 	{ "leaf-1", 25, },
57 	{ "leaf-2", 26, },
58 	{ "rdp", 27, },
59 	{ "irtp", 28, },
60 	{ "iso-tp4", 29, },
61 	{ "netblt", 30, },
62 	{ "mfe-nsp", 31, },
63 	{ "merit-inp", 32, },
64 	{ "sep", 33, },
65 	{ "3pc", 34, },
66 	{ "idpr", 35, },
67 	{ "xtp", 36, },
68 	{ "ddp", 37, },
69 	{ "idpr-cmtp", 38, },
70 	{ "tp++", 39, },
71 	{ "il", 40, },
72 	{ "sip", 41, },
73 	{ "sdrp", 42, },
74 	{ "sip-sr", 43, },
75 	{ "sip-frag", 44, },
76 	{ "idrp", 45, },
77 	{ "rsvp", 46, },
78 	{ "gre", 47, },
79 	{ "mhrp", 48, },
80 	{ "bna", 49, },
81 	{ "sipp-esp", 50, },
82 	{ "sipp-ah", 51, },
83 	{ "i-nlsp", 52, },
84 	{ "swipe", 53, },
85 	{ "nhrp", 54, },
86 	{ "any", 61, },
87 	{ "cftp", 62, },
88 	{ "any", 63, },
89 	{ "sat-expak", 64, },
90 	{ "kryptolan", 65, },
91 	{ "rvd", 66, },
92 	{ "ippc", 67, },
93 	{ "any", 68, },
94 	{ "sat-mon", 69, },
95 	{ "visa", 70, },
96 	{ "ipcv", 71, },
97 	{ "cpnx", 72, },
98 	{ "cphb", 73, },
99 	{ "wsn", 74, },
100 	{ "pvp", 75, },
101 	{ "br-sat-mon", 76, },
102 	{ "sun-nd", 77, },
103 	{ "wb-mon", 78, },
104 	{ "wb-expak", 79, },
105 	{ "iso-ip", 80, },
106 	{ "vmtp", 81, },
107 	{ "secure-vmtp", 82, },
108 	{ "vines", 83, },
109 	{ "ttp", 84, },
110 	{ "nsfnet-igp", 85, },
111 	{ "dgp", 86, },
112 	{ "tcf", 87, },
113 	{ "igrp", 88, },
114 	{ "ospf", 89, },
115 	{ "sprite-rpc", 90, },
116 	{ "larp", 91, },
117 	{ "mtp", 92, },
118 	{ "ax.25", 93, },
119 	{ "ipip", 94, },
120 	{ "micp", 95, },
121 	{ "scc-sp", 96, },
122 	{ "etherip", 97, },
123 	{ "encap", 98, },
124 	{ "any", 99, },
125 	{ "gmtp", 100, },
126 	{ "rudp", 254, },
127 	{ 0 }
128 };
129 
130 enum
131 {
132 	Os,	/* source */
133 	Od,	/* destination */
134 	Osd,	/* source or destination */
135 	Ot,	/* type */
136 };
137 
138 static Field p_fields[] =
139 {
140 	{"s",	Fv4ip,	Os,	"source address",	} ,
141 	{"d",	Fv4ip,	Od,	"destination address",	} ,
142 	{"a",	Fv4ip,	Osd,	"source|destination address",} ,
143 	{"sd",	Fv4ip,	Osd,	"source|destination address",} ,
144 	{"t",	Fnum,	Ot,	"sub protocol number",	} ,
145 	{0}
146 };
147 
148 static void
p_compile(Filter * f)149 p_compile(Filter *f)
150 {
151 	Mux *m;
152 
153 	if(f->op == '='){
154 		compile_cmp(ip.name, f, p_fields);
155 		return;
156 	}
157 	for(m = p_mux; m->name != nil; m++)
158 		if(strcmp(f->s, m->name) == 0){
159 			f->pr = m->pr;
160 			f->ulv = m->val;
161 			f->subop = Ot;
162 			return;
163 		}
164 	sysfatal("unknown ip field or protocol: %s", f->s);
165 }
166 
167 static int
p_filter(Filter * f,Msg * m)168 p_filter(Filter *f, Msg *m)
169 {
170 	Hdr *h;
171 
172 	if(m->pe - m->ps < IPHDR)
173 		return 0;
174 
175 	h = (Hdr*)m->ps;
176 	m->ps += ((h->vihl&0xf)<<2);
177 
178 	switch(f->subop){
179 	case Os:
180 		return NetL(h->src) == f->ulv;
181 	case Od:
182 		return NetL(h->dst) == f->ulv;
183 	case Osd:
184 		return NetL(h->src) == f->ulv || NetL(h->dst) == f->ulv;
185 	case Ot:
186 		return h->proto == f->ulv;
187 	}
188 	return 0;
189 }
190 
191 static int
p_seprint(Msg * m)192 p_seprint(Msg *m)
193 {
194 	Hdr *h;
195 	int f;
196 	int len;
197 
198 	if(m->pe - m->ps < IPHDR)
199 		return -1;
200 	h = (Hdr*)m->ps;
201 
202 	/* next protocol, just dump unless this is the first fragment */
203 	m->pr = &dump;
204 	f = NetS(h->frag);
205 	if((f & ~(IP_DF|IP_MF)) == 0)
206 		demux(p_mux, h->proto, h->proto, m, &dump);
207 
208 	/* truncate the message if there's extra */
209 	len = NetS(h->length);
210 	if(len < m->pe - m->ps)
211 		m->pe = m->ps + len;
212 
213 	/* next header */
214 	m->ps += ((h->vihl&0xf)<<2);
215 
216 	m->p = seprint(m->p, m->e, "s=%V d=%V id=%4.4ux frag=%4.4ux ttl=%3d pr=%d ln=%d",
217 			h->src, h->dst,
218 			NetS(h->id),
219 			NetS(h->frag),
220 			h->ttl,
221 			h->proto,
222 			NetS(h->length)
223 			);
224 	return 0;
225 }
226 
227 Proto ip =
228 {
229 	"ip",
230 	p_compile,
231 	p_filter,
232 	p_seprint,
233 	p_mux,
234 	"%lud",
235 	p_fields,
236 	defaultframer
237 };
238