Open installs a WinDivert filter matching scope and starts the recv loop. Requires Administrator and the WinDivert driver installed.
(ctx context.Context, scope snixplatform.Scope)
| 55 | // Open installs a WinDivert filter matching scope and starts the recv loop. |
| 56 | // Requires Administrator and the WinDivert driver installed. |
| 57 | func (b *Backend) Open(ctx context.Context, scope snixplatform.Scope) error { |
| 58 | b.mu.Lock() |
| 59 | defer b.mu.Unlock() |
| 60 | if b.opened { |
| 61 | return errors.New("snix/windows: backend already open") |
| 62 | } |
| 63 | if !scope.RemoteIP.Is4() { |
| 64 | return fmt.Errorf("snix/windows: IPv6 scope not yet supported (%s)", scope.RemoteIP) |
| 65 | } |
| 66 | |
| 67 | // Fail fast with a clear message when not elevated. WinDivertOpen will |
| 68 | // also reject us, but this check runs before we even touch the DLL so |
| 69 | // diagnostics are crisp (no "WinDivertOpen: ERROR_ACCESS_DENIED" noise). |
| 70 | if elevated, err := IsElevated(); err != nil { |
| 71 | return fmt.Errorf("snix/windows: privilege check failed: %w", err) |
| 72 | } else if !elevated { |
| 73 | return fmt.Errorf("%w; relaunch from an elevated shell (Run as Administrator)", ErrNotElevated) |
| 74 | } |
| 75 | |
| 76 | filter := fmt.Sprintf( |
| 77 | "tcp and ip and ((ip.DstAddr == %s and tcp.DstPort == %d) or (ip.SrcAddr == %s and tcp.SrcPort == %d))", |
| 78 | scope.RemoteIP, scope.RemotePort, scope.RemoteIP, scope.RemotePort) |
| 79 | |
| 80 | h, err := Open(filter, LayerNetwork, b.cfg.Priority, FlagDefault) |
| 81 | if err != nil { |
| 82 | return err |
| 83 | } |
| 84 | if b.cfg.QueueLength > 0 { |
| 85 | if e := SetParam(h, ParamQueueLength, b.cfg.QueueLength); e != nil { |
| 86 | _ = Close(h) |
| 87 | return fmt.Errorf("SetParam QueueLength: %w", e) |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | b.handle = h |
| 92 | b.scope = scope |
| 93 | b.opened = true |
| 94 | |
| 95 | b.reader.Add(1) |
| 96 | go b.recvLoop(ctx) |
| 97 | return nil |
| 98 | } |
| 99 | |
| 100 | // recvLoop reads WinDivert packets and forwards them on b.packets. |
| 101 | // The caller's Verdict decides whether the packet is reinjected (Accept), |
nothing calls this directly
no test coverage detected