~ubuntu-branches/ubuntu/saucy/juju-core/saucy-proposed

« back to all changes in this revision

Viewing changes to src/code.google.com/p/go.net/ipv6/control_rfc3542_linux.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-07-11 17:18:27 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130711171827-vjqkg40r0dlf7ys2
Tags: 1.11.2-0ubuntu1
* New upstream release.
* Make juju-core the default juju (LP: #1190634):
  - d/control: Add virtual package juju -> juju-core.
  - d/juju-core.postinst.in: Bump priority of alternatives over that of
    python juju packages.
* Enable for all architectures (LP: #1172505):
  - d/control: Version BD on golang-go to >= 2:1.1.1 to ensure CGO
    support for non-x86 archs, make juju-core Arch: any.
  - d/README.source: Dropped - no longer required.
* d/watch: Updated for new upstream tarball naming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        "os"
 
10
        "syscall"
 
11
        "unsafe"
 
12
)
 
13
 
 
14
const (
 
15
        // See /usr/include/linux/in6.h.
 
16
        syscall_IPV6_RECVPATHMTU = syscall.IPV6_DSTOPTS + 1 + iota
 
17
        syscall_IPV6_PATHMTU
 
18
        syscall_IPV6_DONTFRAG
 
19
)
 
20
 
 
21
const pktinfo = FlagDst | FlagInterface
 
22
 
 
23
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
 
24
        opt.Lock()
 
25
        defer opt.Unlock()
 
26
        if cf&FlagTrafficClass != 0 {
 
27
                if err := setIPv6ReceiveTrafficClass(fd, on); err != nil {
 
28
                        return err
 
29
                }
 
30
                if on {
 
31
                        opt.set(FlagTrafficClass)
 
32
                } else {
 
33
                        opt.clear(FlagTrafficClass)
 
34
                }
 
35
        }
 
36
        if cf&FlagHopLimit != 0 {
 
37
                if err := setIPv6ReceiveHopLimit(fd, on); err != nil {
 
38
                        return err
 
39
                }
 
40
                if on {
 
41
                        opt.set(FlagHopLimit)
 
42
                } else {
 
43
                        opt.clear(FlagHopLimit)
 
44
                }
 
45
        }
 
46
        if cf&pktinfo != 0 {
 
47
                if err := setIPv6ReceivePacketInfo(fd, on); err != nil {
 
48
                        return err
 
49
                }
 
50
                if on {
 
51
                        opt.set(cf & pktinfo)
 
52
                } else {
 
53
                        opt.clear(cf & pktinfo)
 
54
                }
 
55
        }
 
56
        if cf&FlagPathMTU != 0 {
 
57
                if err := setIPv6ReceivePathMTU(fd, on); err != nil {
 
58
                        return err
 
59
                }
 
60
                if on {
 
61
                        opt.set(FlagPathMTU)
 
62
                } else {
 
63
                        opt.clear(FlagPathMTU)
 
64
                }
 
65
        }
 
66
        return nil
 
67
}
 
68
 
 
69
func newControlMessage(opt *rawOpt) (oob []byte) {
 
70
        opt.Lock()
 
71
        defer opt.Unlock()
 
72
        l, off := 0, 0
 
73
        if opt.isset(FlagTrafficClass) {
 
74
                l += syscall.CmsgSpace(4)
 
75
        }
 
76
        if opt.isset(FlagHopLimit) {
 
77
                l += syscall.CmsgSpace(4)
 
78
        }
 
79
        if opt.isset(pktinfo) {
 
80
                l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
 
81
        }
 
82
        if opt.isset(FlagPathMTU) {
 
83
                l += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
 
84
        }
 
85
        if l > 0 {
 
86
                oob = make([]byte, l)
 
87
                if opt.isset(FlagTrafficClass) {
 
88
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
89
                        m.Level = ianaProtocolIPv6
 
90
                        m.Type = syscall.IPV6_RECVTCLASS
 
91
                        m.SetLen(syscall.CmsgLen(4))
 
92
                        off += syscall.CmsgSpace(4)
 
93
                }
 
94
                if opt.isset(FlagHopLimit) {
 
95
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
96
                        m.Level = ianaProtocolIPv6
 
97
                        m.Type = syscall.IPV6_RECVHOPLIMIT
 
98
                        m.SetLen(syscall.CmsgLen(4))
 
99
                        off += syscall.CmsgSpace(4)
 
100
                }
 
101
                if opt.isset(pktinfo) {
 
102
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
103
                        m.Level = ianaProtocolIPv6
 
104
                        m.Type = syscall.IPV6_RECVPKTINFO
 
105
                        m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
 
106
                        off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
 
107
                }
 
108
                if opt.isset(FlagPathMTU) {
 
109
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
110
                        m.Level = ianaProtocolIPv6
 
111
                        m.Type = syscall_IPV6_RECVPATHMTU
 
112
                        m.SetLen(syscall.CmsgLen(syscall.SizeofIPv6MTUInfo))
 
113
                        off += syscall.CmsgSpace(syscall.SizeofIPv6MTUInfo)
 
114
                }
 
115
        }
 
116
        return
 
117
}
 
118
 
 
119
func parseControlMessage(b []byte) (*ControlMessage, error) {
 
120
        if len(b) == 0 {
 
121
                return nil, nil
 
122
        }
 
123
        cmsgs, err := syscall.ParseSocketControlMessage(b)
 
124
        if err != nil {
 
125
                return nil, os.NewSyscallError("parse socket control message", err)
 
126
        }
 
127
        cm := &ControlMessage{}
 
128
        for _, m := range cmsgs {
 
129
                if m.Header.Level != ianaProtocolIPv6 {
 
130
                        continue
 
131
                }
 
132
                switch m.Header.Type {
 
133
                case syscall.IPV6_TCLASS:
 
134
                        cm.TrafficClass = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
 
135
                case syscall.IPV6_HOPLIMIT:
 
136
                        cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
 
137
                case syscall.IPV6_PKTINFO:
 
138
                        pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&m.Data[0]))
 
139
                        cm.Dst = pi.Addr[:]
 
140
                        cm.IfIndex = int(pi.Ifindex)
 
141
                case syscall_IPV6_PATHMTU:
 
142
                        mi := (*syscall.IPv6MTUInfo)(unsafe.Pointer(&m.Data[0]))
 
143
                        cm.Dst = mi.Addr.Addr[:]
 
144
                        cm.IfIndex = int(mi.Addr.Scope_id)
 
145
                        cm.MTU = int(mi.Mtu)
 
146
                }
 
147
        }
 
148
        return cm, nil
 
149
}
 
150
 
 
151
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
 
152
        if cm == nil {
 
153
                return
 
154
        }
 
155
        l, off := 0, 0
 
156
        if cm.TrafficClass > 0 {
 
157
                l += syscall.CmsgSpace(4)
 
158
        }
 
159
        if cm.HopLimit > 0 {
 
160
                l += syscall.CmsgSpace(4)
 
161
        }
 
162
        pion := false
 
163
        if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
 
164
                pion = true
 
165
                l += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
 
166
        }
 
167
        if len(cm.NextHop) == net.IPv6len {
 
168
                l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
 
169
        }
 
170
        if l > 0 {
 
171
                oob = make([]byte, l)
 
172
                if cm.TrafficClass > 0 {
 
173
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
174
                        m.Level = ianaProtocolIPv6
 
175
                        m.Type = syscall.IPV6_TCLASS
 
176
                        m.SetLen(syscall.CmsgLen(4))
 
177
                        data := oob[off+syscall.CmsgLen(0):]
 
178
                        *(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.TrafficClass)
 
179
                        off += syscall.CmsgSpace(4)
 
180
                }
 
181
                if cm.HopLimit > 0 {
 
182
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
183
                        m.Level = ianaProtocolIPv6
 
184
                        m.Type = syscall.IPV6_HOPLIMIT
 
185
                        m.SetLen(syscall.CmsgLen(4))
 
186
                        data := oob[off+syscall.CmsgLen(0):]
 
187
                        *(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
 
188
                        off += syscall.CmsgSpace(4)
 
189
                }
 
190
                if pion {
 
191
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
192
                        m.Level = ianaProtocolIPv6
 
193
                        m.Type = syscall.IPV6_PKTINFO
 
194
                        m.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
 
195
                        pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
 
196
                        if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
 
197
                                copy(pi.Addr[:], ip)
 
198
                        }
 
199
                        if cm.IfIndex != 0 {
 
200
                                pi.Ifindex = uint32(cm.IfIndex)
 
201
                        }
 
202
                        off += syscall.CmsgSpace(syscall.SizeofInet6Pktinfo)
 
203
                }
 
204
                if len(cm.NextHop) == net.IPv6len {
 
205
                        m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
 
206
                        m.Level = ianaProtocolIPv6
 
207
                        m.Type = syscall.IPV6_NEXTHOP
 
208
                        m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
 
209
                        sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
 
210
                        sa.Family = syscall.AF_INET6
 
211
                        copy(sa.Addr[:], cm.NextHop)
 
212
                        sa.Scope_id = uint32(cm.IfIndex)
 
213
                        off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
 
214
                }
 
215
        }
 
216
        return
 
217
}