66 "encoding/hex"
77 "errors"
88 "fmt"
9+ "math"
910 "net"
1011 "syscall"
1112
@@ -371,6 +372,18 @@ func (h *Handle) filterModify(filter Filter, proto, flags int) error {
371372 if filter .Fd >= 0 {
372373 options .AddRtAttr (nl .TCA_BPF_FD , nl .Uint32Attr ((uint32 (filter .Fd ))))
373374 }
375+ if len (filter .Ops ) > 0 {
376+ if filter .Fd >= 0 {
377+ return fmt .Errorf ("only Ops or Fd can be specified on a BpfFilter" )
378+ }
379+
380+ opsLen , ops , err := serializeSockFilter (filter .Ops )
381+ if err != nil {
382+ return err
383+ }
384+ options .AddRtAttr (nl .TCA_BPF_OPS_LEN , nl .Uint16Attr (opsLen ))
385+ options .AddRtAttr (nl .TCA_BPF_OPS , ops )
386+ }
374387 if filter .Name != "" {
375388 options .AddRtAttr (nl .TCA_BPF_NAME , nl .ZeroTerminated (filter .Name ))
376389 }
@@ -934,7 +947,10 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
934947
935948func parseBpfData (filter Filter , data []syscall.NetlinkRouteAttr ) (bool , error ) {
936949 bpf := filter .(* BpfFilter )
950+ bpf .Fd = - 1
937951 detailed := true
952+ var opsLen uint16
953+ var ops []byte
938954 for _ , datum := range data {
939955 switch datum .Attr .Type {
940956 case nl .TCA_BPF_FD :
@@ -952,6 +968,17 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
952968 bpf .Id = int (native .Uint32 (datum .Value [0 :4 ]))
953969 case nl .TCA_BPF_TAG :
954970 bpf .Tag = hex .EncodeToString (datum .Value )
971+ case nl .TCA_BPF_OPS_LEN :
972+ opsLen = native .Uint16 (datum .Value [0 :2 ])
973+ case nl .TCA_BPF_OPS :
974+ ops = datum .Value
975+ }
976+ }
977+ if opsLen > 0 {
978+ var err error
979+ bpf .Ops , err = deserializeSockFilter (opsLen , ops )
980+ if err != nil {
981+ return detailed , err
955982 }
956983 }
957984 return detailed , nil
@@ -1039,3 +1066,42 @@ func SerializeRtab(rtab [256]uint32) []byte {
10391066 _ = binary .Write (& w , native , rtab )
10401067 return w .Bytes ()
10411068}
1069+
1070+ func deserializeSockFilter (opsLen uint16 , ops []byte ) ([]SockFilter , error ) {
1071+ if excp := int (opsLen ) * 8 ; len (ops ) != excp {
1072+ return nil , fmt .Errorf ("unexpected ops length %d, expected %d" , len (ops ), excp )
1073+ }
1074+
1075+ ins := make ([]SockFilter , opsLen )
1076+ for i := 0 ; i < len (ins ); i ++ {
1077+ ins [i ] = SockFilter {
1078+ Code : native .Uint16 (ops [0 :]),
1079+ Jt : ops [2 ],
1080+ Jf : ops [3 ],
1081+ K : native .Uint32 (ops [4 :]),
1082+ }
1083+
1084+ ops = ops [8 :]
1085+ }
1086+
1087+ return ins , nil
1088+ }
1089+
1090+ func serializeSockFilter (rawIns []SockFilter ) (uint16 , []byte , error ) {
1091+ opsLen := len (rawIns )
1092+ if opsLen > math .MaxUint16 {
1093+ return 0 , nil , fmt .Errorf ("too many bpf instructions, max %d" , math .MaxUint16 )
1094+ }
1095+
1096+ ops := make ([]byte , 8 * opsLen )
1097+ b := ops
1098+ for _ , ins := range rawIns {
1099+ native .PutUint16 (b [0 :], ins .Code )
1100+ b [2 ] = ins .Jt
1101+ b [3 ] = ins .Jf
1102+ native .PutUint32 (b [4 :], ins .K )
1103+
1104+ b = b [8 :]
1105+ }
1106+ return uint16 (opsLen ), ops , nil
1107+ }
0 commit comments