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

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-04-12 07:04:37 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20140412070437-jub6rry6bdr9rqw1
Tags: 1.18.1-0ubuntu1
* New upstream point release, including fixes for:
  - Upgrading juju 1.16.6 -> 1.18.x fails (LP: #1299802).
  - Peer relation disappears during juju-upgrade (LP: #1303697).
  - public-address of units changes to internal bridge post upgrade
    (LP: #1303735).
  - Unable to deploy local charms without series (LP: #1303880).
  - juju scp no longer allows multiple extra arguments to be passed
    (LP: #1306208).
  - juju cannot downgrade to same major.minor version with earlier
    patch number (LP: #1306296).

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