@@ -19,6 +19,7 @@ import (
1919 "fmt"
2020
2121 "gvisor.dev/gvisor/pkg/abi/linux"
22+ "gvisor.dev/gvisor/pkg/bits"
2223 "gvisor.dev/gvisor/pkg/hostarch"
2324 "gvisor.dev/gvisor/pkg/marshal"
2425 "gvisor.dev/gvisor/pkg/syserr"
@@ -103,6 +104,15 @@ func init() {
103104 registerTargetMaker (& dnatTargetMakerR2 {
104105 NetworkProtocol : header .IPv6ProtocolNumber ,
105106 })
107+
108+ // REJECT targets.
109+ registerTargetMaker (& rejectTargetMaker {
110+ NetworkProtocol : header .IPv4ProtocolNumber ,
111+ })
112+ registerTargetMaker (& rejectTargetMaker {
113+ NetworkProtocol : header .IPv6ProtocolNumber ,
114+ })
115+
106116}
107117
108118// The stack package provides some basic, useful targets for us. The following
@@ -533,3 +543,210 @@ func htons(port uint16) uint16 {
533543 hostarch .ByteOrder .PutUint16 (buf , port )
534544 return binary .BigEndian .Uint16 (buf )
535545}
546+
547+ // RejectTargetName is used to mark targets as reject targets.
548+ const RejectTargetName = "REJECT"
549+
550+ // +stateify savable
551+ type rejectIPv4Target struct {
552+ stack.RejectIPv4Target
553+ }
554+
555+ func (rt * rejectIPv4Target ) id () targetID {
556+ return targetID {
557+ name : RejectTargetName ,
558+ networkProtocol : header .IPv4ProtocolNumber ,
559+ }
560+ }
561+
562+ // +stateify savable
563+ type rejectIPv6Target struct {
564+ stack.RejectIPv6Target
565+ }
566+
567+ func (rt * rejectIPv6Target ) id () targetID {
568+ return targetID {
569+ name : RejectTargetName ,
570+ networkProtocol : header .IPv6ProtocolNumber ,
571+ }
572+ }
573+
574+ // +stateify savable
575+ type rejectTargetMaker struct {
576+ NetworkProtocol tcpip.NetworkProtocolNumber
577+ }
578+
579+ func (rm * rejectTargetMaker ) id () targetID {
580+ return targetID {
581+ name : RejectTargetName ,
582+ networkProtocol : rm .NetworkProtocol ,
583+ }
584+ }
585+
586+ func (rm * rejectTargetMaker ) marshalIPv4 (tgt target ) []byte {
587+ rt := tgt .(* rejectIPv4Target )
588+ size := bits .AlignUp (linux .SizeOfXTEntryTarget + linux .SizeOfIPTRejectInfo , 8 )
589+ xt := linux.XTEntryTarget {
590+ TargetSize : uint16 (size ),
591+ }
592+ copy (xt .Name [:], RejectTargetName )
593+
594+ var with uint32
595+ switch rt .RejectWith {
596+ case stack .RejectIPv4WithICMPNetUnreachable :
597+ with = linux .IPT_ICMP_NET_UNREACHABLE
598+ case stack .RejectIPv4WithICMPHostUnreachable :
599+ with = linux .IPT_ICMP_HOST_UNREACHABLE
600+ case stack .RejectIPv4WithICMPPortUnreachable :
601+ with = linux .IPT_ICMP_PORT_UNREACHABLE
602+ case stack .RejectIPv4WithICMPNetProhibited :
603+ with = linux .IPT_ICMP_NET_PROHIBITED
604+ case stack .RejectIPv4WithICMPHostProhibited :
605+ with = linux .IPT_ICMP_HOST_PROHIBITED
606+ case stack .RejectIPv4WithICMPAdminProhibited :
607+ with = linux .IPT_ICMP_ADMIN_PROHIBITED
608+ case stack .RejectIPv4WithTCPReset :
609+ with = linux .IPT_TCP_RESET
610+ case stack .RejectIPv4WithICMPEchoReply :
611+ with = linux .IPT_ICMP_ECHOREPLY
612+ default :
613+ panic (fmt .Sprintf ("unknown reject option %v" , rt .RejectWith ))
614+ }
615+
616+ info := linux.IPTRejectInfo {With : with }
617+
618+ buf := make ([]byte , size )
619+ bufRemain := xt .MarshalUnsafe (buf )
620+ info .MarshalUnsafe (bufRemain )
621+ return buf
622+ }
623+
624+ func (rm * rejectTargetMaker ) marshalIPv6 (tgt target ) []byte {
625+ rt := tgt .(* rejectIPv6Target )
626+ size := bits .AlignUp (linux .SizeOfXTEntryTarget + linux .SizeOfIP6TRejectInfo , 8 )
627+ xt := linux.XTEntryTarget {
628+ TargetSize : uint16 (size ),
629+ }
630+ copy (xt .Name [:], RejectTargetName )
631+
632+ var with uint32
633+ switch rt .RejectWith {
634+ case stack .RejectIPv6WithICMPNoRoute :
635+ with = linux .IP6T_ICMP6_NO_ROUTE
636+ case stack .RejectIPv6WithICMPAddrUnreachable :
637+ with = linux .IP6T_ICMP6_ADDR_UNREACH
638+ case stack .RejectIPv6WithICMPPortUnreachable :
639+ with = linux .IP6T_ICMP6_PORT_UNREACH
640+ case stack .RejectIPv6WithICMPAdminProhibited :
641+ with = linux .IP6T_ICMP6_ADM_PROHIBITED
642+ case stack .RejectIPv6WithTCPReset :
643+ with = linux .IP6T_TCP_RESET
644+ case stack .RejectIPv6WithICMPNotNeighbour :
645+ with = linux .IP6T_ICMP6_NOT_NEIGHBOUR
646+ case stack .RejectIPv6WithICMPPolicyFail :
647+ with = linux .IP6T_ICMP6_POLICY_FAIL
648+ case stack .RejectIPv6WithICMPRejectRoute :
649+ with = linux .IP6T_ICMP6_REJECT_ROUTE
650+ default :
651+ panic (fmt .Sprintf ("unknown reject option %v" , rt .RejectWith ))
652+ }
653+
654+ info := linux.IP6TRejectInfo {With : with }
655+
656+ buf := make ([]byte , size )
657+ bufRemain := xt .MarshalUnsafe (buf )
658+ info .MarshalUnsafe (bufRemain )
659+ return buf
660+ }
661+
662+ func (rm * rejectTargetMaker ) marshal (tgt target ) []byte {
663+ netProto := rm .NetworkProtocol
664+ switch rm .NetworkProtocol {
665+ case header .IPv4ProtocolNumber :
666+ return rm .marshalIPv4 (tgt )
667+ case header .IPv6ProtocolNumber :
668+ return rm .marshalIPv6 (tgt )
669+ default :
670+ panic (fmt .Sprintf ("unsupported network protocol %d" , netProto ))
671+ }
672+ }
673+
674+ func (rm * rejectTargetMaker ) unmarshalIPv4 (buf []byte , filter stack.IPHeaderFilter ) (target , * syserr.Error ) {
675+ if len (buf ) < linux .SizeOfXTEntryTarget + linux .SizeOfIPTRejectInfo {
676+ nflog ("rejectTargetMaker: buf has insufficient size %d" , len (buf ))
677+ return nil , syserr .ErrInvalidArgument
678+ }
679+
680+ var info linux.IPTRejectInfo
681+ info .UnmarshalUnsafe (buf [linux .SizeOfXTEntryTarget :])
682+
683+ var rejectWith stack.RejectIPv4WithICMPType
684+ switch info .With {
685+ case linux .IPT_ICMP_PORT_UNREACHABLE :
686+ rejectWith = stack .RejectIPv4WithICMPPortUnreachable
687+ case linux .IPT_TCP_RESET :
688+ if filter .Protocol != header .TCPProtocolNumber {
689+ nflog ("rejectTargetMaker: TCP_RESET invalid for non-tcp" )
690+ return nil , syserr .ErrInvalidArgument
691+ }
692+ rejectWith = stack .RejectIPv4WithTCPReset
693+ case linux .IPT_ICMP_HOST_UNREACHABLE , linux .IPT_ICMP_NET_UNREACHABLE ,
694+ linux .IPT_ICMP_HOST_PROHIBITED , linux .IPT_ICMP_NET_PROHIBITED , linux .IPT_ICMP_ADMIN_PROHIBITED :
695+
696+ nflog ("rejectTargetMaker: unsupported reject type %d" , info .With )
697+ return nil , syserr .ErrNotSupported
698+ default :
699+ nflog ("rejectTargetMaker: unknown reject type %d" , info .With )
700+ return nil , syserr .ErrInvalidArgument
701+ }
702+
703+ return & rejectIPv4Target {stack.RejectIPv4Target {
704+ RejectWith : rejectWith ,
705+ }}, nil
706+ }
707+
708+ func (rm * rejectTargetMaker ) unmarshalIPv6 (buf []byte , filter stack.IPHeaderFilter ) (target , * syserr.Error ) {
709+ if len (buf ) < linux .SizeOfXTEntryTarget + linux .SizeOfIP6TRejectInfo {
710+ nflog ("rejectTargetMaker: buf has insufficient size %d" , len (buf ))
711+ return nil , syserr .ErrInvalidArgument
712+ }
713+
714+ var info linux.IP6TRejectInfo
715+ info .UnmarshalUnsafe (buf [linux .SizeOfXTEntryTarget :])
716+
717+ var rejectWith stack.RejectIPv6WithICMPType
718+ switch info .With {
719+ case linux .IP6T_ICMP6_PORT_UNREACH :
720+ rejectWith = stack .RejectIPv6WithICMPPortUnreachable
721+ case linux .IP6T_TCP_RESET :
722+ if filter .Protocol != header .TCPProtocolNumber {
723+ nflog ("rejectTargetMaker: TCP_RESET invalid for non-tcp" )
724+ return nil , syserr .ErrInvalidArgument
725+ }
726+ rejectWith = stack .RejectIPv6WithTCPReset
727+ case linux .IP6T_ICMP6_NO_ROUTE , linux .IP6T_ICMP6_ADM_PROHIBITED , linux .IP6T_ICMP6_NOT_NEIGHBOUR ,
728+ linux .IP6T_ICMP6_ADDR_UNREACH , linux .IP6T_ICMP6_POLICY_FAIL , linux .IP6T_ICMP6_REJECT_ROUTE :
729+
730+ nflog ("rejectTargetMaker: unsupported reject type %d" , info .With )
731+ return nil , syserr .ErrNotSupported
732+ default :
733+ nflog ("rejectTargetMaker: unknown reject type %d" , info .With )
734+ return nil , syserr .ErrInvalidArgument
735+ }
736+
737+ return & rejectIPv6Target {stack.RejectIPv6Target {
738+ RejectWith : rejectWith ,
739+ }}, nil
740+ }
741+
742+ func (rm * rejectTargetMaker ) unmarshal (buf []byte , filter stack.IPHeaderFilter ) (target , * syserr.Error ) {
743+ switch filter .NetworkProtocol () {
744+ case header .IPv4ProtocolNumber :
745+ return rm .unmarshalIPv4 (buf , filter )
746+ case header .IPv6ProtocolNumber :
747+ return rm .unmarshalIPv6 (buf , filter )
748+ default :
749+ nflog ("rejectTargetMaker: unsupported network protocol %d" , filter .NetworkProtocol ())
750+ return nil , syserr .ErrInvalidArgument
751+ }
752+ }
0 commit comments