aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2017-02-08 15:49:03 +0100
committerAndrey Konovalov <andreyknvl@google.com>2017-02-08 17:11:54 +0100
commit0130c7b34e9e4e831c2794f00a0d017040a967a9 (patch)
treed004778543ebef9d348e491f428d0de17d332b28
parent8792b9237970ec1e93423de538bbe646a8ecff90 (diff)
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.
-rw-r--r--prog/checksum.go146
-rw-r--r--prog/checksum_test.go17
-rw-r--r--sys/decl.go7
-rw-r--r--sys/socket.txt8
-rw-r--r--sys/test.txt17
-rw-r--r--sys/vnet.txt174
-rw-r--r--sys/vnet_amd64.const28
-rw-r--r--sys/vnet_arm64.const28
-rw-r--r--sys/vnet_ppc64le.const28
-rw-r--r--sysgen/sysgen.go30
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 <uapi/linux/icmp.h>
@@ -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 <uapi/linux/icmpv6.h>
+
+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)