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