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 };