From 0130c7b34e9e4e831c2794f00a0d017040a967a9 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 8 Feb 2017 15:49:03 +0100 Subject: prog, sys: add icmpv6 packet descriptions and checksums Also generalize checksums into the two kinds: inet and pseudo. Inet checksums is just the Internet checksum of a packet. Pseudo checksum is the Internet checksum of a packet with a pseudo header. --- prog/checksum.go | 146 ++++++++++++++++++++++------------------- prog/checksum_test.go | 17 +++-- sys/decl.go | 7 +- sys/socket.txt | 8 +-- sys/test.txt | 17 ++++- sys/vnet.txt | 174 ++++++++++++++++++++++++++++++++++++++++++------- sys/vnet_amd64.const | 28 ++++++++ sys/vnet_arm64.const | 28 ++++++++ sys/vnet_ppc64le.const | 28 ++++++++ sysgen/sysgen.go | 30 ++++++--- 10 files changed, 372 insertions(+), 111 deletions(-) diff --git a/prog/checksum.go b/prog/checksum.go index 03eb81f7b..8ee00bc24 100644 --- a/prog/checksum.go +++ b/prog/checksum.go @@ -184,28 +184,7 @@ func composePseudoHeaderIPv6(tcpPacket, srcAddr, dstAddr *Arg, protocol uint8, p return header } -func findCsumFieldUDP(udpPacket *Arg) *Arg { - csumField := getFieldByName(udpPacket, "csum") - if typ, ok := csumField.Type.(*sys.CsumType); !ok { - panic(fmt.Sprintf("checksum field has bad type %v, arg: %+v", csumField.Type, csumField)) - } else if typ.Kind != sys.CsumUDP { - panic(fmt.Sprintf("checksum field has bad kind %v, arg: %+v", typ.Kind, csumField)) - } - return csumField -} - -func findCsumFieldTCP(tcpPacket *Arg) *Arg { - tcpHeaderField := getFieldByName(tcpPacket, "header") - csumField := getFieldByName(tcpHeaderField, "csum") - if typ, ok := csumField.Type.(*sys.CsumType); !ok { - panic(fmt.Sprintf("checksum field has bad type %v, arg: %+v", csumField.Type, csumField)) - } else if typ.Kind != sys.CsumTCP { - panic(fmt.Sprintf("checksum field has bad kind %v, arg: %+v", typ.Kind, csumField)) - } - return csumField -} - -func calcChecksumTCPUDP(packet, csumField *Arg, pseudoHeader []byte, pid int) *Arg { +func calcChecksumPseudo(packet, csumField *Arg, pseudoHeader []byte, pid int) *Arg { var csum IPChecksum csum.Update(pseudoHeader) csum.Update(encodeArg(packet, pid)) @@ -214,32 +193,75 @@ func calcChecksumTCPUDP(packet, csumField *Arg, pseudoHeader []byte, pid int) *A return &newCsumField } +func findCsummedArg(arg *Arg, typ *sys.CsumType, parentsMap map[*Arg]*Arg) *Arg { + if typ.Buf == "parent" { + if csummedArg, ok := parentsMap[arg]; ok { + return csummedArg + } + panic(fmt.Sprintf("parent for %v is not in parents map", typ.Name())) + } else { + for parent := parentsMap[arg]; parent != nil; parent = parentsMap[parent] { + if typ.Buf == parent.Type.Name() { + return parent + } + } + } + panic(fmt.Sprintf("csum field '%v' references non existent field '%v'", typ.FieldName(), typ.Buf)) +} + func calcChecksumsCall(c *Call, pid int) map[*Arg]*Arg { - var csumMap map[*Arg]*Arg - ipv4HeaderParsed := false - ipv6HeaderParsed := false - var ipSrcAddr *Arg - var ipDstAddr *Arg - tcp := false + var inetCsumFields []*Arg + var pseudoCsumFields []*Arg - // Calculate inet checksums. + // Find all csum fields. + foreachArgArray(&c.Args, nil, func(arg, base *Arg, _ *[]*Arg) { + if typ, ok := arg.Type.(*sys.CsumType); ok { + switch typ.Kind { + case sys.CsumInet: + inetCsumFields = append(inetCsumFields, arg) + case sys.CsumPseudo: + pseudoCsumFields = append(pseudoCsumFields, arg) + default: + panic(fmt.Sprintf("unknown csum kind %v\n", typ.Kind)) + } + } + }) + + // Return if no csum fields found. + if len(inetCsumFields) == 0 && len(pseudoCsumFields) == 0 { + return nil + } + + // Build map of each field to its parent struct. + parentsMap := make(map[*Arg]*Arg) foreachArgArray(&c.Args, nil, func(arg, base *Arg, _ *[]*Arg) { if _, ok := arg.Type.(*sys.StructType); ok { for _, field := range arg.Inner { - if typ, ok1 := field.Type.(*sys.CsumType); ok1 { - if typ.Kind == sys.CsumInet { - newCsumField := calcChecksumInet(arg, field, pid) - if csumMap == nil { - csumMap = make(map[*Arg]*Arg) - } - csumMap[field] = newCsumField - } - } + parentsMap[field.InnerArg()] = arg } } }) - // Calculate tcp and udp checksums. + csumMap := make(map[*Arg]*Arg) + + // Calculate inet checksums. + for _, arg := range inetCsumFields { + typ, _ := arg.Type.(*sys.CsumType) + csummedArg := findCsummedArg(arg, typ, parentsMap) + newCsumField := calcChecksumInet(csummedArg, arg, pid) + csumMap[arg] = newCsumField + } + + // No need to continue if there are no pseudo csum fields. + if len(pseudoCsumFields) == 0 { + return csumMap + } + + // Extract ipv4 or ipv6 source and destination addresses. + ipv4HeaderParsed := false + ipv6HeaderParsed := false + var ipSrcAddr *Arg + var ipDstAddr *Arg foreachArgArray(&c.Args, nil, func(arg, base *Arg, _ *[]*Arg) { // syz_csum_* structs are used in tests switch arg.Type.Name() { @@ -249,34 +271,26 @@ func calcChecksumsCall(c *Call, pid int) map[*Arg]*Arg { case "ipv6_packet", "syz_csum_ipv6_header": ipSrcAddr, ipDstAddr = extractHeaderParamsIPv6(arg) ipv6HeaderParsed = true - case "tcp_packet", "syz_csum_tcp_packet": - tcp = true - fallthrough - case "udp_packet", "syz_csum_udp_packet": - if !ipv4HeaderParsed && !ipv6HeaderParsed { - panic(fmt.Sprintf("%s is being parsed before ipv4 or ipv6 header", arg.Type.Name())) - } - var csumField *Arg - var protocol uint8 - if tcp { - csumField = findCsumFieldTCP(arg) - protocol = 6 // IPPROTO_TCP - } else { - csumField = findCsumFieldUDP(arg) - protocol = 17 // IPPROTO_UDP - } - var pseudoHeader []byte - if ipv4HeaderParsed { - pseudoHeader = composePseudoHeaderIPv4(arg, ipSrcAddr, ipDstAddr, protocol, pid) - } else { - pseudoHeader = composePseudoHeaderIPv6(arg, ipSrcAddr, ipDstAddr, protocol, pid) - } - if csumMap == nil { - csumMap = make(map[*Arg]*Arg) - } - newCsumField := calcChecksumTCPUDP(arg, csumField, pseudoHeader, pid) - csumMap[csumField] = newCsumField } }) + if !ipv4HeaderParsed && !ipv6HeaderParsed { + panic("no ipv4 nor ipv6 header found") + } + + // Calculate pseudo checksums. + for _, arg := range pseudoCsumFields { + typ, _ := arg.Type.(*sys.CsumType) + csummedArg := findCsummedArg(arg, typ, parentsMap) + protocol := uint8(typ.Protocol) + var pseudoHeader []byte + if ipv4HeaderParsed { + pseudoHeader = composePseudoHeaderIPv4(csummedArg, ipSrcAddr, ipDstAddr, protocol, pid) + } else { + pseudoHeader = composePseudoHeaderIPv6(csummedArg, ipSrcAddr, ipDstAddr, protocol, pid) + } + newCsumField := calcChecksumPseudo(csummedArg, arg, pseudoHeader, pid) + csumMap[arg] = newCsumField + } + return csumMap } diff --git a/prog/checksum_test.go b/prog/checksum_test.go index cd16bb70b..dfb6e04a5 100644 --- a/prog/checksum_test.go +++ b/prog/checksum_test.go @@ -79,6 +79,10 @@ func TestChecksumIP(t *testing.T) { "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x11\x00\x00\xab\xcd", 0x541d, }, + { + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x3a\x00\x00\xab\xcd", + 0x53f4, + }, } for _, test := range tests { @@ -148,24 +152,29 @@ func TestChecksumCalc(t *testing.T) { }, { "syz_test$csum_ipv4_tcp(&(0x7f0000000000)={{0x0, 0x1234, 0x5678}, {{0x0}, \"abcd\"}})", - sys.CsumTCP, + sys.CsumPseudo, 0xeb7b, }, { "syz_test$csum_ipv6_tcp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {{0x0}, \"abcd\"}})", - sys.CsumTCP, + sys.CsumPseudo, 0x5428, }, { "syz_test$csum_ipv4_udp(&(0x7f0000000000)={{0x0, 0x1234, 0x5678}, {0x0, \"abcd\"}})", - sys.CsumUDP, + sys.CsumPseudo, 0xeb70, }, { "syz_test$csum_ipv6_udp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {0x0, \"abcd\"}})", - sys.CsumUDP, + sys.CsumPseudo, 0x541d, }, + { + "syz_test$csum_ipv6_icmp(&(0x7f0000000000)={{\"00112233445566778899aabbccddeeff\", \"ffeeddccbbaa99887766554433221100\"}, {0x0, \"abcd\"}})", + sys.CsumPseudo, + 0x53f4, + }, } for i, test := range tests { p, err := Deserialize([]byte(test.prog)) diff --git a/sys/decl.go b/sys/decl.go index 6b4d24f37..270ae4582 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -194,13 +194,14 @@ type CsumKind int const ( CsumInet CsumKind = iota - CsumTCP - CsumUDP + CsumPseudo ) type CsumType struct { IntTypeCommon - Kind CsumKind + Kind CsumKind + Buf string + Protocol uint64 // for CsumPseudo } type VmaType struct { diff --git a/sys/socket.txt b/sys/socket.txt index afc25f3cd..daada3bfd 100644 --- a/sys/socket.txt +++ b/sys/socket.txt @@ -303,10 +303,10 @@ udp6_pair { resource sock_icmp6[sock] -socket$icmp6(domain const[AF_INET6], type const[SOCK_DGRAM], proto const[IPPROTO_ICMP]) sock_icmp6 -socket$icmp6_raw(domain const[AF_INET6], type const[SOCK_RAW], proto const[IPPROTO_ICMP]) sock_icmp6 -socketpair$icmp6(domain const[AF_INET6], type const[SOCK_DGRAM], proto const[IPPROTO_ICMP], fds ptr[out, icmp6_pair]) -socketpair$icmp6_raw(domain const[AF_INET6], type const[SOCK_RAW], proto const[IPPROTO_ICMP], fds ptr[out, icmp6_pair]) +socket$icmp6(domain const[AF_INET6], type const[SOCK_DGRAM], proto const[IPPROTO_ICMPV6]) sock_icmp6 +socket$icmp6_raw(domain const[AF_INET6], type const[SOCK_RAW], proto const[IPPROTO_ICMPV6]) sock_icmp6 +socketpair$icmp6(domain const[AF_INET6], type const[SOCK_DGRAM], proto const[IPPROTO_ICMPV6], fds ptr[out, icmp6_pair]) +socketpair$icmp6_raw(domain const[AF_INET6], type const[SOCK_RAW], proto const[IPPROTO_ICMPV6], fds ptr[out, icmp6_pair]) accept$icmp6(fd sock_icmp6, peer ptr[out, sockaddr_in6, opt], peerlen ptr[inout, len[peer, int32]]) sock_icmp6 accept4$icmp6(fd sock_icmp6, peer ptr[out, sockaddr_in6, opt], peerlen ptr[inout, len[peer, int32]], flags flags[accept_flags]) sock_icmp6 bind$icmp6(fd sock_icmp6, addr ptr[in, sockaddr_in6], addrlen len[addr]) diff --git a/sys/test.txt b/sys/test.txt index 9d4ac0ced..851164305 100644 --- a/sys/test.txt +++ b/sys/test.txt @@ -398,6 +398,7 @@ syz_test$csum_ipv4_tcp(a0 ptr[in, syz_csum_ipv4_tcp_packet]) syz_test$csum_ipv6_tcp(a0 ptr[in, syz_csum_ipv6_tcp_packet]) syz_test$csum_ipv4_udp(a0 ptr[in, syz_csum_ipv4_udp_packet]) syz_test$csum_ipv6_udp(a0 ptr[in, syz_csum_ipv6_udp_packet]) +syz_test$csum_ipv6_icmp(a0 ptr[in, syz_csum_ipv6_icmp_packet]) syz_csum_encode { f0 int16 @@ -409,13 +410,13 @@ syz_csum_encode { } [packed] syz_csum_ipv4_header { - csum csum[inet, int16] + csum csum[parent, inet, int16] src_ip int32be dst_ip int32be } [packed] syz_csum_tcp_header { - csum csum[tcp, int16] + csum csum[syz_csum_tcp_packet, pseudo, IPPROTO_TCP, int16] } [packed] syz_csum_tcp_packet { @@ -439,7 +440,7 @@ syz_csum_ipv6_tcp_packet { } [packed] syz_csum_udp_packet { - csum csum[udp, int16] + csum csum[parent, pseudo, IPPROTO_UDP, int16] payload array[int8] } [packed] @@ -452,3 +453,13 @@ syz_csum_ipv6_udp_packet { header syz_csum_ipv6_header payload syz_csum_udp_packet } [packed] + +syz_csum_icmp_packet { + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16] + payload array[int8] +} [packed] + +syz_csum_ipv6_icmp_packet { + header syz_csum_ipv6_header + payload syz_csum_icmp_packet +} [packed] diff --git a/sys/vnet.txt b/sys/vnet.txt index eee1ece19..817290e36 100644 --- a/sys/vnet.txt +++ b/sys/vnet.txt @@ -247,7 +247,7 @@ ipv4_header { # TODO: frag_off is actually 13 bits, 3 bits are flags ttl int8 protocol flags[ipv4_types, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] src_ip ipv4_addr dst_ip ipv4_addr options ipv4_options @@ -255,7 +255,7 @@ ipv4_header { ipv4_packet { header ipv4_header - payload ip_payload + payload ipv4_payload } [packed] ################################################################################ @@ -302,6 +302,7 @@ ipv6_addr [ # NEXTHDR_HOP, NEXTHDR_TCP, NEXTHDR_UDP, NEXTHDR_IPV6, NEXTHDR_ROUTING, NEXTHDR_FRAGMENT, NEXTHDR_GRE, NEXTHDR_ESP, NEXTHDR_AUTH, NEXTHDR_ICMP, NEXTHDR_NONE, NEXTHDR_DEST, NEXTHDR_SCTP, NEXTHDR_MOBILITY # https://tools.ietf.org/html/rfc2402 # https://tools.ietf.org/html/rfc2406 +# https://tools.ietf.org/html/rfc3775 # https://tools.ietf.org/html/rfc2460#section-4 # The length field in each of the extension headers specifies the @@ -371,19 +372,25 @@ ipv6_packet { ipv6_packet_payload { ext_headers array[ipv6_ext_header] - payload ip_payload + payload ipv6_payload } [packed] ################################################################################ ###################################### IP ###################################### ################################################################################ -ip_payload [ +ipv4_payload [ tcp tcp_packet udp udp_packet icmp icmp_packet ] [varlen] +ipv6_payload [ + tcp tcp_packet + udp udp_packet + icmpv6 icmpv6_packet +] [varlen] + ################################################################################ ###################################### TCP ##################################### ################################################################################ @@ -500,7 +507,7 @@ tcp_header { data_off bytesize4[parent, int8:4] flags flags[tcp_flags, int8] window_size int16be - csum csum[tcp, int16be] + csum csum[tcp_packet, pseudo, IPPROTO_TCP, int16be] urg_ptr int16be options tcp_options } [packed] @@ -525,7 +532,7 @@ udp_packet { src_port proc[int16be, 20000, 4] dst_port proc[int16be, 20000, 4] length len[parent, int16be] - csum csum[udp, int16be] + csum csum[parent, pseudo, IPPROTO_UDP, int16be] data array[int8] } [packed] @@ -535,6 +542,8 @@ udp_packet { # https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#ICMP_datagram_structure # https://tools.ietf.org/html/rfc792 +# https://tools.ietf.org/html/rfc4884#section-4.1 +# http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml include @@ -557,7 +566,7 @@ icmp_ipv4_header { icmp_echo_reply_packet { type const[ICMP_ECHOREPLY, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] id int16be seq_num int16be data array[int8] @@ -568,8 +577,9 @@ icmp_dest_unreach_codes = ICMP_NET_UNREACH, ICMP_HOST_UNREACH, ICMP_PROT_UNREACH icmp_dest_unreach_packet { type const[ICMP_DEST_UNREACH, int8] code flags[icmp_dest_unreach_codes, int8] - csum csum[inet, int16be] - unused const[0, int16] + csum csum[parent, inet, int16be] + unused const[0, int8] + length int8 mtu int16be iph icmp_ipv4_header data array[int8, 0:8] @@ -578,7 +588,7 @@ icmp_dest_unreach_packet { icmp_source_quench_packet { type const[ICMP_SOURCE_QUENCH, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] unused const[0, int32] iph icmp_ipv4_header data array[int8, 0:8] @@ -589,7 +599,7 @@ icmp_redirect_codes = ICMP_REDIR_NET, ICMP_REDIR_HOST, ICMP_REDIR_NETTOS, ICMP_R icmp_redirect_packet { type const[ICMP_REDIRECT, int8] code flags[icmp_redirect_codes, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] ip ipv4_addr iph icmp_ipv4_header data array[int8, 0:8] @@ -598,7 +608,7 @@ icmp_redirect_packet { icmp_echo_packet { type const[ICMP_ECHO, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] id int16be seq_num int16be data array[int8] @@ -609,8 +619,10 @@ icmp_time_exceeded_codes = ICMP_EXC_TTL, ICMP_EXC_FRAGTIME icmp_time_exceeded_packet { type const[ICMP_TIME_EXCEEDED, int8] code flags[icmp_time_exceeded_codes, int8] - csum csum[inet, int16be] - unsed const[0, int32] + csum csum[parent, inet, int16be] + unused1 const[0, int8] + length int8 + unused2 const[0, int16] iph icmp_ipv4_header data array[int8, 0:8] } [packed] @@ -618,9 +630,10 @@ icmp_time_exceeded_packet { icmp_parameter_prob_packet { type const[ICMP_PARAMETERPROB, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] pointer int8 - unsed array[const[0, int8], 3] + length int8 + unsed const[0, int16] iph icmp_ipv4_header data array[int8, 0:8] } [packed] @@ -628,7 +641,7 @@ icmp_parameter_prob_packet { icmp_timestamp_packet { type const[ICMP_TIMESTAMP, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] id int16be seq_num int16be orig_ts int32be @@ -639,7 +652,7 @@ icmp_timestamp_packet { icmp_timestamp_reply_packet { type const[ICMP_TIMESTAMPREPLY, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] id int16be seq_num int16be orig_ts int32be @@ -650,7 +663,7 @@ icmp_timestamp_reply_packet { icmp_info_request_packet { type const[ICMP_INFO_REQUEST, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] id int16be seq_num int16be } [packed] @@ -658,7 +671,7 @@ icmp_info_request_packet { icmp_info_reply_packet { type const[ICMP_INFO_REPLY, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] id int16be seq_num int16be } [packed] @@ -666,14 +679,14 @@ icmp_info_reply_packet { icmp_address_request_packet { type const[ICMP_ADDRESS, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] mask int32be } [packed] icmp_address_reply_packet { type const[ICMP_ADDRESSREPLY, int8] code const[0, int8] - csum csum[inet, int16be] + csum csum[parent, inet, int16be] mask int32be } [packed] @@ -694,3 +707,120 @@ icmp_packet [ address_request icmp_address_request_packet address_reply icmp_address_reply_packet ] [varlen] + +################################################################################ +##################################### ICMPv6 ################################### +################################################################################ + +# https://tools.ietf.org/html/rfc4443 +# http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml + +include + +icmpv6_ipv6_packet { + priority int8:4 + version const[6, int8:4] + flow_label array[int8, 3] + length int16be + next_header flags[ipv6_types, int8] + hop_limit int8 + src_ip ipv6_addr + dst_ip ipv6_addr + ext_headers array[ipv6_ext_header] + data array[int8] +} [packed] + +icmpv6_dest_unreach_codes = ICMPV6_NOROUTE, ICMPV6_ADM_PROHIBITED, ICMPV6_NOT_NEIGHBOUR, ICMPV6_ADDR_UNREACH, ICMPV6_PORT_UNREACH, ICMPV6_POLICY_FAIL, ICMPV6_REJECT_ROUTE + +icmpv6_dest_unreach_packet { + type const[ICMPV6_DEST_UNREACH, int8] + code flags[icmpv6_dest_unreach_codes, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + length int8 + unused array[const[0, int8], 3] + packet icmpv6_ipv6_packet +} [packed] + +icmpv6_pkt_toobig_packet { + type const[ICMPV6_PKT_TOOBIG, int8] + code const[0, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + mtu int32be + packet icmpv6_ipv6_packet +} [packed] + +icmpv6_time_exceed_codes = ICMPV6_EXC_HOPLIMIT, ICMPV6_EXC_FRAGTIME + +icmpv6_time_exceed_packet { + type const[ICMPV6_TIME_EXCEED, int8] + code flags[icmpv6_time_exceed_codes, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + length int8 + unused array[const[0, int8], 3] + packet icmpv6_ipv6_packet +} [packed] + +icmpv6_param_prob_codes = ICMPV6_HDR_FIELD, ICMPV6_UNK_NEXTHDR, ICMPV6_UNK_OPTION + +icmpv6_param_prob_packet { + type const[ICMPV6_PARAMPROB, int8] + code flags[icmpv6_param_prob_codes, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + pointer int32be + packet icmpv6_ipv6_packet +} [packed] + +icmpv6_echo_request_packet { + type const[ICMPV6_ECHO_REQUEST, int8] + code const[0, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + id int16be + seq_num int16be + data array[int8] +} [packed] + +icmpv6_echo_reply_packet { + type const[ICMPV6_ECHO_REPLY, int8] + code const[0, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + id int16be + seq_num int16be + data array[int8] +} [packed] + +icmpv6_mld_types = ICMPV6_MGM_QUERY, ICMPV6_MGM_REPORT, ICMPV6_MGM_REDUCTION + +# https://tools.ietf.org/html/rfc2710#section-3 +icmpv6_mld_packet { + type flags[icmpv6_mld_types, int8] + code const[0, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + mrd int16be + unused int16 + addr ipv6_addr +} [packed] + +icmpv6_ni_types = ICMPV6_NI_QUERY, ICMPV6_NI_REPLY + +# https://tools.ietf.org/html/rfc4620#section-4 +icmpv6_ni_packet { + type flags[icmpv6_ni_types, int8] + code const[0, int8] + csum csum[parent, pseudo, IPPROTO_ICMPV6, int16be] + qtype int16be + flags int16be + nonce int64be + data array[int8] +} [packed] + +icmpv6_packet [ + dest_unreach icmpv6_dest_unreach_packet + pkt_toobig icmpv6_pkt_toobig_packet + time_exceed icmpv6_time_exceed_packet + param_prob icmpv6_param_prob_packet + echo_request icmpv6_echo_request_packet + echo_reply icmpv6_echo_reply_packet + mld icmpv6_mld_packet +# TODO: ICMPV6_MLD2_REPORT +# TODO: ICMPV6_DHAAD_REQUEST, ICMPV6_DHAAD_REPLY, ICMPV6_MOBILE_PREFIX_SOL, ICMPV6_MOBILE_PREFIX_ADV (with ipv6 ext headers) +] [varlen] diff --git a/sys/vnet_amd64.const b/sys/vnet_amd64.const index e9c262f0d..a9ebe9aad 100644 --- a/sys/vnet_amd64.const +++ b/sys/vnet_amd64.const @@ -63,6 +63,34 @@ ETH_P_TIPC = 35018 ETH_P_TSN = 8944 ETH_P_WCCP = 34878 ETH_P_X25 = 2053 +ICMPV6_ADDR_UNREACH = 3 +ICMPV6_ADM_PROHIBITED = 1 +ICMPV6_DEST_UNREACH = 1 +ICMPV6_DHAAD_REPLY = 145 +ICMPV6_DHAAD_REQUEST = 144 +ICMPV6_ECHO_REPLY = 129 +ICMPV6_ECHO_REQUEST = 128 +ICMPV6_EXC_FRAGTIME = 1 +ICMPV6_EXC_HOPLIMIT = 0 +ICMPV6_HDR_FIELD = 0 +ICMPV6_MGM_QUERY = 130 +ICMPV6_MGM_REDUCTION = 132 +ICMPV6_MGM_REPORT = 131 +ICMPV6_MLD2_REPORT = 143 +ICMPV6_MOBILE_PREFIX_ADV = 147 +ICMPV6_MOBILE_PREFIX_SOL = 146 +ICMPV6_NI_QUERY = 139 +ICMPV6_NI_REPLY = 140 +ICMPV6_NOROUTE = 0 +ICMPV6_NOT_NEIGHBOUR = 2 +ICMPV6_PARAMPROB = 4 +ICMPV6_PKT_TOOBIG = 2 +ICMPV6_POLICY_FAIL = 5 +ICMPV6_PORT_UNREACH = 4 +ICMPV6_REJECT_ROUTE = 6 +ICMPV6_TIME_EXCEED = 3 +ICMPV6_UNK_NEXTHDR = 1 +ICMPV6_UNK_OPTION = 2 ICMP_ADDRESS = 17 ICMP_ADDRESSREPLY = 18 ICMP_DEST_UNREACH = 3 diff --git a/sys/vnet_arm64.const b/sys/vnet_arm64.const index e9c262f0d..a9ebe9aad 100644 --- a/sys/vnet_arm64.const +++ b/sys/vnet_arm64.const @@ -63,6 +63,34 @@ ETH_P_TIPC = 35018 ETH_P_TSN = 8944 ETH_P_WCCP = 34878 ETH_P_X25 = 2053 +ICMPV6_ADDR_UNREACH = 3 +ICMPV6_ADM_PROHIBITED = 1 +ICMPV6_DEST_UNREACH = 1 +ICMPV6_DHAAD_REPLY = 145 +ICMPV6_DHAAD_REQUEST = 144 +ICMPV6_ECHO_REPLY = 129 +ICMPV6_ECHO_REQUEST = 128 +ICMPV6_EXC_FRAGTIME = 1 +ICMPV6_EXC_HOPLIMIT = 0 +ICMPV6_HDR_FIELD = 0 +ICMPV6_MGM_QUERY = 130 +ICMPV6_MGM_REDUCTION = 132 +ICMPV6_MGM_REPORT = 131 +ICMPV6_MLD2_REPORT = 143 +ICMPV6_MOBILE_PREFIX_ADV = 147 +ICMPV6_MOBILE_PREFIX_SOL = 146 +ICMPV6_NI_QUERY = 139 +ICMPV6_NI_REPLY = 140 +ICMPV6_NOROUTE = 0 +ICMPV6_NOT_NEIGHBOUR = 2 +ICMPV6_PARAMPROB = 4 +ICMPV6_PKT_TOOBIG = 2 +ICMPV6_POLICY_FAIL = 5 +ICMPV6_PORT_UNREACH = 4 +ICMPV6_REJECT_ROUTE = 6 +ICMPV6_TIME_EXCEED = 3 +ICMPV6_UNK_NEXTHDR = 1 +ICMPV6_UNK_OPTION = 2 ICMP_ADDRESS = 17 ICMP_ADDRESSREPLY = 18 ICMP_DEST_UNREACH = 3 diff --git a/sys/vnet_ppc64le.const b/sys/vnet_ppc64le.const index e9c262f0d..a9ebe9aad 100644 --- a/sys/vnet_ppc64le.const +++ b/sys/vnet_ppc64le.const @@ -63,6 +63,34 @@ ETH_P_TIPC = 35018 ETH_P_TSN = 8944 ETH_P_WCCP = 34878 ETH_P_X25 = 2053 +ICMPV6_ADDR_UNREACH = 3 +ICMPV6_ADM_PROHIBITED = 1 +ICMPV6_DEST_UNREACH = 1 +ICMPV6_DHAAD_REPLY = 145 +ICMPV6_DHAAD_REQUEST = 144 +ICMPV6_ECHO_REPLY = 129 +ICMPV6_ECHO_REQUEST = 128 +ICMPV6_EXC_FRAGTIME = 1 +ICMPV6_EXC_HOPLIMIT = 0 +ICMPV6_HDR_FIELD = 0 +ICMPV6_MGM_QUERY = 130 +ICMPV6_MGM_REDUCTION = 132 +ICMPV6_MGM_REPORT = 131 +ICMPV6_MLD2_REPORT = 143 +ICMPV6_MOBILE_PREFIX_ADV = 147 +ICMPV6_MOBILE_PREFIX_SOL = 146 +ICMPV6_NI_QUERY = 139 +ICMPV6_NI_REPLY = 140 +ICMPV6_NOROUTE = 0 +ICMPV6_NOT_NEIGHBOUR = 2 +ICMPV6_PARAMPROB = 4 +ICMPV6_PKT_TOOBIG = 2 +ICMPV6_POLICY_FAIL = 5 +ICMPV6_PORT_UNREACH = 4 +ICMPV6_REJECT_ROUTE = 6 +ICMPV6_TIME_EXCEED = 3 +ICMPV6_UNK_NEXTHDR = 1 +ICMPV6_UNK_OPTION = 2 ICMP_ADDRESS = 17 ICMP_ADDRESSREPLY = 18 ICMP_DEST_UNREACH = 3 diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index e88710d56..09efdf66a 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -501,22 +501,34 @@ func generateArg( } fmt.Fprintf(out, "&LenType{%v, Buf: \"%v\", ByteSize: %v}", intCommon(size, bigEndian, bitfieldLen), a[0], byteSize) case "csum": - if want := 2; len(a) != want { - failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + if len(a) != 3 && len(a) != 4 { + failf("wrong number of arguments for %v arg %v, want 3-4, got %v", typ, name, len(a)) } - size, bigEndian, bitfieldLen := decodeIntType(a[1]) + var size uint64 + var bigEndian bool + var bitfieldLen uint64 + var protocol uint64 var kind string - switch a[0] { + switch a[1] { case "inet": kind = "CsumInet" - case "tcp": - kind = "CsumTCP" - case "udp": - kind = "CsumUDP" + size, bigEndian, bitfieldLen = decodeIntType(a[2]) + case "pseudo": + kind = "CsumPseudo" + size, bigEndian, bitfieldLen = decodeIntType(a[3]) + if v, ok := consts[a[2]]; ok { + protocol = v + } else { + v, err := strconv.ParseUint(a[2], 10, 64) + if err != nil { + failf("failed to parse protocol %v", a[2]) + } + protocol = v + } default: failf("unknown checksum kind '%v'", a[0]) } - fmt.Fprintf(out, "&CsumType{%v, Kind: %v}", intCommon(size, bigEndian, bitfieldLen), kind) + fmt.Fprintf(out, "&CsumType{%v, Buf: \"%s\", Kind: %v, Protocol: %v}", intCommon(size, bigEndian, bitfieldLen), a[0], kind, protocol) case "flags": canBeArg = true size := uint64(ptrSize) -- cgit mrf-deployment