plan9port

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

ip6.c (5377B)


      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	vcf[4];			/* Version and header length */
     11 	uchar	length[2];		/* packet length */
     12 	uchar	proto;			/* Protocol */
     13 	uchar	ttl;			/* Time to live */
     14 	uchar	src[IPaddrlen];		/* IP source */
     15 	uchar	dst[IPaddrlen];		/* IP destination */
     16 };
     17 
     18 enum
     19 {
     20 	IP6HDR		= 40,		/* sizeof(Iphdr) */
     21 	IP_VER		= 0x60,		/* Using IP version 4 */
     22 	HBH_HDR		= 0,
     23 	ROUT_HDR	= 43,
     24 	FRAG_HDR	= 44,
     25 	FRAG_HSZ	= 8, 		/* in bytes */
     26 	DEST_HDR	= 60
     27 };
     28 
     29 static Mux p_mux[] =
     30 {
     31 	{ "igmp", 2, },
     32 	{ "ggp", 3, },
     33 	{ "ip", 4, },
     34 	{ "st", 5, },
     35 	{ "tcp", 6, },
     36 	{ "ucl", 7, },
     37 	{ "egp", 8, },
     38 	{ "igp", 9, },
     39 	{ "bbn-rcc-mon", 10, },
     40 	{ "nvp-ii", 11, },
     41 	{ "pup", 12, },
     42 	{ "argus", 13, },
     43 	{ "emcon", 14, },
     44 	{ "xnet", 15, },
     45 	{ "chaos", 16, },
     46 	{ "udp", 17, },
     47 	{ "mux", 18, },
     48 	{ "dcn-meas", 19, },
     49 	{ "hmp", 20, },
     50 	{ "prm", 21, },
     51 	{ "xns-idp", 22, },
     52 	{ "trunk-1", 23, },
     53 	{ "trunk-2", 24, },
     54 	{ "leaf-1", 25, },
     55 	{ "leaf-2", 26, },
     56 	{ "rdp", 27, },
     57 	{ "irtp", 28, },
     58 	{ "iso-tp4", 29, },
     59 	{ "netblt", 30, },
     60 	{ "mfe-nsp", 31, },
     61 	{ "merit-inp", 32, },
     62 	{ "sep", 33, },
     63 	{ "3pc", 34, },
     64 	{ "idpr", 35, },
     65 	{ "xtp", 36, },
     66 	{ "ddp", 37, },
     67 	{ "idpr-cmtp", 38, },
     68 	{ "tp++", 39, },
     69 	{ "il", 40, },
     70 	{ "sip", 41, },
     71 	{ "sdrp", 42, },
     72 	{ "idrp", 45, },
     73 	{ "rsvp", 46, },
     74 	{ "gre", 47, },
     75 	{ "mhrp", 48, },
     76 	{ "bna", 49, },
     77 	{ "sipp-esp", 50, },
     78 	{ "sipp-ah", 51, },
     79 	{ "i-nlsp", 52, },
     80 	{ "swipe", 53, },
     81 	{ "nhrp", 54, },
     82 	{ "icmp6", 58, },
     83 	{ "any", 61, },
     84 	{ "cftp", 62, },
     85 	{ "any", 63, },
     86 	{ "sat-expak", 64, },
     87 	{ "kryptolan", 65, },
     88 	{ "rvd", 66, },
     89 	{ "ippc", 67, },
     90 	{ "any", 68, },
     91 	{ "sat-mon", 69, },
     92 	{ "visa", 70, },
     93 	{ "ipcv", 71, },
     94 	{ "cpnx", 72, },
     95 	{ "cphb", 73, },
     96 	{ "wsn", 74, },
     97 	{ "pvp", 75, },
     98 	{ "br-sat-mon", 76, },
     99 	{ "sun-nd", 77, },
    100 	{ "wb-mon", 78, },
    101 	{ "wb-expak", 79, },
    102 	{ "iso-ip", 80, },
    103 	{ "vmtp", 81, },
    104 	{ "secure-vmtp", 82, },
    105 	{ "vines", 83, },
    106 	{ "ttp", 84, },
    107 	{ "nsfnet-igp", 85, },
    108 	{ "dgp", 86, },
    109 	{ "tcf", 87, },
    110 	{ "igrp", 88, },
    111 	{ "ospf", 89, },
    112 	{ "sprite-rpc", 90, },
    113 	{ "larp", 91, },
    114 	{ "mtp", 92, },
    115 	{ "ax.25", 93, },
    116 	{ "ipip", 94, },
    117 	{ "micp", 95, },
    118 	{ "scc-sp", 96, },
    119 	{ "etherip", 97, },
    120 	{ "encap", 98, },
    121 	{ "any", 99, },
    122 	{ "gmtp", 100, },
    123 	{ "rudp", 254, },
    124 	{ 0 }
    125 };
    126 
    127 enum
    128 {
    129 	Os,	/* source */
    130 	Od,	/* destination */
    131 	Osd,	/* source or destination */
    132 	Ot,	/* type */
    133 };
    134 
    135 static Field p_fields[] =
    136 {
    137 	{"s",	Fv6ip,	Os,	"source address",	} ,
    138 	{"d",	Fv6ip,	Od,	"destination address",	} ,
    139 	{"a",	Fv6ip,	Osd,	"source|destination address",} ,
    140 	{"t",	Fnum,	Ot,	"sub protocol number",	} ,
    141 	{0}
    142 };
    143 
    144 static void
    145 p_compile(Filter *f)
    146 {
    147 	Mux *m;
    148 
    149 	if(f->op == '='){
    150 		compile_cmp(ip6.name, f, p_fields);
    151 		return;
    152 	}
    153 	for(m = p_mux; m->name != nil; m++)
    154 		if(strcmp(f->s, m->name) == 0){
    155 			f->pr = m->pr;
    156 			f->ulv = m->val;
    157 			f->subop = Ot;
    158 			return;
    159 		}
    160 	sysfatal("unknown ip6 field or protocol: %s", f->s);
    161 }
    162 
    163 static int
    164 v6hdrlen(Hdr *h)
    165 {
    166 	int plen, len = IP6HDR;
    167 	int pktlen = IP6HDR + NetS(h->length);
    168 	uchar nexthdr = h->proto;
    169 	uchar *pkt = (uchar*) h;
    170 
    171 	pkt += len;
    172 	plen = len;
    173 
    174 	while ( (nexthdr == HBH_HDR) || (nexthdr == ROUT_HDR) ||
    175 		(nexthdr == FRAG_HDR) || (nexthdr == DEST_HDR) ) {
    176 
    177 		if (nexthdr == FRAG_HDR)
    178 			len = FRAG_HSZ;
    179 		else
    180 			len = ( ((int) *(pkt+1)) + 1) * 8;
    181 
    182 		if (plen + len > pktlen)
    183 			return -1;
    184 
    185 		pkt += len;
    186 		nexthdr = *pkt;
    187 		plen += len;
    188 	}
    189 	return plen;
    190 }
    191 
    192 static int
    193 p_filter(Filter *f, Msg *m)
    194 {
    195 	Hdr *h;
    196 	int hlen;
    197 
    198 	if(m->pe - m->ps < IP6HDR)
    199 		return 0;
    200 
    201 	h = (Hdr*)m->ps;
    202 
    203 	if ((hlen = v6hdrlen(h)) < 0)
    204 		return 0;
    205 	else
    206 		m->ps += hlen;
    207 	switch(f->subop){
    208 	case Os:
    209 		return !memcmp(h->src, f->a, IPaddrlen);
    210 	case Od:
    211 		return !memcmp(h->dst, f->a, IPaddrlen);
    212 	case Osd:
    213 		return !memcmp(h->src, f->a, IPaddrlen) || !memcmp(h->dst, f->a, IPaddrlen);
    214 	case Ot:
    215 		return h->proto == f->ulv;
    216 	}
    217 	return 0;
    218 }
    219 
    220 static int
    221 v6hdr_seprint(Msg *m)
    222 {
    223 	int len = IP6HDR;
    224 	uchar *pkt = m->ps;
    225 	Hdr *h = (Hdr *) pkt;
    226 	int pktlen = IP6HDR + NetS(h->length);
    227 	uchar nexthdr = h->proto;
    228 	int plen;
    229 
    230 	pkt += len;
    231 	plen = len;
    232 
    233 	while ( (nexthdr == HBH_HDR) || (nexthdr == ROUT_HDR) ||
    234 		(nexthdr == FRAG_HDR) || (nexthdr == DEST_HDR) ) {
    235 
    236 		switch (nexthdr) {
    237 		case FRAG_HDR:
    238 			m->p = seprint(m->p, m->e, "\n	  xthdr=frag id=%d offset=%d pr=%d more=%d res1=%d res2=%d",
    239 					NetL(pkt+4),
    240 					NetS(pkt+2) & ~7,
    241 					(int) (*pkt),
    242 					(int) (*(pkt+3) & 0x1),
    243 					(int) *(pkt+1),
    244 					(int) (*(pkt+3) & 0x6)
    245 				);
    246 			len = FRAG_HSZ;
    247 			break;
    248 
    249 		case HBH_HDR:
    250 		case ROUT_HDR:
    251 		case DEST_HDR:
    252 			len = ( ((int) *(pkt+1)) + 1) * 8;
    253 			break;
    254 		}
    255 
    256 		if (plen + len > pktlen) {
    257 			m->p = seprint(m->p, m->e, "bad pkt");
    258 			m->pr = &dump;
    259 			return -1;
    260 		}
    261 		plen += len;
    262 		pkt += len;
    263 		nexthdr = *pkt;
    264 	}
    265 
    266 	m->ps = pkt;
    267 	return 1;
    268 
    269 }
    270 
    271 static int
    272 p_seprint(Msg *m)
    273 {
    274 	Hdr *h;
    275 	int len;
    276 
    277 	if(m->pe - m->ps < IP6HDR)
    278 		return -1;
    279 	h = (Hdr*)m->ps;
    280 
    281 	demux(p_mux, h->proto, h->proto, m, &dump);
    282 
    283 	/* truncate the message if there's extra */
    284 	len = NetS(h->length) + IP6HDR;
    285 	if(len < m->pe - m->ps)
    286 		m->pe = m->ps + len;
    287 
    288 	m->p = seprint(m->p, m->e, "s=%I d=%I ttl=%3d pr=%d ln=%d",
    289 			h->src, h->dst,
    290 			h->ttl,
    291 			h->proto,
    292 			NetS(h->length)
    293 			);
    294 
    295 	v6hdr_seprint(m);
    296 
    297 	return 0;
    298 }
    299 
    300 Proto ip6 =
    301 {
    302 	"ip6",
    303 	p_compile,
    304 	p_filter,
    305 	p_seprint,
    306 	p_mux,
    307 	"%lud",
    308 	p_fields,
    309 	defaultframer
    310 };