| 1 | package instancectl |
| 2 | |
| 3 | import ( |
| 4 | "encoding/binary" |
| 5 | "net" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | func TestPlan14BoundConnectFilter(t *testing.T) { |
| 10 | for _, test := range []struct { |
| 11 | ip string |
| 12 | ipv6, allow bool |
| 13 | }{ |
| 14 | {"127.0.0.1", false, false}, {"127.0.0.53", false, false}, {"127.23.4.5", false, false}, |
| 15 | {"1.1.1.1", false, true}, {"::1", true, false}, {"::ffff:127.0.0.1", true, false}, |
| 16 | {"2001:4860:4860::8888", true, true}, {"::ffff:1.1.1.1", true, true}, |
| 17 | } { |
| 18 | t.Run(test.ip, func(t *testing.T) { |
| 19 | var ctx [24]byte |
| 20 | ip := net.ParseIP(test.ip) |
| 21 | if test.ipv6 { |
| 22 | copy(ctx[8:], ip.To16()) |
| 23 | } else { |
| 24 | copy(ctx[4:], ip.To4()) |
| 25 | } |
| 26 | p := claimConnectFilter(test.ipv6) |
| 27 | var reg uint32 |
| 28 | for pc, steps := 0, 0; ; pc, steps = pc+1, steps+1 { |
| 29 | if pc < 0 || pc >= len(p) || steps > 100 { |
| 30 | t.Fatal("invalid program control flow", pc) |
| 31 | } |
| 32 | i := p[pc] |
| 33 | switch i.Code { |
| 34 | case 0x61: |
| 35 | reg = binary.NativeEndian.Uint32(ctx[i.Offset : i.Offset+4]) |
| 36 | case 0xdc: |
| 37 | var b [4]byte |
| 38 | binary.NativeEndian.PutUint32(b[:], reg) |
| 39 | reg = binary.BigEndian.Uint32(b[:]) |
| 40 | case 0x54: |
| 41 | reg &= uint32(i.Immediate) |
| 42 | case 0x15: |
| 43 | if reg == uint32(i.Immediate) { |
| 44 | pc += int(i.Offset) |
| 45 | } |
| 46 | case 0x55: |
| 47 | if reg != uint32(i.Immediate) { |
| 48 | pc += int(i.Offset) |
| 49 | } |
| 50 | case 0xb7: |
| 51 | reg = uint32(i.Immediate) |
| 52 | case 0x95: |
| 53 | if (reg == 1) != test.allow { |
| 54 | t.Fatal("wrong network verdict", reg) |
| 55 | } |
| 56 | return |
| 57 | default: |
| 58 | t.Fatal("unknown instruction", i) |
| 59 | } |
| 60 | } |
| 61 | }) |
| 62 | } |
| 63 | } |
| 64 | |