Support REJECT hook

PiperOrigin-RevId: 420174647
This commit is contained in:
Ghanan Gowripalan
2022-01-06 17:11:19 -08:00
committed by gVisor bot
parent d7dbf65873
commit 381a17d923
8 changed files with 480 additions and 20 deletions
+5 -1
View File
@@ -102,13 +102,17 @@ const (
ICMPv4ReassemblyTimeout ICMPv4Code = 1
)
// ICMP codes for ICMPv4 Destination Unreachable messages as defined in RFC 792.
// ICMP codes for ICMPv4 Destination Unreachable messages as defined in RFC 792,
// RFC 1122 section 3.2.2.1 and RFC 1812 section 5.2.7.1.
const (
ICMPv4NetUnreachable ICMPv4Code = 0
ICMPv4HostUnreachable ICMPv4Code = 1
ICMPv4ProtoUnreachable ICMPv4Code = 2
ICMPv4PortUnreachable ICMPv4Code = 3
ICMPv4FragmentationNeeded ICMPv4Code = 4
ICMPv4NetProhibited ICMPv4Code = 9
ICMPv4HostProhibited ICMPv4Code = 10
ICMPv4AdminProhibited ICMPv4Code = 13
)
// ICMPv4UnusedCode is a code to use in ICMP messages where no code is needed.
+24
View File
@@ -410,6 +410,24 @@ type icmpReason interface {
isICMPReason()
}
// icmpReasonNetworkProhibited is an error where the destination network is
// prohibited.
type icmpReasonNetworkProhibited struct{}
func (*icmpReasonNetworkProhibited) isICMPReason() {}
// icmpReasonHostProhibited is an error where the destination host is
// prohibited.
type icmpReasonHostProhibited struct{}
func (*icmpReasonHostProhibited) isICMPReason() {}
// icmpReasonAdministrativelyProhibited is an error where the destination is
// administratively prohibited.
type icmpReasonAdministrativelyProhibited struct{}
func (*icmpReasonAdministrativelyProhibited) isICMPReason() {}
// icmpReasonPortUnreachable is an error where the transport protocol has no
// listener and no alternative means to inform the sender.
type icmpReasonPortUnreachable struct{}
@@ -560,6 +578,12 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer, deliv
sent := netEP.stats.icmp.packetsSent
icmpType, icmpCode, counter, pointer := func() (header.ICMPv4Type, header.ICMPv4Code, tcpip.MultiCounterStat, byte) {
switch reason := reason.(type) {
case *icmpReasonNetworkProhibited:
return header.ICMPv4DstUnreachable, header.ICMPv4NetProhibited, sent.dstUnreachable, 0
case *icmpReasonHostProhibited:
return header.ICMPv4DstUnreachable, header.ICMPv4HostProhibited, sent.dstUnreachable, 0
case *icmpReasonAdministrativelyProhibited:
return header.ICMPv4DstUnreachable, header.ICMPv4AdminProhibited, sent.dstUnreachable, 0
case *icmpReasonPortUnreachable:
return header.ICMPv4DstUnreachable, header.ICMPv4PortUnreachable, sent.dstUnreachable, 0
case *icmpReasonProtoUnreachable:
+21
View File
@@ -1129,6 +1129,7 @@ func (e *endpoint) Stats() stack.NetworkEndpointStats {
}
var _ stack.NetworkProtocol = (*protocol)(nil)
var _ stack.RejectIPv4WithHandler = (*protocol)(nil)
var _ fragmentation.TimeoutHandler = (*protocol)(nil)
type protocol struct {
@@ -1285,6 +1286,26 @@ func (p *protocol) allowICMPReply(icmpType header.ICMPv4Type, code header.ICMPv4
return true
}
// SendRejectionError implements stack.RejectIPv4WithHandler.
func (p *protocol) SendRejectionError(pkt *stack.PacketBuffer, rejectWith stack.RejectIPv4WithICMPType, inputHook bool) tcpip.Error {
switch rejectWith {
case stack.RejectIPv4WithICMPNetUnreachable:
return p.returnError(&icmpReasonNetworkUnreachable{}, pkt, inputHook)
case stack.RejectIPv4WithICMPHostUnreachable:
return p.returnError(&icmpReasonHostUnreachable{}, pkt, inputHook)
case stack.RejectIPv4WithICMPPortUnreachable:
return p.returnError(&icmpReasonPortUnreachable{}, pkt, inputHook)
case stack.RejectIPv4WithICMPNetProhibited:
return p.returnError(&icmpReasonNetworkProhibited{}, pkt, inputHook)
case stack.RejectIPv4WithICMPHostProhibited:
return p.returnError(&icmpReasonHostProhibited{}, pkt, inputHook)
case stack.RejectIPv4WithICMPAdminProhibited:
return p.returnError(&icmpReasonAdministrativelyProhibited{}, pkt, inputHook)
default:
panic(fmt.Sprintf("unhandled %[1]T = %[1]d", rejectWith))
}
}
// calculateNetworkMTU calculates the network-layer payload MTU based on the
// link-layer payload mtu.
func calculateNetworkMTU(linkMTU, networkHeaderSize uint32) (uint32, tcpip.Error) {
+13 -1
View File
@@ -678,7 +678,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
})
defer replyPkt.DecRef()
icmp := header.ICMPv6(replyPkt.TransportHeader().Push(header.ICMPv6EchoMinimumSize))
pkt.TransportProtocolNumber = header.ICMPv6ProtocolNumber
replyPkt.TransportProtocolNumber = header.ICMPv6ProtocolNumber
copy(icmp, h)
icmp.SetType(header.ICMPv6EchoReply)
dataRange := replyPkt.Data().AsRange()
@@ -964,6 +964,16 @@ func (p *icmpReasonParameterProblem) respondsToMulticast() bool {
return p.respondToMulticast
}
// icmpReasonAdministrativelyProhibited is an error where the destination is
// administratively prohibited.
type icmpReasonAdministrativelyProhibited struct{}
func (*icmpReasonAdministrativelyProhibited) isICMPReason() {}
func (*icmpReasonAdministrativelyProhibited) respondsToMulticast() bool {
return false
}
// icmpReasonPortUnreachable is an error where the transport protocol has no
// listener and no alternative means to inform the sender.
type icmpReasonPortUnreachable struct{}
@@ -1104,6 +1114,8 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer, deliv
switch reason := reason.(type) {
case *icmpReasonParameterProblem:
return header.ICMPv6ParamProblem, reason.code, sent.paramProblem, reason.pointer
case *icmpReasonAdministrativelyProhibited:
return header.ICMPv6DstUnreachable, header.ICMPv6Prohibited, sent.dstUnreachable, 0
case *icmpReasonPortUnreachable:
return header.ICMPv6DstUnreachable, header.ICMPv6PortUnreachable, sent.dstUnreachable, 0
case *icmpReasonNetUnreachable:
+17
View File
@@ -1899,6 +1899,7 @@ func (e *endpoint) Stats() stack.NetworkEndpointStats {
}
var _ stack.NetworkProtocol = (*protocol)(nil)
var _ stack.RejectIPv6WithHandler = (*protocol)(nil)
var _ fragmentation.TimeoutHandler = (*protocol)(nil)
type protocol struct {
@@ -2124,6 +2125,22 @@ func (p *protocol) allowICMPReply(icmpType header.ICMPv6Type) bool {
return true
}
// SendRejectionError implements stack.RejectIPv6WithHandler.
func (p *protocol) SendRejectionError(pkt *stack.PacketBuffer, rejectWith stack.RejectIPv6WithICMPType, inputHook bool) tcpip.Error {
switch rejectWith {
case stack.RejectIPv6WithICMPNoRoute:
return p.returnError(&icmpReasonNetUnreachable{}, pkt, inputHook)
case stack.RejectIPv6WithICMPAddrUnreachable:
return p.returnError(&icmpReasonHostUnreachable{}, pkt, inputHook)
case stack.RejectIPv6WithICMPPortUnreachable:
return p.returnError(&icmpReasonPortUnreachable{}, pkt, inputHook)
case stack.RejectIPv6WithICMPAdminProhibited:
return p.returnError(&icmpReasonAdministrativelyProhibited{}, pkt, inputHook)
default:
panic(fmt.Sprintf("unhandled %[1]T = %[1]d", rejectWith))
}
}
// calculateNetworkMTU calculates the network-layer payload MTU based on the
// link-layer payload MTU and the length of every IPv6 header.
// Note that this is different than the Payload Length field of the IPv6 header,
+82
View File
@@ -45,6 +45,88 @@ func (*DropTarget) Action(*PacketBuffer, Hook, *Route, AddressableEndpoint) (Rul
return RuleDrop, 0
}
// RejectIPv4WithHandler handles rejecting a packet.
type RejectIPv4WithHandler interface {
// SendRejectionError sends an error packet in response to the packet.
SendRejectionError(pkt *PacketBuffer, rejectWith RejectIPv4WithICMPType, inputHook bool) tcpip.Error
}
// RejectIPv4WithICMPType indicates the type of ICMP error that should be sent.
type RejectIPv4WithICMPType int
// The types of errors that may be returned when rejecting IPv4 packets.
const (
_ RejectIPv4WithICMPType = iota
RejectIPv4WithICMPNetUnreachable
RejectIPv4WithICMPHostUnreachable
RejectIPv4WithICMPPortUnreachable
RejectIPv4WithICMPNetProhibited
RejectIPv4WithICMPHostProhibited
RejectIPv4WithICMPAdminProhibited
)
// RejectIPv4Target drops packets and sends back an error packet in response to the
// matched packet.
type RejectIPv4Target struct {
Handler RejectIPv4WithHandler
RejectWith RejectIPv4WithICMPType
}
// Action implements Target.Action.
func (rt *RejectIPv4Target) Action(pkt *PacketBuffer, hook Hook, _ *Route, _ AddressableEndpoint) (RuleVerdict, int) {
switch hook {
case Input, Forward, Output:
// There is nothing reasonable for us to do in response to an error here;
// we already drop the packet.
_ = rt.Handler.SendRejectionError(pkt, rt.RejectWith, hook == Input)
return RuleDrop, 0
case Prerouting, Postrouting:
panic(fmt.Sprintf("%s hook not supported for REDIRECT", hook))
default:
panic(fmt.Sprintf("unhandled hook = %s", hook))
}
}
// RejectIPv6WithHandler handles rejecting a packet.
type RejectIPv6WithHandler interface {
// SendRejectionError sends an error packet in response to the packet.
SendRejectionError(pkt *PacketBuffer, rejectWith RejectIPv6WithICMPType, forwardingHook bool) tcpip.Error
}
// RejectIPv6WithICMPType indicates the type of ICMP error that should be sent.
type RejectIPv6WithICMPType int
// The types of errors that may be returned when rejecting IPv6 packets.
const (
_ RejectIPv6WithICMPType = iota
RejectIPv6WithICMPNoRoute
RejectIPv6WithICMPAddrUnreachable
RejectIPv6WithICMPPortUnreachable
RejectIPv6WithICMPAdminProhibited
)
// RejectIPv6Target drops packets and sends back an error packet in response to the
// matched packet.
type RejectIPv6Target struct {
Handler RejectIPv6WithHandler
RejectWith RejectIPv6WithICMPType
}
// Action implements Target.Action.
func (rt *RejectIPv6Target) Action(pkt *PacketBuffer, hook Hook, _ *Route, _ AddressableEndpoint) (RuleVerdict, int) {
switch hook {
case Input, Forward, Output:
// There is nothing reasonable for us to do in response to an error here;
// we already drop the packet.
_ = rt.Handler.SendRejectionError(pkt, rt.RejectWith, hook == Input)
return RuleDrop, 0
case Prerouting, Postrouting:
panic(fmt.Sprintf("%s hook not supported for REDIRECT", hook))
default:
panic(fmt.Sprintf("unhandled hook = %s", hook))
}
}
// ErrorTarget logs an error and drops the packet. It represents a target that
// should be unreachable.
type ErrorTarget struct {
@@ -3037,3 +3037,295 @@ func TestLocallyRoutedPackets(t *testing.T) {
})
}
}
type icmpv4Matcher struct {
icmpType header.ICMPv4Type
}
func (m *icmpv4Matcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches bool, hotdrop bool) {
if pkt.NetworkProtocolNumber != header.IPv4ProtocolNumber {
return false, false
}
if pkt.TransportProtocolNumber != header.ICMPv4ProtocolNumber {
return false, false
}
return header.ICMPv4(pkt.TransportHeader().View()).Type() == m.icmpType, false
}
type icmpv6Matcher struct {
icmpType header.ICMPv6Type
}
func (m *icmpv6Matcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches bool, hotdrop bool) {
if pkt.NetworkProtocolNumber != header.IPv6ProtocolNumber {
return false, false
}
if pkt.TransportProtocolNumber != header.ICMPv6ProtocolNumber {
return false, false
}
return header.ICMPv6(pkt.TransportHeader().View()).Type() == m.icmpType, false
}
func TestRejectWith(t *testing.T) {
type natHook struct {
hook stack.Hook
dstAddr tcpip.Address
matcher stack.Matcher
errorICMPDstAddr tcpip.Address
errorICMPPayload buffer.View
}
type rejectWithVal struct {
name string
val int
errorICMPCode uint8
}
rxICMPv4EchoRequest := func(dst tcpip.Address) buffer.View {
return utils.ICMPv4Echo(utils.Host1IPv4Addr.AddressWithPrefix.Address, dst, ttl, header.ICMPv4Echo)
}
rxICMPv6EchoRequest := func(dst tcpip.Address) buffer.View {
return utils.ICMPv6Echo(utils.Host1IPv6Addr.AddressWithPrefix.Address, dst, ttl, header.ICMPv6EchoRequest)
}
tests := []struct {
name string
netProto tcpip.NetworkProtocolNumber
rxICMPEchoRequest func(tcpip.Address) buffer.View
icmpChecker func(*testing.T, buffer.View, tcpip.Address, uint8, uint8, buffer.View)
natHooks []natHook
rejectTarget func(*testing.T, stack.NetworkProtocol, int) stack.Target
rejectWithVals []rejectWithVal
errorICMPType uint8
}{
{
name: "IPv4",
netProto: header.IPv4ProtocolNumber,
rxICMPEchoRequest: rxICMPv4EchoRequest,
icmpChecker: func(t *testing.T, v buffer.View, dstAddr tcpip.Address, icmpType, icmpCode uint8, origPayload buffer.View) {
t.Helper()
checker.IPv4(t, v,
checker.SrcAddr(utils.RouterNIC1IPv4Addr.AddressWithPrefix.Address),
checker.DstAddr(dstAddr),
checker.ICMPv4(
checker.ICMPv4Checksum(),
checker.ICMPv4Type(header.ICMPv4Type(icmpType)),
checker.ICMPv4Code(header.ICMPv4Code(icmpCode)),
checker.ICMPv4Payload(origPayload),
),
)
},
natHooks: []natHook{
{
hook: stack.Input,
dstAddr: utils.RouterNIC1IPv4Addr.AddressWithPrefix.Address,
matcher: &icmpv4Matcher{icmpType: header.ICMPv4Echo},
errorICMPDstAddr: utils.Host1IPv4Addr.AddressWithPrefix.Address,
errorICMPPayload: rxICMPv4EchoRequest(utils.RouterNIC1IPv4Addr.AddressWithPrefix.Address),
},
{
hook: stack.Forward,
dstAddr: utils.Host2IPv4Addr.AddressWithPrefix.Address,
matcher: &icmpv4Matcher{icmpType: header.ICMPv4Echo},
errorICMPDstAddr: utils.Host1IPv4Addr.AddressWithPrefix.Address,
errorICMPPayload: rxICMPv4EchoRequest(utils.Host2IPv4Addr.AddressWithPrefix.Address),
},
{
hook: stack.Output,
dstAddr: utils.RouterNIC1IPv4Addr.AddressWithPrefix.Address,
matcher: &icmpv4Matcher{icmpType: header.ICMPv4EchoReply},
errorICMPDstAddr: utils.RouterNIC1IPv4Addr.AddressWithPrefix.Address,
errorICMPPayload: utils.ICMPv4Echo(utils.RouterNIC1IPv4Addr.AddressWithPrefix.Address, utils.Host1IPv4Addr.AddressWithPrefix.Address, ttl, header.ICMPv4EchoReply),
},
},
rejectTarget: func(t *testing.T, netProto stack.NetworkProtocol, rejectWith int) stack.Target {
handler, ok := netProto.(stack.RejectIPv4WithHandler)
if !ok {
t.Fatalf("expected %T to implement %T", netProto, handler)
}
return &stack.RejectIPv4Target{
Handler: handler,
RejectWith: stack.RejectIPv4WithICMPType(rejectWith),
}
},
rejectWithVals: []rejectWithVal{
{
name: "ICMP Network Unreachable",
val: int(stack.RejectIPv4WithICMPNetUnreachable),
errorICMPCode: uint8(header.ICMPv4NetUnreachable),
},
{
name: "ICMP Host Unreachable",
val: int(stack.RejectIPv4WithICMPHostUnreachable),
errorICMPCode: uint8(header.ICMPv4HostUnreachable),
},
{
name: "ICMP Port Unreachable",
val: int(stack.RejectIPv4WithICMPPortUnreachable),
errorICMPCode: uint8(header.ICMPv4PortUnreachable),
},
{
name: "ICMP Network Prohibited",
val: int(stack.RejectIPv4WithICMPNetProhibited),
errorICMPCode: uint8(header.ICMPv4NetProhibited),
},
{
name: "ICMP Host Prohibited",
val: int(stack.RejectIPv4WithICMPHostProhibited),
errorICMPCode: uint8(header.ICMPv4HostProhibited),
},
{
name: "ICMP Administratively Prohibited",
val: int(stack.RejectIPv4WithICMPAdminProhibited),
errorICMPCode: uint8(header.ICMPv4AdminProhibited),
},
},
errorICMPType: uint8(header.ICMPv4DstUnreachable),
},
{
name: "IPv6",
netProto: header.IPv6ProtocolNumber,
rxICMPEchoRequest: rxICMPv6EchoRequest,
icmpChecker: func(t *testing.T, v buffer.View, dstAddr tcpip.Address, icmpType, icmpCode uint8, origPayload buffer.View) {
t.Helper()
checker.IPv6(t, v,
checker.SrcAddr(utils.RouterNIC1IPv6Addr.AddressWithPrefix.Address),
checker.DstAddr(dstAddr),
checker.ICMPv6(
checker.ICMPv6Type(header.ICMPv6Type(icmpType)),
checker.ICMPv6Code(header.ICMPv6Code(icmpCode)),
checker.ICMPv6Payload(origPayload),
),
)
},
natHooks: []natHook{
{
hook: stack.Input,
dstAddr: utils.RouterNIC1IPv6Addr.AddressWithPrefix.Address,
matcher: &icmpv6Matcher{icmpType: header.ICMPv6EchoRequest},
errorICMPDstAddr: utils.Host1IPv6Addr.AddressWithPrefix.Address,
errorICMPPayload: rxICMPv6EchoRequest(utils.RouterNIC1IPv6Addr.AddressWithPrefix.Address),
},
{
hook: stack.Forward,
dstAddr: utils.Host2IPv6Addr.AddressWithPrefix.Address,
matcher: &icmpv6Matcher{icmpType: header.ICMPv6EchoRequest},
errorICMPDstAddr: utils.Host1IPv6Addr.AddressWithPrefix.Address,
errorICMPPayload: rxICMPv6EchoRequest(utils.Host2IPv6Addr.AddressWithPrefix.Address),
},
{
hook: stack.Output,
dstAddr: utils.RouterNIC1IPv6Addr.AddressWithPrefix.Address,
matcher: &icmpv6Matcher{icmpType: header.ICMPv6EchoReply},
errorICMPDstAddr: utils.RouterNIC1IPv6Addr.AddressWithPrefix.Address,
errorICMPPayload: utils.ICMPv6Echo(utils.RouterNIC1IPv6Addr.AddressWithPrefix.Address, utils.Host1IPv6Addr.AddressWithPrefix.Address, ttl, header.ICMPv6EchoReply),
},
},
rejectTarget: func(t *testing.T, netProto stack.NetworkProtocol, rejectWith int) stack.Target {
handler, ok := netProto.(stack.RejectIPv6WithHandler)
if !ok {
t.Fatalf("expected %T to implement %T", netProto, handler)
}
return &stack.RejectIPv6Target{
Handler: handler,
RejectWith: stack.RejectIPv6WithICMPType(rejectWith),
}
},
rejectWithVals: []rejectWithVal{
{
name: "ICMP No Route",
val: int(stack.RejectIPv6WithICMPNoRoute),
errorICMPCode: uint8(header.ICMPv6NetworkUnreachable),
},
{
name: "ICMP Address Unreachable",
val: int(stack.RejectIPv6WithICMPAddrUnreachable),
errorICMPCode: uint8(header.ICMPv6AddressUnreachable),
},
{
name: "ICMP Port Unreachable",
val: int(stack.RejectIPv6WithICMPPortUnreachable),
errorICMPCode: uint8(header.ICMPv6PortUnreachable),
},
{
name: "ICMP Administratively Prohibited",
val: int(stack.RejectIPv6WithICMPAdminProhibited),
errorICMPCode: uint8(header.ICMPv6Prohibited),
},
},
errorICMPType: uint8(header.ICMPv6DstUnreachable),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
for _, natHook := range test.natHooks {
t.Run(natHook.hook.String(), func(t *testing.T) {
for _, rejectWith := range test.rejectWithVals {
t.Run(rejectWith.name, func(t *testing.T) {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol, tcp.NewProtocol},
})
ep1 := channel.New(1, header.IPv6MinimumMTU, "")
ep2 := channel.New(1, header.IPv6MinimumMTU, "")
utils.SetupRouterStack(t, s, ep1, ep2)
{
ipv6 := test.netProto == ipv6.ProtocolNumber
ipt := s.IPTables()
filter := ipt.GetTable(stack.FilterID, ipv6)
ruleIdx := filter.BuiltinChains[natHook.hook]
filter.Rules[ruleIdx].Matchers = []stack.Matcher{natHook.matcher}
filter.Rules[ruleIdx].Target = test.rejectTarget(t, s.NetworkProtocolInstance(test.netProto), rejectWith.val)
// Make sure the packet is not dropped by the next rule.
filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
if err := ipt.ReplaceTable(stack.FilterID, filter, ipv6); err != nil {
t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, ipv6, err)
}
}
func() {
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: test.rxICMPEchoRequest(natHook.dstAddr).ToVectorisedView(),
})
defer pkt.DecRef()
ep1.InjectInbound(test.netProto, pkt)
}()
{
pkt := ep1.Read()
if pkt == nil {
t.Fatal("expected to read a packet on ep1")
}
test.icmpChecker(
t,
stack.PayloadSince(pkt.NetworkHeader()),
natHook.errorICMPDstAddr,
test.errorICMPType,
rejectWith.errorICMPCode,
natHook.errorICMPPayload,
)
}
})
}
})
}
})
}
}
+26 -18
View File
@@ -353,7 +353,8 @@ func SetupRoutedStacks(t *testing.T, host1Stack, routerStack, host2Stack *stack.
})
}
func rxICMPv4Echo(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8, ty header.ICMPv4Type) {
// ICMPv4Echo returns an ICMPv4 echo packet.
func ICMPv4Echo(src, dst tcpip.Address, ttl uint8, ty header.ICMPv4Type) buffer.View {
totalLen := header.IPv4MinimumSize + header.ICMPv4MinimumSize
hdr := buffer.NewPrependable(totalLen)
pkt := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize))
@@ -370,27 +371,31 @@ func rxICMPv4Echo(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8, ty hea
DstAddr: dst,
})
ip.SetChecksum(^ip.CalculateChecksum())
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
})
defer newPkt.DecRef()
e.InjectInbound(header.IPv4ProtocolNumber, newPkt)
return hdr.View()
}
// RxICMPv4EchoRequest constructs and injects an ICMPv4 echo request packet on
// the provided endpoint.
func RxICMPv4EchoRequest(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
rxICMPv4Echo(e, src, dst, ttl, header.ICMPv4Echo)
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: ICMPv4Echo(src, dst, ttl, header.ICMPv4Echo).ToVectorisedView(),
})
defer newPkt.DecRef()
e.InjectInbound(header.IPv4ProtocolNumber, newPkt)
}
// RxICMPv4EchoReply constructs and injects an ICMPv4 echo reply packet on
// the provided endpoint.
func RxICMPv4EchoReply(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
rxICMPv4Echo(e, src, dst, ttl, header.ICMPv4EchoReply)
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: ICMPv4Echo(src, dst, ttl, header.ICMPv4EchoReply).ToVectorisedView(),
})
defer newPkt.DecRef()
e.InjectInbound(header.IPv4ProtocolNumber, newPkt)
}
func rxICMPv6Echo(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8, ty header.ICMPv6Type) {
// ICMPv6Echo returns an ICMPv6 echo packet.
func ICMPv6Echo(src, dst tcpip.Address, ttl uint8, ty header.ICMPv6Type) buffer.View {
totalLen := header.IPv6MinimumSize + header.ICMPv6MinimumSize
hdr := buffer.NewPrependable(totalLen)
pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6MinimumSize))
@@ -410,22 +415,25 @@ func rxICMPv6Echo(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8, ty hea
SrcAddr: src,
DstAddr: dst,
})
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
})
defer newPkt.DecRef()
e.InjectInbound(header.IPv6ProtocolNumber, newPkt)
return hdr.View()
}
// RxICMPv6EchoRequest constructs and injects an ICMPv6 echo request packet on
// the provided endpoint.
func RxICMPv6EchoRequest(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
rxICMPv6Echo(e, src, dst, ttl, header.ICMPv6EchoRequest)
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: ICMPv6Echo(src, dst, ttl, header.ICMPv6EchoRequest).ToVectorisedView(),
})
defer newPkt.DecRef()
e.InjectInbound(header.IPv6ProtocolNumber, newPkt)
}
// RxICMPv6EchoReply constructs and injects an ICMPv6 echo reply packet on
// the provided endpoint.
func RxICMPv6EchoReply(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
rxICMPv6Echo(e, src, dst, ttl, header.ICMPv6EchoReply)
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: ICMPv6Echo(src, dst, ttl, header.ICMPv6EchoReply).ToVectorisedView(),
})
defer newPkt.DecRef()
e.InjectInbound(header.IPv6ProtocolNumber, newPkt)
}