github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/parameters/packetman.go (about) 1 /* 2 * Copyright (c) 2020, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package parameters 21 22 import ( 23 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors" 24 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol" 25 ) 26 27 // PacketManipulationSpec is a work-around to avoid the client-side code size 28 // impact of importing the packetman package and its dependencies. 29 // 30 // TODO: Given that packetman and its parameters are server-side only, 31 // rearrange tactics/parameters to reference packetman.Spec directly, but only 32 // in server code. This should allow reinstating the spec.Validate below. 33 34 // PacketManipulationSpec is type-compatible with 35 // psiphon/common.packetman.Spec. 36 type PacketManipulationSpec struct { 37 Name string 38 PacketSpecs [][]string 39 } 40 41 // PacketManipulationSpecs is a list of packet manipulation specs. 42 type PacketManipulationSpecs []*PacketManipulationSpec 43 44 // Validate checks that each spec name is unique and that each spec compiles. 45 func (specs PacketManipulationSpecs) Validate() error { 46 specNames := make(map[string]bool) 47 for _, spec := range specs { 48 if spec.Name == "" { 49 return errors.TraceNew("missing spec name") 50 } 51 if ok, _ := specNames[spec.Name]; ok { 52 return errors.Tracef("duplicate spec name: %s", spec.Name) 53 } 54 specNames[spec.Name] = true 55 56 // See PacketManipulationSpec comment above. 57 // 58 // Note that, even with spec.Validate disabled, spec validation will still 59 // be performed, by packetman.Manipulator, on startup and after tactics hot 60 // reload, with equivilent outcomes for invalid specs; however, the tactics 61 // load itself will not fail in this case. 62 63 // err := spec.Validate() 64 // if err != nil { 65 // return errors.Trace(err) 66 // } 67 } 68 return nil 69 } 70 71 // ProtocolPacketManipulations is a map from tunnel protocol names (or "All") 72 // to a list of packet manipulation spec names. 73 type ProtocolPacketManipulations map[string][]string 74 75 // Validate checks that tunnel protocol and spec names are valid. Duplicate 76 // spec names are allowed in each entry, enabling weighted selection. 77 func (manipulations ProtocolPacketManipulations) Validate(specs PacketManipulationSpecs) error { 78 validSpecNames := make(map[string]bool) 79 for _, spec := range specs { 80 validSpecNames[spec.Name] = true 81 } 82 for tunnelProtocol, specNames := range manipulations { 83 if tunnelProtocol != protocol.TUNNEL_PROTOCOLS_ALL { 84 if !protocol.TunnelProtocolMayUseServerPacketManipulation(tunnelProtocol) { 85 return errors.TraceNew("invalid tunnel protocol for packet manipulation") 86 } 87 } 88 89 for _, specName := range specNames { 90 if ok, _ := validSpecNames[specName]; !ok { 91 return errors.Tracef("invalid spec name: %s", specName) 92 } 93 } 94 } 95 return nil 96 }