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 {
109a747e4fSDavid du Colombier uchar vihl; /* Version and header length */
119a747e4fSDavid du Colombier uchar tos; /* Type of service */
129a747e4fSDavid du Colombier uchar length[2]; /* packet length */
139a747e4fSDavid du Colombier uchar id[2]; /* ip->identification */
149a747e4fSDavid du Colombier uchar frag[2]; /* Fragment information */
159a747e4fSDavid du Colombier uchar ttl; /* Time to live */
169a747e4fSDavid du Colombier uchar proto; /* Protocol */
179a747e4fSDavid du Colombier uchar cksum[2]; /* Header checksum */
189a747e4fSDavid du Colombier uchar src[4]; /* IP source */
199a747e4fSDavid du Colombier uchar dst[4]; /* IP destination */
209a747e4fSDavid du Colombier };
219a747e4fSDavid du Colombier
229a747e4fSDavid du Colombier enum
239a747e4fSDavid du Colombier {
249a747e4fSDavid du Colombier IPHDR = 20, /* sizeof(Iphdr) */
259a747e4fSDavid du Colombier IP_VER = 0x40, /* Using IP version 4 */
269a747e4fSDavid du Colombier IP_DF = 0x4000, /* Don't fragment */
279a747e4fSDavid du Colombier IP_MF = 0x2000, /* More fragments */
289a747e4fSDavid du Colombier };
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier static Mux p_mux[] =
319a747e4fSDavid du Colombier {
329a747e4fSDavid du Colombier { "icmp", 1, },
339a747e4fSDavid du Colombier { "igmp", 2, },
349a747e4fSDavid du Colombier { "ggp", 3, },
359a747e4fSDavid du Colombier { "ip", 4, },
369a747e4fSDavid du Colombier { "st", 5, },
379a747e4fSDavid du Colombier { "tcp", 6, },
389a747e4fSDavid du Colombier { "ucl", 7, },
399a747e4fSDavid du Colombier { "egp", 8, },
409a747e4fSDavid du Colombier { "igp", 9, },
419a747e4fSDavid du Colombier { "bbn-rcc-mon", 10, },
429a747e4fSDavid du Colombier { "nvp-ii", 11, },
439a747e4fSDavid du Colombier { "pup", 12, },
449a747e4fSDavid du Colombier { "argus", 13, },
459a747e4fSDavid du Colombier { "emcon", 14, },
469a747e4fSDavid du Colombier { "xnet", 15, },
479a747e4fSDavid du Colombier { "chaos", 16, },
489a747e4fSDavid du Colombier { "udp", 17, },
499a747e4fSDavid du Colombier { "mux", 18, },
509a747e4fSDavid du Colombier { "dcn-meas", 19, },
519a747e4fSDavid du Colombier { "hmp", 20, },
529a747e4fSDavid du Colombier { "prm", 21, },
539a747e4fSDavid du Colombier { "xns-idp", 22, },
549a747e4fSDavid du Colombier { "trunk-1", 23, },
559a747e4fSDavid du Colombier { "trunk-2", 24, },
569a747e4fSDavid du Colombier { "leaf-1", 25, },
579a747e4fSDavid du Colombier { "leaf-2", 26, },
589a747e4fSDavid du Colombier { "rdp", 27, },
599a747e4fSDavid du Colombier { "irtp", 28, },
609a747e4fSDavid du Colombier { "iso-tp4", 29, },
619a747e4fSDavid du Colombier { "netblt", 30, },
629a747e4fSDavid du Colombier { "mfe-nsp", 31, },
639a747e4fSDavid du Colombier { "merit-inp", 32, },
649a747e4fSDavid du Colombier { "sep", 33, },
659a747e4fSDavid du Colombier { "3pc", 34, },
669a747e4fSDavid du Colombier { "idpr", 35, },
679a747e4fSDavid du Colombier { "xtp", 36, },
689a747e4fSDavid du Colombier { "ddp", 37, },
699a747e4fSDavid du Colombier { "idpr-cmtp", 38, },
709a747e4fSDavid du Colombier { "tp++", 39, },
719a747e4fSDavid du Colombier { "il", 40, },
729a747e4fSDavid du Colombier { "sip", 41, },
739a747e4fSDavid du Colombier { "sdrp", 42, },
749a747e4fSDavid du Colombier { "sip-sr", 43, },
759a747e4fSDavid du Colombier { "sip-frag", 44, },
769a747e4fSDavid du Colombier { "idrp", 45, },
779a747e4fSDavid du Colombier { "rsvp", 46, },
789a747e4fSDavid du Colombier { "gre", 47, },
799a747e4fSDavid du Colombier { "mhrp", 48, },
809a747e4fSDavid du Colombier { "bna", 49, },
819a747e4fSDavid du Colombier { "sipp-esp", 50, },
829a747e4fSDavid du Colombier { "sipp-ah", 51, },
839a747e4fSDavid du Colombier { "i-nlsp", 52, },
849a747e4fSDavid du Colombier { "swipe", 53, },
859a747e4fSDavid du Colombier { "nhrp", 54, },
869a747e4fSDavid du Colombier { "any", 61, },
879a747e4fSDavid du Colombier { "cftp", 62, },
889a747e4fSDavid du Colombier { "any", 63, },
899a747e4fSDavid du Colombier { "sat-expak", 64, },
909a747e4fSDavid du Colombier { "kryptolan", 65, },
919a747e4fSDavid du Colombier { "rvd", 66, },
929a747e4fSDavid du Colombier { "ippc", 67, },
939a747e4fSDavid du Colombier { "any", 68, },
949a747e4fSDavid du Colombier { "sat-mon", 69, },
959a747e4fSDavid du Colombier { "visa", 70, },
969a747e4fSDavid du Colombier { "ipcv", 71, },
979a747e4fSDavid du Colombier { "cpnx", 72, },
989a747e4fSDavid du Colombier { "cphb", 73, },
999a747e4fSDavid du Colombier { "wsn", 74, },
1009a747e4fSDavid du Colombier { "pvp", 75, },
1019a747e4fSDavid du Colombier { "br-sat-mon", 76, },
1029a747e4fSDavid du Colombier { "sun-nd", 77, },
1039a747e4fSDavid du Colombier { "wb-mon", 78, },
1049a747e4fSDavid du Colombier { "wb-expak", 79, },
1059a747e4fSDavid du Colombier { "iso-ip", 80, },
1069a747e4fSDavid du Colombier { "vmtp", 81, },
1079a747e4fSDavid du Colombier { "secure-vmtp", 82, },
1089a747e4fSDavid du Colombier { "vines", 83, },
1099a747e4fSDavid du Colombier { "ttp", 84, },
1109a747e4fSDavid du Colombier { "nsfnet-igp", 85, },
1119a747e4fSDavid du Colombier { "dgp", 86, },
1129a747e4fSDavid du Colombier { "tcf", 87, },
1139a747e4fSDavid du Colombier { "igrp", 88, },
1149a747e4fSDavid du Colombier { "ospf", 89, },
1159a747e4fSDavid du Colombier { "sprite-rpc", 90, },
1169a747e4fSDavid du Colombier { "larp", 91, },
1179a747e4fSDavid du Colombier { "mtp", 92, },
1189a747e4fSDavid du Colombier { "ax.25", 93, },
1199a747e4fSDavid du Colombier { "ipip", 94, },
1209a747e4fSDavid du Colombier { "micp", 95, },
1219a747e4fSDavid du Colombier { "scc-sp", 96, },
1229a747e4fSDavid du Colombier { "etherip", 97, },
1239a747e4fSDavid du Colombier { "encap", 98, },
1249a747e4fSDavid du Colombier { "any", 99, },
1259a747e4fSDavid du Colombier { "gmtp", 100, },
1269a747e4fSDavid du Colombier { "rudp", 254, },
1279a747e4fSDavid du Colombier { 0 }
1289a747e4fSDavid du Colombier };
1299a747e4fSDavid du Colombier
1309a747e4fSDavid du Colombier enum
1319a747e4fSDavid du Colombier {
132e6dcbf51SDavid du Colombier Os, /* source */
133e6dcbf51SDavid du Colombier Od, /* destination */
134e6dcbf51SDavid du Colombier Osd, /* source or destination */
135e6dcbf51SDavid du Colombier Ot, /* type */
1369a747e4fSDavid du Colombier };
1379a747e4fSDavid du Colombier
1389a747e4fSDavid du Colombier static Field p_fields[] =
1399a747e4fSDavid du Colombier {
1409a747e4fSDavid du Colombier {"s", Fv4ip, Os, "source address", } ,
1419a747e4fSDavid du Colombier {"d", Fv4ip, Od, "destination address", } ,
1429a747e4fSDavid du Colombier {"a", Fv4ip, Osd, "source|destination address",} ,
143dc5a79c1SDavid du Colombier {"sd", Fv4ip, Osd, "source|destination address",} ,
1449a747e4fSDavid du Colombier {"t", Fnum, Ot, "sub protocol number", } ,
1459a747e4fSDavid du Colombier {0}
1469a747e4fSDavid du Colombier };
1479a747e4fSDavid du Colombier
1489a747e4fSDavid du Colombier static void
p_compile(Filter * f)1499a747e4fSDavid du Colombier p_compile(Filter *f)
1509a747e4fSDavid du Colombier {
1519a747e4fSDavid du Colombier Mux *m;
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier if(f->op == '='){
1549a747e4fSDavid du Colombier compile_cmp(ip.name, f, p_fields);
1559a747e4fSDavid du Colombier return;
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier for(m = p_mux; m->name != nil; m++)
1589a747e4fSDavid du Colombier if(strcmp(f->s, m->name) == 0){
1599a747e4fSDavid du Colombier f->pr = m->pr;
1609a747e4fSDavid du Colombier f->ulv = m->val;
1619a747e4fSDavid du Colombier f->subop = Ot;
1629a747e4fSDavid du Colombier return;
1639a747e4fSDavid du Colombier }
1649a747e4fSDavid du Colombier sysfatal("unknown ip field or protocol: %s", f->s);
1659a747e4fSDavid du Colombier }
1669a747e4fSDavid du Colombier
1679a747e4fSDavid du Colombier static int
p_filter(Filter * f,Msg * m)1689a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m)
1699a747e4fSDavid du Colombier {
1709a747e4fSDavid du Colombier Hdr *h;
1719a747e4fSDavid du Colombier
1729a747e4fSDavid du Colombier if(m->pe - m->ps < IPHDR)
1739a747e4fSDavid du Colombier return 0;
1749a747e4fSDavid du Colombier
1759a747e4fSDavid du Colombier h = (Hdr*)m->ps;
176e6dcbf51SDavid du Colombier m->ps += (h->vihl & 0xf) << 2;
1779a747e4fSDavid du Colombier
1789a747e4fSDavid du Colombier switch(f->subop){
1799a747e4fSDavid du Colombier case Os:
1809a747e4fSDavid du Colombier return NetL(h->src) == f->ulv;
1819a747e4fSDavid du Colombier case Od:
1829a747e4fSDavid du Colombier return NetL(h->dst) == f->ulv;
1839a747e4fSDavid du Colombier case Osd:
1849a747e4fSDavid du Colombier return NetL(h->src) == f->ulv || NetL(h->dst) == f->ulv;
1859a747e4fSDavid du Colombier case Ot:
1869a747e4fSDavid du Colombier return h->proto == f->ulv;
1879a747e4fSDavid du Colombier }
1889a747e4fSDavid du Colombier return 0;
1899a747e4fSDavid du Colombier }
1909a747e4fSDavid du Colombier
1919a747e4fSDavid du Colombier static int
p_seprint(Msg * m)1929a747e4fSDavid du Colombier p_seprint(Msg *m)
1939a747e4fSDavid du Colombier {
194*853458f3SDavid du Colombier int f, len, hl;
195*853458f3SDavid du Colombier uchar *p;
1969a747e4fSDavid du Colombier Hdr *h;
1979a747e4fSDavid du Colombier
1989a747e4fSDavid du Colombier if(m->pe - m->ps < IPHDR)
1999a747e4fSDavid du Colombier return -1;
2009a747e4fSDavid du Colombier h = (Hdr*)m->ps;
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier /* next protocol, just dump unless this is the first fragment */
2039a747e4fSDavid du Colombier m->pr = &dump;
2049a747e4fSDavid du Colombier f = NetS(h->frag);
2059a747e4fSDavid du Colombier if((f & ~(IP_DF|IP_MF)) == 0)
2069a747e4fSDavid du Colombier demux(p_mux, h->proto, h->proto, m, &dump);
2079a747e4fSDavid du Colombier
2089a747e4fSDavid du Colombier /* truncate the message if there's extra */
2099a747e4fSDavid du Colombier len = NetS(h->length);
2109a747e4fSDavid du Colombier if(len < m->pe - m->ps)
2119a747e4fSDavid du Colombier m->pe = m->ps + len;
2129a747e4fSDavid du Colombier
2139a747e4fSDavid du Colombier /* next header */
214*853458f3SDavid du Colombier hl = (h->vihl &0xf) << 2;
2159a747e4fSDavid du Colombier
216*853458f3SDavid du Colombier m->p = seprint(m->p, m->e, "s=%V d=%V id=%4.4ux frag=%4.4ux ttl=%3d pr=%d ln=%d hl=%d",
217e6dcbf51SDavid du Colombier h->src, h->dst, NetS(h->id), NetS(h->frag), h->ttl, h->proto,
218*853458f3SDavid du Colombier NetS(h->length),
219*853458f3SDavid du Colombier (h->vihl & 0xf) << 2);
220*853458f3SDavid du Colombier
221*853458f3SDavid du Colombier m->ps += hl;
222*853458f3SDavid du Colombier p = (uchar *)(h + 1);
223*853458f3SDavid du Colombier if(p < m->ps){
224*853458f3SDavid du Colombier m->p = seprint(m->p, m->e, " opts=(");
225*853458f3SDavid du Colombier while(p < m->ps)
226*853458f3SDavid du Colombier m->p = seprint(m->p, m->e, "%.2ux", *p++);
227*853458f3SDavid du Colombier m->p = seprint(m->p, m->e, ")");
228*853458f3SDavid du Colombier }
229*853458f3SDavid du Colombier
2309a747e4fSDavid du Colombier return 0;
2319a747e4fSDavid du Colombier }
2329a747e4fSDavid du Colombier
2339a747e4fSDavid du Colombier Proto ip =
2349a747e4fSDavid du Colombier {
2359a747e4fSDavid du Colombier "ip",
2369a747e4fSDavid du Colombier p_compile,
2379a747e4fSDavid du Colombier p_filter,
2389a747e4fSDavid du Colombier p_seprint,
2399a747e4fSDavid du Colombier p_mux,
240ed397113SDavid du Colombier "%lud",
2419a747e4fSDavid du Colombier p_fields,
2423ff48bf5SDavid du Colombier defaultframer,
2439a747e4fSDavid du Colombier };
244