github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/tcpip/header/igmp.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package header 16 17 import ( 18 "encoding/binary" 19 "fmt" 20 "time" 21 22 "github.com/nicocha30/gvisor-ligolo/pkg/tcpip" 23 "github.com/nicocha30/gvisor-ligolo/pkg/tcpip/checksum" 24 ) 25 26 // IGMP represents an IGMP header stored in a byte array. 27 type IGMP []byte 28 29 // IGMP implements `Transport`. 30 var _ Transport = (*IGMP)(nil) 31 32 const ( 33 // IGMPMinimumSize is the minimum size of a valid IGMP packet in bytes, 34 // as per RFC 2236, Section 2, Page 2. 35 IGMPMinimumSize = 8 36 37 // IGMPQueryMinimumSize is the minimum size of a valid Membership Query 38 // Message in bytes, as per RFC 2236, Section 2, Page 2. 39 IGMPQueryMinimumSize = 8 40 41 // IGMPReportMinimumSize is the minimum size of a valid Report Message in 42 // bytes, as per RFC 2236, Section 2, Page 2. 43 IGMPReportMinimumSize = 8 44 45 // IGMPLeaveMessageMinimumSize is the minimum size of a valid Leave Message 46 // in bytes, as per RFC 2236, Section 2, Page 2. 47 IGMPLeaveMessageMinimumSize = 8 48 49 // IGMPTTL is the TTL for all IGMP messages, as per RFC 2236, Section 3, Page 50 // 3. 51 IGMPTTL = 1 52 53 // igmpTypeOffset defines the offset of the type field in an IGMP message. 54 igmpTypeOffset = 0 55 56 // igmpMaxRespTimeOffset defines the offset of the MaxRespTime field in an 57 // IGMP message. 58 igmpMaxRespTimeOffset = 1 59 60 // igmpChecksumOffset defines the offset of the checksum field in an IGMP 61 // message. 62 igmpChecksumOffset = 2 63 64 // igmpGroupAddressOffset defines the offset of the Group Address field in an 65 // IGMP message. 66 igmpGroupAddressOffset = 4 67 68 // IGMPProtocolNumber is IGMP's transport protocol number. 69 IGMPProtocolNumber tcpip.TransportProtocolNumber = 2 70 ) 71 72 // IGMPType is the IGMP type field as per RFC 2236. 73 type IGMPType byte 74 75 // Values for the IGMP Type described in RFC 2236 Section 2.1, Page 2. 76 // Descriptions below come from there. 77 const ( 78 // IGMPMembershipQuery indicates that the message type is Membership Query. 79 // "There are two sub-types of Membership Query messages: 80 // - General Query, used to learn which groups have members on an 81 // attached network. 82 // - Group-Specific Query, used to learn if a particular group 83 // has any members on an attached network. 84 // These two messages are differentiated by the Group Address, as 85 // described in section 1.4 ." 86 IGMPMembershipQuery IGMPType = 0x11 87 // IGMPv1MembershipReport indicates that the message is a Membership Report 88 // generated by a host using the IGMPv1 protocol: "an additional type of 89 // message, for backwards-compatibility with IGMPv1" 90 IGMPv1MembershipReport IGMPType = 0x12 91 // IGMPv2MembershipReport indicates that the Message type is a Membership 92 // Report generated by a host using the IGMPv2 protocol. 93 IGMPv2MembershipReport IGMPType = 0x16 94 // IGMPLeaveGroup indicates that the message type is a Leave Group 95 // notification message. 96 IGMPLeaveGroup IGMPType = 0x17 97 // IGMPv3MembershipReport indicates that the message type is a IGMPv3 report. 98 IGMPv3MembershipReport IGMPType = 0x22 99 ) 100 101 // Type is the IGMP type field. 102 func (b IGMP) Type() IGMPType { return IGMPType(b[igmpTypeOffset]) } 103 104 // SetType sets the IGMP type field. 105 func (b IGMP) SetType(t IGMPType) { b[igmpTypeOffset] = byte(t) } 106 107 // MaxRespTime gets the MaxRespTimeField. This is meaningful only in Membership 108 // Query messages, in other cases it is set to 0 by the sender and ignored by 109 // the receiver. 110 func (b IGMP) MaxRespTime() time.Duration { 111 // As per RFC 2236 section 2.2, 112 // 113 // The Max Response Time field is meaningful only in Membership Query 114 // messages, and specifies the maximum allowed time before sending a 115 // responding report in units of 1/10 second. In all other messages, it 116 // is set to zero by the sender and ignored by receivers. 117 return DecisecondToDuration(uint16(b[igmpMaxRespTimeOffset])) 118 } 119 120 // SetMaxRespTime sets the MaxRespTimeField. 121 func (b IGMP) SetMaxRespTime(m byte) { b[igmpMaxRespTimeOffset] = m } 122 123 // Checksum is the IGMP checksum field. 124 func (b IGMP) Checksum() uint16 { 125 return binary.BigEndian.Uint16(b[igmpChecksumOffset:]) 126 } 127 128 // SetChecksum sets the IGMP checksum field. 129 func (b IGMP) SetChecksum(checksum uint16) { 130 binary.BigEndian.PutUint16(b[igmpChecksumOffset:], checksum) 131 } 132 133 // GroupAddress gets the Group Address field. 134 func (b IGMP) GroupAddress() tcpip.Address { 135 return tcpip.AddrFrom4([4]byte(b[igmpGroupAddressOffset:][:IPv4AddressSize])) 136 } 137 138 // SetGroupAddress sets the Group Address field. 139 func (b IGMP) SetGroupAddress(address tcpip.Address) { 140 addrBytes := address.As4() 141 if n := copy(b[igmpGroupAddressOffset:], addrBytes[:]); n != IPv4AddressSize { 142 panic(fmt.Sprintf("copied %d bytes, expected %d", n, IPv4AddressSize)) 143 } 144 } 145 146 // SourcePort implements Transport.SourcePort. 147 func (IGMP) SourcePort() uint16 { 148 return 0 149 } 150 151 // DestinationPort implements Transport.DestinationPort. 152 func (IGMP) DestinationPort() uint16 { 153 return 0 154 } 155 156 // SetSourcePort implements Transport.SetSourcePort. 157 func (IGMP) SetSourcePort(uint16) { 158 } 159 160 // SetDestinationPort implements Transport.SetDestinationPort. 161 func (IGMP) SetDestinationPort(uint16) { 162 } 163 164 // Payload implements Transport.Payload. 165 func (IGMP) Payload() []byte { 166 return nil 167 } 168 169 // IGMPCalculateChecksum calculates the IGMP checksum over the provided IGMP 170 // header. 171 func IGMPCalculateChecksum(h IGMP) uint16 { 172 // The header contains a checksum itself, set it aside to avoid checksumming 173 // the checksum and replace it afterwards. 174 existingXsum := h.Checksum() 175 h.SetChecksum(0) 176 xsum := ^checksum.Checksum(h, 0) 177 h.SetChecksum(existingXsum) 178 return xsum 179 } 180 181 // DecisecondToDuration converts a value representing deci-seconds to a 182 // time.Duration. 183 func DecisecondToDuration(ds uint16) time.Duration { 184 return time.Duration(ds) * time.Second / 10 185 }