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 vcf[4]; /* Version and header length */
119a747e4fSDavid du Colombier uchar length[2]; /* packet length */
129a747e4fSDavid du Colombier uchar proto; /* Protocol */
139a747e4fSDavid du Colombier uchar ttl; /* Time to live */
149a747e4fSDavid du Colombier uchar src[IPaddrlen]; /* IP source */
159a747e4fSDavid du Colombier uchar dst[IPaddrlen]; /* IP destination */
169a747e4fSDavid du Colombier };
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier enum
199a747e4fSDavid du Colombier {
209a747e4fSDavid du Colombier IP6HDR = 40, /* sizeof(Iphdr) */
219a747e4fSDavid du Colombier IP_VER = 0x60, /* Using IP version 4 */
229a747e4fSDavid du Colombier HBH_HDR = 0,
239a747e4fSDavid du Colombier ROUT_HDR = 43,
249a747e4fSDavid du Colombier FRAG_HDR = 44,
259a747e4fSDavid du Colombier FRAG_HSZ = 8, /* in bytes */
269a747e4fSDavid du Colombier DEST_HDR = 60,
279a747e4fSDavid du Colombier };
289a747e4fSDavid du Colombier
299a747e4fSDavid du Colombier static Mux p_mux[] =
309a747e4fSDavid du Colombier {
319a747e4fSDavid du Colombier { "igmp", 2, },
329a747e4fSDavid du Colombier { "ggp", 3, },
339a747e4fSDavid du Colombier { "ip", 4, },
349a747e4fSDavid du Colombier { "st", 5, },
359a747e4fSDavid du Colombier { "tcp", 6, },
369a747e4fSDavid du Colombier { "ucl", 7, },
379a747e4fSDavid du Colombier { "egp", 8, },
389a747e4fSDavid du Colombier { "igp", 9, },
399a747e4fSDavid du Colombier { "bbn-rcc-mon", 10, },
409a747e4fSDavid du Colombier { "nvp-ii", 11, },
419a747e4fSDavid du Colombier { "pup", 12, },
429a747e4fSDavid du Colombier { "argus", 13, },
439a747e4fSDavid du Colombier { "emcon", 14, },
449a747e4fSDavid du Colombier { "xnet", 15, },
459a747e4fSDavid du Colombier { "chaos", 16, },
469a747e4fSDavid du Colombier { "udp", 17, },
479a747e4fSDavid du Colombier { "mux", 18, },
489a747e4fSDavid du Colombier { "dcn-meas", 19, },
499a747e4fSDavid du Colombier { "hmp", 20, },
509a747e4fSDavid du Colombier { "prm", 21, },
519a747e4fSDavid du Colombier { "xns-idp", 22, },
529a747e4fSDavid du Colombier { "trunk-1", 23, },
539a747e4fSDavid du Colombier { "trunk-2", 24, },
549a747e4fSDavid du Colombier { "leaf-1", 25, },
559a747e4fSDavid du Colombier { "leaf-2", 26, },
569a747e4fSDavid du Colombier { "rdp", 27, },
579a747e4fSDavid du Colombier { "irtp", 28, },
589a747e4fSDavid du Colombier { "iso-tp4", 29, },
599a747e4fSDavid du Colombier { "netblt", 30, },
609a747e4fSDavid du Colombier { "mfe-nsp", 31, },
619a747e4fSDavid du Colombier { "merit-inp", 32, },
629a747e4fSDavid du Colombier { "sep", 33, },
639a747e4fSDavid du Colombier { "3pc", 34, },
649a747e4fSDavid du Colombier { "idpr", 35, },
659a747e4fSDavid du Colombier { "xtp", 36, },
669a747e4fSDavid du Colombier { "ddp", 37, },
679a747e4fSDavid du Colombier { "idpr-cmtp", 38, },
689a747e4fSDavid du Colombier { "tp++", 39, },
699a747e4fSDavid du Colombier { "il", 40, },
709a747e4fSDavid du Colombier { "sip", 41, },
719a747e4fSDavid du Colombier { "sdrp", 42, },
729a747e4fSDavid du Colombier { "idrp", 45, },
739a747e4fSDavid du Colombier { "rsvp", 46, },
749a747e4fSDavid du Colombier { "gre", 47, },
759a747e4fSDavid du Colombier { "mhrp", 48, },
769a747e4fSDavid du Colombier { "bna", 49, },
779a747e4fSDavid du Colombier { "sipp-esp", 50, },
789a747e4fSDavid du Colombier { "sipp-ah", 51, },
799a747e4fSDavid du Colombier { "i-nlsp", 52, },
809a747e4fSDavid du Colombier { "swipe", 53, },
819a747e4fSDavid du Colombier { "nhrp", 54, },
829a747e4fSDavid du Colombier { "icmp6", 58, },
839a747e4fSDavid du Colombier { "any", 61, },
849a747e4fSDavid du Colombier { "cftp", 62, },
859a747e4fSDavid du Colombier { "any", 63, },
869a747e4fSDavid du Colombier { "sat-expak", 64, },
879a747e4fSDavid du Colombier { "kryptolan", 65, },
889a747e4fSDavid du Colombier { "rvd", 66, },
899a747e4fSDavid du Colombier { "ippc", 67, },
909a747e4fSDavid du Colombier { "any", 68, },
919a747e4fSDavid du Colombier { "sat-mon", 69, },
929a747e4fSDavid du Colombier { "visa", 70, },
939a747e4fSDavid du Colombier { "ipcv", 71, },
949a747e4fSDavid du Colombier { "cpnx", 72, },
959a747e4fSDavid du Colombier { "cphb", 73, },
969a747e4fSDavid du Colombier { "wsn", 74, },
979a747e4fSDavid du Colombier { "pvp", 75, },
989a747e4fSDavid du Colombier { "br-sat-mon", 76, },
999a747e4fSDavid du Colombier { "sun-nd", 77, },
1009a747e4fSDavid du Colombier { "wb-mon", 78, },
1019a747e4fSDavid du Colombier { "wb-expak", 79, },
1029a747e4fSDavid du Colombier { "iso-ip", 80, },
1039a747e4fSDavid du Colombier { "vmtp", 81, },
1049a747e4fSDavid du Colombier { "secure-vmtp", 82, },
1059a747e4fSDavid du Colombier { "vines", 83, },
1069a747e4fSDavid du Colombier { "ttp", 84, },
1079a747e4fSDavid du Colombier { "nsfnet-igp", 85, },
1089a747e4fSDavid du Colombier { "dgp", 86, },
1099a747e4fSDavid du Colombier { "tcf", 87, },
1109a747e4fSDavid du Colombier { "igrp", 88, },
1119a747e4fSDavid du Colombier { "ospf", 89, },
1129a747e4fSDavid du Colombier { "sprite-rpc", 90, },
1139a747e4fSDavid du Colombier { "larp", 91, },
1149a747e4fSDavid du Colombier { "mtp", 92, },
1159a747e4fSDavid du Colombier { "ax.25", 93, },
1169a747e4fSDavid du Colombier { "ipip", 94, },
1179a747e4fSDavid du Colombier { "micp", 95, },
1189a747e4fSDavid du Colombier { "scc-sp", 96, },
1199a747e4fSDavid du Colombier { "etherip", 97, },
1209a747e4fSDavid du Colombier { "encap", 98, },
1219a747e4fSDavid du Colombier { "any", 99, },
1229a747e4fSDavid du Colombier { "gmtp", 100, },
1239a747e4fSDavid du Colombier { "rudp", 254, },
1249a747e4fSDavid du Colombier { 0 }
1259a747e4fSDavid du Colombier };
1269a747e4fSDavid du Colombier
1279a747e4fSDavid du Colombier enum
1289a747e4fSDavid du Colombier {
129*e6dcbf51SDavid du Colombier Os, /* source */
130*e6dcbf51SDavid du Colombier Od, /* destination */
131*e6dcbf51SDavid du Colombier Osd, /* source or destination */
132*e6dcbf51SDavid du Colombier Ot, /* type */
1339a747e4fSDavid du Colombier };
1349a747e4fSDavid du Colombier
1359a747e4fSDavid du Colombier static Field p_fields[] =
1369a747e4fSDavid du Colombier {
1379a747e4fSDavid du Colombier {"s", Fv6ip, Os, "source address", } ,
1389a747e4fSDavid du Colombier {"d", Fv6ip, Od, "destination address", } ,
1399a747e4fSDavid du Colombier {"a", Fv6ip, Osd, "source|destination address",} ,
1409a747e4fSDavid du Colombier {"t", Fnum, Ot, "sub protocol number", } ,
1419a747e4fSDavid du Colombier {0}
1429a747e4fSDavid du Colombier };
1439a747e4fSDavid du Colombier
1449a747e4fSDavid du Colombier static void
p_compile(Filter * f)1459a747e4fSDavid du Colombier p_compile(Filter *f)
1469a747e4fSDavid du Colombier {
1479a747e4fSDavid du Colombier Mux *m;
1489a747e4fSDavid du Colombier
1499a747e4fSDavid du Colombier if(f->op == '='){
1509a747e4fSDavid du Colombier compile_cmp(ip6.name, f, p_fields);
1519a747e4fSDavid du Colombier return;
1529a747e4fSDavid du Colombier }
1539a747e4fSDavid du Colombier for(m = p_mux; m->name != nil; m++)
1549a747e4fSDavid du Colombier if(strcmp(f->s, m->name) == 0){
1559a747e4fSDavid du Colombier f->pr = m->pr;
1569a747e4fSDavid du Colombier f->ulv = m->val;
1579a747e4fSDavid du Colombier f->subop = Ot;
1589a747e4fSDavid du Colombier return;
1599a747e4fSDavid du Colombier }
1609a747e4fSDavid du Colombier sysfatal("unknown ip6 field or protocol: %s", f->s);
1619a747e4fSDavid du Colombier }
1629a747e4fSDavid du Colombier
1639a747e4fSDavid du Colombier static int
v6hdrlen(Hdr * h)1649a747e4fSDavid du Colombier v6hdrlen(Hdr *h)
1659a747e4fSDavid du Colombier {
1669a747e4fSDavid du Colombier int plen, len = IP6HDR;
1679a747e4fSDavid du Colombier int pktlen = IP6HDR + NetS(h->length);
1689a747e4fSDavid du Colombier uchar nexthdr = h->proto;
1699a747e4fSDavid du Colombier uchar *pkt = (uchar*) h;
1709a747e4fSDavid du Colombier
1719a747e4fSDavid du Colombier pkt += len;
1729a747e4fSDavid du Colombier plen = len;
1739a747e4fSDavid du Colombier
174*e6dcbf51SDavid du Colombier while (nexthdr == HBH_HDR || nexthdr == ROUT_HDR ||
175*e6dcbf51SDavid du Colombier nexthdr == FRAG_HDR || nexthdr == DEST_HDR) {
1769a747e4fSDavid du Colombier if (nexthdr == FRAG_HDR)
1779a747e4fSDavid du Colombier len = FRAG_HSZ;
1789a747e4fSDavid du Colombier else
179*e6dcbf51SDavid du Colombier len = ((int)*(pkt+1) + 1) * 8;
1809a747e4fSDavid du Colombier
1819a747e4fSDavid du Colombier if (plen + len > pktlen)
1829a747e4fSDavid du Colombier return -1;
1839a747e4fSDavid du Colombier
1849a747e4fSDavid du Colombier pkt += len;
1859a747e4fSDavid du Colombier nexthdr = *pkt;
1869a747e4fSDavid du Colombier plen += len;
1879a747e4fSDavid du Colombier }
1889a747e4fSDavid du Colombier return plen;
1899a747e4fSDavid du Colombier }
1909a747e4fSDavid du Colombier
1919a747e4fSDavid du Colombier static int
p_filter(Filter * f,Msg * m)1929a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m)
1939a747e4fSDavid du Colombier {
1949a747e4fSDavid du Colombier Hdr *h;
1959a747e4fSDavid du Colombier int hlen;
1969a747e4fSDavid du Colombier
1979a747e4fSDavid du Colombier if(m->pe - m->ps < IP6HDR)
1989a747e4fSDavid du Colombier return 0;
1999a747e4fSDavid du Colombier
2009a747e4fSDavid du Colombier h = (Hdr*)m->ps;
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier if ((hlen = v6hdrlen(h)) < 0)
2039a747e4fSDavid du Colombier return 0;
2049a747e4fSDavid du Colombier else
2059a747e4fSDavid du Colombier m->ps += hlen;
2069a747e4fSDavid du Colombier switch(f->subop){
2079a747e4fSDavid du Colombier case Os:
208*e6dcbf51SDavid du Colombier return memcmp(h->src, f->a, IPaddrlen) == 0;
2099a747e4fSDavid du Colombier case Od:
210*e6dcbf51SDavid du Colombier return memcmp(h->dst, f->a, IPaddrlen) == 0;
2119a747e4fSDavid du Colombier case Osd:
212*e6dcbf51SDavid du Colombier return memcmp(h->src, f->a, IPaddrlen) == 0 ||
213*e6dcbf51SDavid du Colombier memcmp(h->dst, f->a, IPaddrlen) == 0;
2149a747e4fSDavid du Colombier case Ot:
2159a747e4fSDavid du Colombier return h->proto == f->ulv;
2169a747e4fSDavid du Colombier }
2179a747e4fSDavid du Colombier return 0;
2189a747e4fSDavid du Colombier }
2199a747e4fSDavid du Colombier
2209a747e4fSDavid du Colombier static int
v6hdr_seprint(Msg * m)2219a747e4fSDavid du Colombier v6hdr_seprint(Msg *m)
2229a747e4fSDavid du Colombier {
223*e6dcbf51SDavid du Colombier int plen, len = IP6HDR;
2249a747e4fSDavid du Colombier uchar *pkt = m->ps;
2259a747e4fSDavid du Colombier Hdr *h = (Hdr *)pkt;
2269a747e4fSDavid du Colombier int pktlen = IP6HDR + NetS(h->length);
2279a747e4fSDavid du Colombier uchar nexthdr = h->proto;
2289a747e4fSDavid du Colombier
2299a747e4fSDavid du Colombier pkt += len;
2309a747e4fSDavid du Colombier plen = len;
2319a747e4fSDavid du Colombier
232*e6dcbf51SDavid du Colombier while (nexthdr == HBH_HDR || nexthdr == ROUT_HDR ||
233*e6dcbf51SDavid du Colombier nexthdr == FRAG_HDR || nexthdr == DEST_HDR) {
2349a747e4fSDavid du Colombier switch (nexthdr) {
2359a747e4fSDavid du Colombier case FRAG_HDR:
236*e6dcbf51SDavid du Colombier m->p = seprint(m->p, m->e, "\n xthdr=frag id=%d "
237*e6dcbf51SDavid du Colombier "offset=%d pr=%d more=%d res1=%d res2=%d",
238*e6dcbf51SDavid du Colombier NetL(pkt+4), NetS(pkt+2) & ~7, (int)*pkt,
239*e6dcbf51SDavid du Colombier (int)(*(pkt+3) & 0x1), (int)*(pkt+1),
240*e6dcbf51SDavid du Colombier (int)(*(pkt+3) & 0x6));
2419a747e4fSDavid du Colombier len = FRAG_HSZ;
2429a747e4fSDavid du Colombier break;
2439a747e4fSDavid du Colombier
2449a747e4fSDavid du Colombier case HBH_HDR:
2459a747e4fSDavid du Colombier case ROUT_HDR:
2469a747e4fSDavid du Colombier case DEST_HDR:
247*e6dcbf51SDavid du Colombier len = ((int)*(pkt+1) + 1) * 8;
2489a747e4fSDavid du Colombier break;
2499a747e4fSDavid du Colombier }
2509a747e4fSDavid du Colombier
2519a747e4fSDavid du Colombier if (plen + len > pktlen) {
2529a747e4fSDavid du Colombier m->p = seprint(m->p, m->e, "bad pkt");
2539a747e4fSDavid du Colombier m->pr = &dump;
2549a747e4fSDavid du Colombier return -1;
2559a747e4fSDavid du Colombier }
2569a747e4fSDavid du Colombier plen += len;
2579a747e4fSDavid du Colombier pkt += len;
2589a747e4fSDavid du Colombier nexthdr = *pkt;
2599a747e4fSDavid du Colombier }
2609a747e4fSDavid du Colombier
2619a747e4fSDavid du Colombier m->ps = pkt;
2629a747e4fSDavid du Colombier return 1;
2639a747e4fSDavid du Colombier }
2649a747e4fSDavid du Colombier
2659a747e4fSDavid du Colombier static int
p_seprint(Msg * m)2669a747e4fSDavid du Colombier p_seprint(Msg *m)
2679a747e4fSDavid du Colombier {
2689a747e4fSDavid du Colombier int len;
269*e6dcbf51SDavid du Colombier Hdr *h;
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier if(m->pe - m->ps < IP6HDR)
2729a747e4fSDavid du Colombier return -1;
2739a747e4fSDavid du Colombier h = (Hdr*)m->ps;
2749a747e4fSDavid du Colombier
2759a747e4fSDavid du Colombier demux(p_mux, h->proto, h->proto, m, &dump);
2769a747e4fSDavid du Colombier
2779a747e4fSDavid du Colombier /* truncate the message if there's extra */
2789a747e4fSDavid du Colombier len = NetS(h->length) + IP6HDR;
2799a747e4fSDavid du Colombier if(len < m->pe - m->ps)
2809a747e4fSDavid du Colombier m->pe = m->ps + len;
2819a747e4fSDavid du Colombier
2829a747e4fSDavid du Colombier m->p = seprint(m->p, m->e, "s=%I d=%I ttl=%3d pr=%d ln=%d",
283*e6dcbf51SDavid du Colombier h->src, h->dst, h->ttl, h->proto, NetS(h->length));
2849a747e4fSDavid du Colombier v6hdr_seprint(m);
2859a747e4fSDavid du Colombier return 0;
2869a747e4fSDavid du Colombier }
2879a747e4fSDavid du Colombier
2889a747e4fSDavid du Colombier Proto ip6 =
2899a747e4fSDavid du Colombier {
2909a747e4fSDavid du Colombier "ip6",
2919a747e4fSDavid du Colombier p_compile,
2929a747e4fSDavid du Colombier p_filter,
2939a747e4fSDavid du Colombier p_seprint,
2949a747e4fSDavid du Colombier p_mux,
295ed397113SDavid du Colombier "%lud",
2969a747e4fSDavid du Colombier p_fields,
2973ff48bf5SDavid du Colombier defaultframer,
2989a747e4fSDavid du Colombier };
299