dgramopt.go raw
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package ipv6
6
7 import (
8 "net"
9
10 "golang.org/x/net/bpf"
11 )
12
13 // MulticastHopLimit returns the hop limit field value for outgoing
14 // multicast packets.
15 func (c *dgramOpt) MulticastHopLimit() (int, error) {
16 if !c.ok() {
17 return 0, errInvalidConn
18 }
19 so, ok := sockOpts[ssoMulticastHopLimit]
20 if !ok {
21 return 0, errNotImplemented
22 }
23 return so.GetInt(c.Conn)
24 }
25
26 // SetMulticastHopLimit sets the hop limit field value for future
27 // outgoing multicast packets.
28 func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
29 if !c.ok() {
30 return errInvalidConn
31 }
32 so, ok := sockOpts[ssoMulticastHopLimit]
33 if !ok {
34 return errNotImplemented
35 }
36 return so.SetInt(c.Conn, hoplim)
37 }
38
39 // MulticastInterface returns the default interface for multicast
40 // packet transmissions.
41 func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
42 if !c.ok() {
43 return nil, errInvalidConn
44 }
45 so, ok := sockOpts[ssoMulticastInterface]
46 if !ok {
47 return nil, errNotImplemented
48 }
49 return so.getMulticastInterface(c.Conn)
50 }
51
52 // SetMulticastInterface sets the default interface for future
53 // multicast packet transmissions.
54 func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
55 if !c.ok() {
56 return errInvalidConn
57 }
58 so, ok := sockOpts[ssoMulticastInterface]
59 if !ok {
60 return errNotImplemented
61 }
62 return so.setMulticastInterface(c.Conn, ifi)
63 }
64
65 // MulticastLoopback reports whether transmitted multicast packets
66 // should be copied and send back to the originator.
67 func (c *dgramOpt) MulticastLoopback() (bool, error) {
68 if !c.ok() {
69 return false, errInvalidConn
70 }
71 so, ok := sockOpts[ssoMulticastLoopback]
72 if !ok {
73 return false, errNotImplemented
74 }
75 on, err := so.GetInt(c.Conn)
76 if err != nil {
77 return false, err
78 }
79 return on == 1, nil
80 }
81
82 // SetMulticastLoopback sets whether transmitted multicast packets
83 // should be copied and send back to the originator.
84 func (c *dgramOpt) SetMulticastLoopback(on bool) error {
85 if !c.ok() {
86 return errInvalidConn
87 }
88 so, ok := sockOpts[ssoMulticastLoopback]
89 if !ok {
90 return errNotImplemented
91 }
92 return so.SetInt(c.Conn, boolint(on))
93 }
94
95 // JoinGroup joins the group address group on the interface ifi.
96 // By default all sources that can cast data to group are accepted.
97 // It's possible to mute and unmute data transmission from a specific
98 // source by using ExcludeSourceSpecificGroup and
99 // IncludeSourceSpecificGroup.
100 // JoinGroup uses the system assigned multicast interface when ifi is
101 // nil, although this is not recommended because the assignment
102 // depends on platforms and sometimes it might require routing
103 // configuration.
104 func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
105 if !c.ok() {
106 return errInvalidConn
107 }
108 so, ok := sockOpts[ssoJoinGroup]
109 if !ok {
110 return errNotImplemented
111 }
112 grp := netAddrToIP16(group)
113 if grp == nil {
114 return errMissingAddress
115 }
116 return so.setGroup(c.Conn, ifi, grp)
117 }
118
119 // LeaveGroup leaves the group address group on the interface ifi
120 // regardless of whether the group is any-source group or
121 // source-specific group.
122 func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
123 if !c.ok() {
124 return errInvalidConn
125 }
126 so, ok := sockOpts[ssoLeaveGroup]
127 if !ok {
128 return errNotImplemented
129 }
130 grp := netAddrToIP16(group)
131 if grp == nil {
132 return errMissingAddress
133 }
134 return so.setGroup(c.Conn, ifi, grp)
135 }
136
137 // JoinSourceSpecificGroup joins the source-specific group comprising
138 // group and source on the interface ifi.
139 // JoinSourceSpecificGroup uses the system assigned multicast
140 // interface when ifi is nil, although this is not recommended because
141 // the assignment depends on platforms and sometimes it might require
142 // routing configuration.
143 func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
144 if !c.ok() {
145 return errInvalidConn
146 }
147 so, ok := sockOpts[ssoJoinSourceGroup]
148 if !ok {
149 return errNotImplemented
150 }
151 grp := netAddrToIP16(group)
152 if grp == nil {
153 return errMissingAddress
154 }
155 src := netAddrToIP16(source)
156 if src == nil {
157 return errMissingAddress
158 }
159 return so.setSourceGroup(c.Conn, ifi, grp, src)
160 }
161
162 // LeaveSourceSpecificGroup leaves the source-specific group on the
163 // interface ifi.
164 func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
165 if !c.ok() {
166 return errInvalidConn
167 }
168 so, ok := sockOpts[ssoLeaveSourceGroup]
169 if !ok {
170 return errNotImplemented
171 }
172 grp := netAddrToIP16(group)
173 if grp == nil {
174 return errMissingAddress
175 }
176 src := netAddrToIP16(source)
177 if src == nil {
178 return errMissingAddress
179 }
180 return so.setSourceGroup(c.Conn, ifi, grp, src)
181 }
182
183 // ExcludeSourceSpecificGroup excludes the source-specific group from
184 // the already joined any-source groups by JoinGroup on the interface
185 // ifi.
186 func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
187 if !c.ok() {
188 return errInvalidConn
189 }
190 so, ok := sockOpts[ssoBlockSourceGroup]
191 if !ok {
192 return errNotImplemented
193 }
194 grp := netAddrToIP16(group)
195 if grp == nil {
196 return errMissingAddress
197 }
198 src := netAddrToIP16(source)
199 if src == nil {
200 return errMissingAddress
201 }
202 return so.setSourceGroup(c.Conn, ifi, grp, src)
203 }
204
205 // IncludeSourceSpecificGroup includes the excluded source-specific
206 // group by ExcludeSourceSpecificGroup again on the interface ifi.
207 func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
208 if !c.ok() {
209 return errInvalidConn
210 }
211 so, ok := sockOpts[ssoUnblockSourceGroup]
212 if !ok {
213 return errNotImplemented
214 }
215 grp := netAddrToIP16(group)
216 if grp == nil {
217 return errMissingAddress
218 }
219 src := netAddrToIP16(source)
220 if src == nil {
221 return errMissingAddress
222 }
223 return so.setSourceGroup(c.Conn, ifi, grp, src)
224 }
225
226 // Checksum reports whether the kernel will compute, store or verify a
227 // checksum for both incoming and outgoing packets. If on is true, it
228 // returns an offset in bytes into the data of where the checksum
229 // field is located.
230 func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
231 if !c.ok() {
232 return false, 0, errInvalidConn
233 }
234 so, ok := sockOpts[ssoChecksum]
235 if !ok {
236 return false, 0, errNotImplemented
237 }
238 offset, err = so.GetInt(c.Conn)
239 if err != nil {
240 return false, 0, err
241 }
242 if offset < 0 {
243 return false, 0, nil
244 }
245 return true, offset, nil
246 }
247
248 // SetChecksum enables the kernel checksum processing. If on is true,
249 // the offset should be an offset in bytes into the data of where the
250 // checksum field is located.
251 func (c *dgramOpt) SetChecksum(on bool, offset int) error {
252 if !c.ok() {
253 return errInvalidConn
254 }
255 so, ok := sockOpts[ssoChecksum]
256 if !ok {
257 return errNotImplemented
258 }
259 if !on {
260 offset = -1
261 }
262 return so.SetInt(c.Conn, offset)
263 }
264
265 // ICMPFilter returns an ICMP filter.
266 func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
267 if !c.ok() {
268 return nil, errInvalidConn
269 }
270 so, ok := sockOpts[ssoICMPFilter]
271 if !ok {
272 return nil, errNotImplemented
273 }
274 return so.getICMPFilter(c.Conn)
275 }
276
277 // SetICMPFilter deploys the ICMP filter.
278 func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
279 if !c.ok() {
280 return errInvalidConn
281 }
282 so, ok := sockOpts[ssoICMPFilter]
283 if !ok {
284 return errNotImplemented
285 }
286 return so.setICMPFilter(c.Conn, f)
287 }
288
289 // SetBPF attaches a BPF program to the connection.
290 //
291 // Only supported on Linux.
292 func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
293 if !c.ok() {
294 return errInvalidConn
295 }
296 so, ok := sockOpts[ssoAttachFilter]
297 if !ok {
298 return errNotImplemented
299 }
300 return so.setBPF(c.Conn, filter)
301 }
302