vendor: add d2g/dhcp4server
This commit is contained in:
parent
461d433911
commit
26ef6e312d
16
Godeps/Godeps.json
generated
16
Godeps/Godeps.json
generated
@ -63,6 +63,10 @@
|
|||||||
"ImportPath": "github.com/d2g/dhcp4client",
|
"ImportPath": "github.com/d2g/dhcp4client",
|
||||||
"Rev": "bed07e1bc5b85f69c6f0fd73393aa35ec68ed892"
|
"Rev": "bed07e1bc5b85f69c6f0fd73393aa35ec68ed892"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/d2g/dhcp4server",
|
||||||
|
"Rev": "1b74244053681c90de5cf1af3d6b5c93b74e3abb"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/j-keck/arping",
|
"ImportPath": "github.com/j-keck/arping",
|
||||||
"Rev": "2cf9dc699c5640a7e2c81403a44127bf28033600"
|
"Rev": "2cf9dc699c5640a7e2c81403a44127bf28033600"
|
||||||
@ -234,6 +238,18 @@
|
|||||||
"ImportPath": "github.com/vishvananda/netns",
|
"ImportPath": "github.com/vishvananda/netns",
|
||||||
"Rev": "54f0e4339ce73702a0607f49922aaa1e749b418d"
|
"Rev": "54f0e4339ce73702a0607f49922aaa1e749b418d"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/bpf",
|
||||||
|
"Rev": "e90d6d0afc4c315a0d87a568ae68577cc15149a0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/internal/iana",
|
||||||
|
"Rev": "e90d6d0afc4c315a0d87a568ae68577cc15149a0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/ipv4",
|
||||||
|
"Rev": "e90d6d0afc4c315a0d87a568ae68577cc15149a0"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/sys/unix",
|
"ImportPath": "golang.org/x/sys/unix",
|
||||||
"Rev": "076b546753157f758b316e59bcb51e6807c04057"
|
"Rev": "076b546753157f758b316e59bcb51e6807c04057"
|
||||||
|
354
vendor/github.com/d2g/dhcp4server/LICENSE
generated
vendored
Normal file
354
vendor/github.com/d2g/dhcp4server/LICENSE
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
1.1. “Contributor”
|
||||||
|
|
||||||
|
means each individual or legal entity that creates, contributes to the
|
||||||
|
creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. “Contributor Version”
|
||||||
|
|
||||||
|
means the combination of the Contributions of others (if any) used by a
|
||||||
|
Contributor and that particular Contributor’s Contribution.
|
||||||
|
|
||||||
|
1.3. “Contribution”
|
||||||
|
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. “Covered Software”
|
||||||
|
|
||||||
|
means Source Code Form to which the initial Contributor has attached the
|
||||||
|
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||||
|
Modifications of such Source Code Form, in each case including portions
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
1.5. “Incompatible With Secondary Licenses”
|
||||||
|
means
|
||||||
|
|
||||||
|
a. that the initial Contributor has attached the notice described in
|
||||||
|
Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
b. that the Covered Software was made available under the terms of version
|
||||||
|
1.1 or earlier of the License, but not also under the terms of a
|
||||||
|
Secondary License.
|
||||||
|
|
||||||
|
1.6. “Executable Form”
|
||||||
|
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. “Larger Work”
|
||||||
|
|
||||||
|
means a work that combines Covered Software with other material, in a separate
|
||||||
|
file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. “License”
|
||||||
|
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. “Licensable”
|
||||||
|
|
||||||
|
means having the right to grant, to the maximum extent possible, whether at the
|
||||||
|
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||||
|
this License.
|
||||||
|
|
||||||
|
1.10. “Modifications”
|
||||||
|
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
a. any file in Source Code Form that results from an addition to, deletion
|
||||||
|
from, or modification of the contents of Covered Software; or
|
||||||
|
|
||||||
|
b. any new file in Source Code Form that contains any Covered Software.
|
||||||
|
|
||||||
|
1.11. “Patent Claims” of a Contributor
|
||||||
|
|
||||||
|
means any patent claim(s), including without limitation, method, process,
|
||||||
|
and apparatus claims, in any patent Licensable by such Contributor that
|
||||||
|
would be infringed, but for the grant of the License, by the making,
|
||||||
|
using, selling, offering for sale, having made, import, or transfer of
|
||||||
|
either its Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
1.12. “Secondary License”
|
||||||
|
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||||
|
General Public License, Version 2.1, the GNU Affero General Public
|
||||||
|
License, Version 3.0, or any later versions of those licenses.
|
||||||
|
|
||||||
|
1.13. “Source Code Form”
|
||||||
|
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. “You” (or “Your”)
|
||||||
|
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, “You” includes any entity that controls, is
|
||||||
|
controlled by, or is under common control with You. For purposes of this
|
||||||
|
definition, “control” means (a) the power, direct or indirect, to cause
|
||||||
|
the direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||||
|
outstanding shares or beneficial ownership of such entity.
|
||||||
|
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
a. under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or as
|
||||||
|
part of a Larger Work; and
|
||||||
|
|
||||||
|
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||||
|
sale, have made, import, and otherwise transfer either its Contributions
|
||||||
|
or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||||
|
effective for each Contribution on the date the Contributor first distributes
|
||||||
|
such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under this
|
||||||
|
License. No additional rights or licenses will be implied from the distribution
|
||||||
|
or licensing of Covered Software under this License. Notwithstanding Section
|
||||||
|
2.1(b) above, no patent license is granted by a Contributor:
|
||||||
|
|
||||||
|
a. for any code that a Contributor has removed from Covered Software; or
|
||||||
|
|
||||||
|
b. for infringements caused by: (i) Your and any other third party’s
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks, or
|
||||||
|
logos of any Contributor (except as may be necessary to comply with the
|
||||||
|
notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this License
|
||||||
|
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||||
|
under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its Contributions
|
||||||
|
are its original creation(s) or it has sufficient rights to grant the
|
||||||
|
rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under applicable
|
||||||
|
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||||
|
Section 2.1.
|
||||||
|
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under the
|
||||||
|
terms of this License. You must inform recipients that the Source Code Form
|
||||||
|
of the Covered Software is governed by the terms of this License, and how
|
||||||
|
they can obtain a copy of this License. You may not attempt to alter or
|
||||||
|
restrict the recipients’ rights in the Source Code Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
a. such Covered Software must also be made available in Source Code Form,
|
||||||
|
as described in Section 3.1, and You must inform recipients of the
|
||||||
|
Executable Form how they can obtain a copy of such Source Code Form by
|
||||||
|
reasonable means in a timely manner, at a charge no more than the cost
|
||||||
|
of distribution to the recipient; and
|
||||||
|
|
||||||
|
b. You may distribute such Executable Form under the terms of this License,
|
||||||
|
or sublicense it under different terms, provided that the license for
|
||||||
|
the Executable Form does not attempt to limit or alter the recipients’
|
||||||
|
rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for the
|
||||||
|
Covered Software. If the Larger Work is a combination of Covered Software
|
||||||
|
with a work governed by one or more Secondary Licenses, and the Covered
|
||||||
|
Software is not Incompatible With Secondary Licenses, this License permits
|
||||||
|
You to additionally distribute such Covered Software under the terms of
|
||||||
|
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||||
|
their option, further distribute the Covered Software under the terms of
|
||||||
|
either this License or such Secondary License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices (including
|
||||||
|
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||||
|
of liability) contained within the Source Code Form of the Covered
|
||||||
|
Software, except that You may alter any license notices to the extent
|
||||||
|
required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||||
|
of any Contributor. You must make it absolutely clear that any such
|
||||||
|
warranty, support, indemnity, or liability obligation is offered by You
|
||||||
|
alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this License
|
||||||
|
with respect to some or all of the Covered Software due to statute, judicial
|
||||||
|
order, or regulation then You must: (a) comply with the terms of this License
|
||||||
|
to the maximum extent possible; and (b) describe the limitations and the code
|
||||||
|
they affect. Such description must be placed in a text file included with all
|
||||||
|
distributions of the Covered Software under this License. Except to the
|
||||||
|
extent prohibited by statute or regulation, such description must be
|
||||||
|
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||||
|
understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically if You
|
||||||
|
fail to comply with any of its terms. However, if You become compliant,
|
||||||
|
then the rights granted under this License from a particular Contributor
|
||||||
|
are reinstated (a) provisionally, unless and until such Contributor
|
||||||
|
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||||
|
if such Contributor fails to notify You of the non-compliance by some
|
||||||
|
reasonable means prior to 60 days after You have come back into compliance.
|
||||||
|
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||||
|
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||||
|
some reasonable means, this is the first time You have received notice of
|
||||||
|
non-compliance with this License from such Contributor, and You become
|
||||||
|
compliant prior to 30 days after Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||||
|
and cross-claims) alleging that a Contributor Version directly or
|
||||||
|
indirectly infringes any patent, then the rights granted to You by any and
|
||||||
|
all Contributors for the Covered Software under Section 2.1 of this License
|
||||||
|
shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||||
|
license agreements (excluding distributors and resellers) which have been
|
||||||
|
validly granted by You or Your distributors under this License prior to
|
||||||
|
termination shall survive termination.
|
||||||
|
|
||||||
|
6. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Covered Software is provided under this License on an “as is” basis, without
|
||||||
|
warranty of any kind, either expressed, implied, or statutory, including,
|
||||||
|
without limitation, warranties that the Covered Software is free of defects,
|
||||||
|
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||||
|
risk as to the quality and performance of the Covered Software is with You.
|
||||||
|
Should any Covered Software prove defective in any respect, You (not any
|
||||||
|
Contributor) assume the cost of any necessary servicing, repair, or
|
||||||
|
correction. This disclaimer of warranty constitutes an essential part of this
|
||||||
|
License. No use of any Covered Software is authorized under this License
|
||||||
|
except under this disclaimer.
|
||||||
|
|
||||||
|
7. Limitation of Liability
|
||||||
|
|
||||||
|
Under no circumstances and under no legal theory, whether tort (including
|
||||||
|
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||||
|
distributes Covered Software as permitted above, be liable to You for any
|
||||||
|
direct, indirect, special, incidental, or consequential damages of any
|
||||||
|
character including, without limitation, damages for lost profits, loss of
|
||||||
|
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses, even if such party shall have been
|
||||||
|
informed of the possibility of such damages. This limitation of liability
|
||||||
|
shall not apply to liability for death or personal injury resulting from such
|
||||||
|
party’s negligence to the extent applicable law prohibits such limitation.
|
||||||
|
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||||
|
consequential damages, so this exclusion and limitation may not apply to You.
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the courts of
|
||||||
|
a jurisdiction where the defendant maintains its principal place of business
|
||||||
|
and such litigation shall be governed by laws of that jurisdiction, without
|
||||||
|
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||||
|
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject matter
|
||||||
|
hereof. If any provision of this License is held to be unenforceable, such
|
||||||
|
provision shall be reformed only to the extent necessary to make it
|
||||||
|
enforceable. Any law or regulation which provides that the language of a
|
||||||
|
contract shall be construed against the drafter shall not be used to construe
|
||||||
|
this License against a Contributor.
|
||||||
|
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version of
|
||||||
|
the License under which You originally received the Covered Software, or
|
||||||
|
under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a modified
|
||||||
|
version of this License if you rename the license and remove any
|
||||||
|
references to the name of the license steward (except to note that such
|
||||||
|
modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular file, then
|
||||||
|
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||||
|
directory) where a recipient would be likely to look for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||||
|
|
||||||
|
This Source Code Form is “Incompatible
|
||||||
|
With Secondary Licenses”, as defined by
|
||||||
|
the Mozilla Public License, v. 2.0.
|
||||||
|
|
4
vendor/github.com/d2g/dhcp4server/README.md
generated
vendored
Normal file
4
vendor/github.com/d2g/dhcp4server/README.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
dhcp4server [](http://godoc.org/github.com/d2g/dhcp4server) [](https://coveralls.io/r/d2g/dhcp4server) [](https://codeship.com/projects/59804)
|
||||||
|
===========
|
||||||
|
|
||||||
|
DHCP Server
|
95
vendor/github.com/d2g/dhcp4server/leasepool/lease.go
generated
vendored
Normal file
95
vendor/github.com/d2g/dhcp4server/leasepool/lease.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package leasepool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LeaseStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Free LeaseStatus = 0
|
||||||
|
Reserved LeaseStatus = 1
|
||||||
|
Active LeaseStatus = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Lease struct {
|
||||||
|
IP net.IP //The IP of the Lease
|
||||||
|
Status LeaseStatus //Are Reserved, Active or Free
|
||||||
|
MACAddress net.HardwareAddr //Mac Address of the Device
|
||||||
|
Hostname string //Hostname From option 12
|
||||||
|
Expiry time.Time //Expiry Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this Lease) MarshalJSON() ([]byte, error) {
|
||||||
|
stringMarshal := struct {
|
||||||
|
IP string
|
||||||
|
Status int
|
||||||
|
MACAddress string
|
||||||
|
Hostname string
|
||||||
|
Expiry time.Time
|
||||||
|
}{
|
||||||
|
(this.IP.String()),
|
||||||
|
int(this.Status),
|
||||||
|
(this.MACAddress.String()),
|
||||||
|
this.Hostname,
|
||||||
|
this.Expiry,
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(stringMarshal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Lease) UnmarshalJSON(data []byte) error {
|
||||||
|
stringUnMarshal := struct {
|
||||||
|
IP string
|
||||||
|
Status int
|
||||||
|
MACAddress string
|
||||||
|
Hostname string
|
||||||
|
Expiry time.Time
|
||||||
|
}{}
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, &stringUnMarshal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
this.IP = net.ParseIP(stringUnMarshal.IP)
|
||||||
|
this.Status = LeaseStatus(stringUnMarshal.Status)
|
||||||
|
if stringUnMarshal.MACAddress != "" {
|
||||||
|
this.MACAddress, err = net.ParseMAC(stringUnMarshal.MACAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Hostname = stringUnMarshal.Hostname
|
||||||
|
this.Expiry = stringUnMarshal.Expiry
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this Lease) Equal(other Lease) bool {
|
||||||
|
if !this.IP.Equal(other.IP) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(this.Status) != int(other.Status) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.MACAddress.String() != other.MACAddress.String() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.Hostname != other.Hostname {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !this.Expiry.Equal(other.Expiry) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
51
vendor/github.com/d2g/dhcp4server/leasepool/lease_test.go
generated
vendored
Normal file
51
vendor/github.com/d2g/dhcp4server/leasepool/lease_test.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package leasepool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Leases are Marshalled and Unmarshalled for storage.
|
||||||
|
* I JSON Marshal these for gvklite
|
||||||
|
*/
|
||||||
|
func TestMarshaling(test *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
startLease := Lease{}
|
||||||
|
startLease.IP = net.IPv4(192, 168, 0, 1)
|
||||||
|
startLease.Hostname = "ExampleHostname"
|
||||||
|
startLease.Status = Active
|
||||||
|
startLease.Expiry = time.Now()
|
||||||
|
startLease.MACAddress, err = net.ParseMAC("01:23:45:67:89:ab")
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Parsing Mac Address:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
byteStartLease, err := json.Marshal(startLease)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Marshaling to JSON:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("StartLease As JSON:" + string(byteStartLease))
|
||||||
|
|
||||||
|
endLease := Lease{}
|
||||||
|
err = json.Unmarshal(byteStartLease, &endLease)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Unmarshaling to JSON:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Logf("End Lease Object:%v\n", endLease)
|
||||||
|
|
||||||
|
if !startLease.Equal(endLease) {
|
||||||
|
byteEndLease, err := json.Marshal(endLease)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Can't Marshal End Lease For Debuging:" + err.Error())
|
||||||
|
}
|
||||||
|
test.Log("End Lease as JSON:" + string(byteEndLease))
|
||||||
|
test.Error("Starting Lease Doesn't Match End Lease")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
vendor/github.com/d2g/dhcp4server/leasepool/leasepool.go
generated
vendored
Normal file
49
vendor/github.com/d2g/dhcp4server/leasepool/leasepool.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package leasepool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lease.IP is the Key.
|
||||||
|
*/
|
||||||
|
type LeasePool interface {
|
||||||
|
//Add A Lease To The Pool
|
||||||
|
AddLease(Lease) error
|
||||||
|
|
||||||
|
//Remove
|
||||||
|
RemoveLease(net.IP) error
|
||||||
|
|
||||||
|
//Remove All Leases from the Pool (Required for Persistant LeaseManagers)
|
||||||
|
PurgeLeases() error
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the Lease
|
||||||
|
* -Found
|
||||||
|
* -Copy Of the Lease
|
||||||
|
* -Any Error
|
||||||
|
*/
|
||||||
|
GetLease(net.IP) (bool, Lease, error)
|
||||||
|
|
||||||
|
//Get the lease already in use by that hardware address.
|
||||||
|
GetLeaseForHardwareAddress(net.HardwareAddr) (bool, Lease, error)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -Lease Available
|
||||||
|
* -Lease
|
||||||
|
* -Error
|
||||||
|
*/
|
||||||
|
GetNextFreeLease() (bool, Lease, error)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return All Leases
|
||||||
|
*/
|
||||||
|
GetLeases() ([]Lease, error)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update Lease
|
||||||
|
* - Has Updated
|
||||||
|
* - Error
|
||||||
|
*/
|
||||||
|
UpdateLease(Lease) (bool, error)
|
||||||
|
}
|
150
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool.go
generated
vendored
Normal file
150
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package memorypool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"github.com/d2g/dhcp4server/leasepool"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MemoryPool struct {
|
||||||
|
pool []leasepool.Lease
|
||||||
|
poolLock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add A Lease To The Pool
|
||||||
|
func (t *MemoryPool) AddLease(newLease leasepool.Lease) error {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
if t.pool == nil {
|
||||||
|
t.pool = make([]leasepool.Lease, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range t.pool {
|
||||||
|
if t.pool[i].IP.Equal(newLease.IP) {
|
||||||
|
//Lease Already Exists In Pool
|
||||||
|
return errors.New("Error: Lease IP \"" + newLease.IP.String() + "\" alreay exists in Pool")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pool = append([]leasepool.Lease{newLease}, t.pool...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove a Lease From The Pool
|
||||||
|
func (t *MemoryPool) RemoveLease(leaseIP net.IP) error {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
for i := range t.pool {
|
||||||
|
if t.pool[i].IP.Equal(leaseIP) {
|
||||||
|
|
||||||
|
//Move the Last Element to This Position.
|
||||||
|
t.pool[i] = t.pool[len(t.pool)-1]
|
||||||
|
|
||||||
|
//Shortern the Pool By One.
|
||||||
|
t.pool = t.pool[0:(len(t.pool) - 1)]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("Error: Lease IP \"" + leaseIP.String() + "\" Is Not In The Pool")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove All Leases from the Pool (Required for Persistant LeaseManagers)
|
||||||
|
func (t *MemoryPool) PurgeLeases() error {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
t.pool = nil
|
||||||
|
t.pool = make([]leasepool.Lease, 0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the Lease
|
||||||
|
* -Found
|
||||||
|
* -Copy Of the Lease
|
||||||
|
* -Any Error
|
||||||
|
*/
|
||||||
|
func (t *MemoryPool) GetLease(leaseIP net.IP) (bool, leasepool.Lease, error) {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
for i := range t.pool {
|
||||||
|
if t.pool[i].IP.Equal(leaseIP) {
|
||||||
|
return true, t.pool[i], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, leasepool.Lease{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the lease already in use by that hardware address.
|
||||||
|
func (t *MemoryPool) GetLeaseForHardwareAddress(macAddress net.HardwareAddr) (bool, leasepool.Lease, error) {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
for i := range t.pool {
|
||||||
|
if bytes.Equal(t.pool[i].MACAddress, macAddress) {
|
||||||
|
return true, t.pool[i], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, leasepool.Lease{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -Lease Available
|
||||||
|
* -Lease
|
||||||
|
* -Error
|
||||||
|
*/
|
||||||
|
func (t *MemoryPool) GetNextFreeLease() (bool, leasepool.Lease, error) {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
//Loop Through the elements backwards.
|
||||||
|
for i := (len(t.pool) - 1); i >= 0; i-- {
|
||||||
|
//If the Lease Is Free
|
||||||
|
if t.pool[i].Status == leasepool.Free {
|
||||||
|
//Take the Element
|
||||||
|
iLease := t.pool[i]
|
||||||
|
//Shrink the Pool By 1
|
||||||
|
t.pool = t.pool[:(len(t.pool) - 1)]
|
||||||
|
//Place the Lease At the Begining (This saves us having some sort of counter...)
|
||||||
|
t.pool = append([]leasepool.Lease{iLease}, t.pool...)
|
||||||
|
return true, iLease, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, leasepool.Lease{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return All Leases
|
||||||
|
*/
|
||||||
|
func (t *MemoryPool) GetLeases() ([]leasepool.Lease, error) {
|
||||||
|
return t.pool, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update Lease
|
||||||
|
* - Has Updated
|
||||||
|
* - Error
|
||||||
|
*/
|
||||||
|
func (t *MemoryPool) UpdateLease(lease leasepool.Lease) (bool, error) {
|
||||||
|
t.poolLock.Lock()
|
||||||
|
defer t.poolLock.Unlock()
|
||||||
|
|
||||||
|
for i := range t.pool {
|
||||||
|
if t.pool[i].IP.Equal(lease.IP) {
|
||||||
|
|
||||||
|
t.pool[i].MACAddress = lease.MACAddress
|
||||||
|
t.pool[i].Hostname = lease.Hostname
|
||||||
|
t.pool[i].Expiry = lease.Expiry
|
||||||
|
t.pool[i].Status = lease.Status
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
51
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool_test.go
generated
vendored
Normal file
51
vendor/github.com/d2g/dhcp4server/leasepool/memorypool/memorypool_test.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package memorypool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/d2g/dhcp4"
|
||||||
|
"github.com/d2g/dhcp4server/leasepool"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLeaseCycle(test *testing.T) {
|
||||||
|
myMemoryLeasePool := MemoryPool{}
|
||||||
|
|
||||||
|
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||||
|
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||||
|
for i := 0; i < 30; i++ {
|
||||||
|
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Creating Lease:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 30; i++ {
|
||||||
|
hasLease, iLease, err := myMemoryLeasePool.GetNextFreeLease()
|
||||||
|
if err != nil || !hasLease {
|
||||||
|
test.Error("Error Getting Lease:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).Equal(iLease.IP) {
|
||||||
|
test.Error("Expected Lease:" + dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).String() + " Received:" + iLease.IP.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSingleLease(test *testing.T) {
|
||||||
|
myMemoryLeasePool := MemoryPool{}
|
||||||
|
|
||||||
|
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 5), 0)})
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Creating Lease:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
hasLease, iLease, err := myMemoryLeasePool.GetNextFreeLease()
|
||||||
|
if err != nil || !hasLease {
|
||||||
|
test.Error("Error Getting Lease:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dhcp4.IPAdd(net.IPv4(192, 168, 1, 5), 0).Equal(iLease.IP) {
|
||||||
|
test.Error("Expected Lease:" + dhcp4.IPAdd(net.IPv4(192, 168, 1, 5), 0).String() + " Received:" + iLease.IP.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
572
vendor/github.com/d2g/dhcp4server/server.go
generated
vendored
Normal file
572
vendor/github.com/d2g/dhcp4server/server.go
generated
vendored
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
package dhcp4server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/d2g/dhcp4"
|
||||||
|
"github.com/d2g/dhcp4server/leasepool"
|
||||||
|
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The DHCP Server Structure
|
||||||
|
*/
|
||||||
|
type Server struct {
|
||||||
|
//Configuration Options
|
||||||
|
ip net.IP //The IP Address We Tell Clients The Server Is On.
|
||||||
|
defaultGateway net.IP //The Default Gateway Address
|
||||||
|
dnsServers []net.IP //DNS Servers
|
||||||
|
subnetMask net.IP //ie. 255.255.255.0
|
||||||
|
leaseDuration time.Duration //Number of Seconds
|
||||||
|
ignoreIPs []net.IP //Slice of IP's that should be ignored by the Server.
|
||||||
|
ignoreHardwareAddress []net.HardwareAddr //Slice of Hardware Addresses we should ignore.
|
||||||
|
|
||||||
|
//Local Address
|
||||||
|
laddr net.UDPAddr
|
||||||
|
|
||||||
|
//Remote address
|
||||||
|
raddr net.UDPAddr
|
||||||
|
|
||||||
|
//LeasePool
|
||||||
|
leasePool leasepool.LeasePool //Lease Pool Manager
|
||||||
|
|
||||||
|
//Used to Gracefully Close the Server
|
||||||
|
shutdownLock sync.Mutex
|
||||||
|
shutdown bool
|
||||||
|
//Listeners & Response Connection.
|
||||||
|
connection *ipv4.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create A New Server
|
||||||
|
func New(ip net.IP, l leasepool.LeasePool, options ...func(*Server) error) (*Server, error) {
|
||||||
|
s := Server{
|
||||||
|
ip: ip,
|
||||||
|
defaultGateway: ip,
|
||||||
|
dnsServers: []net.IP{net.IPv4(208, 67, 222, 222), net.IPv4(208, 67, 220, 220)}, //OPENDNS
|
||||||
|
subnetMask: net.IPv4(255, 255, 255, 0),
|
||||||
|
leaseDuration: 24 * time.Hour,
|
||||||
|
leasePool: l,
|
||||||
|
laddr: net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67},
|
||||||
|
raddr: net.UDPAddr{IP: net.IPv4bcast, Port: 68},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.setOptions(options...)
|
||||||
|
if err != nil {
|
||||||
|
return &s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) setOptions(options ...func(*Server) error) error {
|
||||||
|
for _, opt := range options {
|
||||||
|
if err := opt(s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the Server IP
|
||||||
|
func IP(i net.IP) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.ip = i
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the Default Gateway Address.
|
||||||
|
func DefaultGateway(r net.IP) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.defaultGateway = r
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the DNS servers.
|
||||||
|
func DNSServers(dnss []net.IP) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.dnsServers = dnss
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the Subnet Mask
|
||||||
|
func SubnetMask(m net.IP) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.subnetMask = m
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Lease Duration
|
||||||
|
func LeaseDuration(d time.Duration) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.leaseDuration = d
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Ignore IPs
|
||||||
|
func IgnoreIPs(ips []net.IP) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.ignoreIPs = ips
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Ignore Hardware Addresses
|
||||||
|
func IgnoreHardwareAddresses(h []net.HardwareAddr) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.ignoreHardwareAddress = h
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set LeasePool
|
||||||
|
func LeasePool(p leasepool.LeasePool) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.leasePool = p
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set The Local Address
|
||||||
|
func SetLocalAddr(a net.UDPAddr) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.laddr = a
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set The Remote Address
|
||||||
|
func SetRemoteAddr(a net.UDPAddr) func(*Server) error {
|
||||||
|
return func(s *Server) error {
|
||||||
|
s.raddr = a
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) shouldShutdown() bool {
|
||||||
|
s.shutdownLock.Lock()
|
||||||
|
defer s.shutdownLock.Unlock()
|
||||||
|
return s.shutdown
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start The DHCP Server
|
||||||
|
*/
|
||||||
|
func (s *Server) ListenAndServe() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
connection, err := net.ListenPacket("udp4", s.laddr.String())
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Debug: Error Returned From ListenPacket On \"%s\" Because of \"%s\"\n", s.laddr.String(), err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.connection = ipv4.NewPacketConn(connection)
|
||||||
|
defer s.connection.Close()
|
||||||
|
|
||||||
|
//We Currently Don't Use this Feature Which is the only bit that is Linux Only.
|
||||||
|
//if err := s.connection.SetControlMessage(ipv4.FlagInterface, true); err != nil {
|
||||||
|
// return err
|
||||||
|
//}
|
||||||
|
|
||||||
|
//Make Our Buffer (Max Buffer is 574) "I believe this 576 size comes from RFC 791" - Random Mailing list quote of the day.
|
||||||
|
buffer := make([]byte, 576)
|
||||||
|
|
||||||
|
log.Println("Trace: DHCP Server Listening.")
|
||||||
|
|
||||||
|
for {
|
||||||
|
ListenForDHCPPackets:
|
||||||
|
if s.shouldShutdown() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set Read Deadline
|
||||||
|
s.connection.SetReadDeadline(time.Now().Add(time.Second))
|
||||||
|
// Read Packet
|
||||||
|
n, control_message, source, err := s.connection.ReadFrom(buffer)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
switch v := err.(type) {
|
||||||
|
case *net.OpError:
|
||||||
|
if v.Timeout() {
|
||||||
|
goto ListenForDHCPPackets
|
||||||
|
}
|
||||||
|
case *net.AddrError:
|
||||||
|
if v.Timeout() {
|
||||||
|
goto ListenForDHCPPackets
|
||||||
|
}
|
||||||
|
case *net.UnknownNetworkError:
|
||||||
|
if v.Timeout() {
|
||||||
|
goto ListenForDHCPPackets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Debug: Unexpect Error from Connection Read From:" + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//We seem to have an issue with undersized packets?
|
||||||
|
if n < 240 {
|
||||||
|
log.Printf("Error: Invalid Packet Size \"%d\" Received:%v\n", n, buffer[:n])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//We should ignore some requests
|
||||||
|
//It shouldn't be possible to ignore IP's because they shouldn't have them as we're the DHCP server.
|
||||||
|
//However, they can have i.e. if you're the client & server :S.
|
||||||
|
for _, ipToIgnore := range s.ignoreIPs {
|
||||||
|
if ipToIgnore.Equal(source.(*net.UDPAddr).IP) {
|
||||||
|
log.Println("Debug: Ignoring DHCP Request From IP:" + ipToIgnore.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packet := dhcp4.Packet(buffer[:n])
|
||||||
|
|
||||||
|
//We can ignore hardware addresses.
|
||||||
|
//Usefull for ignoring a range of hardware addresses
|
||||||
|
for _, hardwareAddressToIgnore := range s.ignoreHardwareAddress {
|
||||||
|
if bytes.Equal(hardwareAddressToIgnore, packet.CHAddr()) {
|
||||||
|
log.Println("Debug: Ignoring DHCP Request From Hardware Address:" + hardwareAddressToIgnore.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Trace: Packet Received ID:%v\n", packet.XId())
|
||||||
|
log.Printf("Trace: Packet Options:%v\n", packet.ParseOptions())
|
||||||
|
log.Printf("Trace: Packet Client IP : %v\n", packet.CIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Your IP : %v\n", packet.YIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Server IP : %v\n", packet.SIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Gateway IP: %v\n", packet.GIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Client Mac: %v\n", packet.CHAddr().String())
|
||||||
|
|
||||||
|
//We need to stop butting in with other servers.
|
||||||
|
if packet.SIAddr().Equal(net.IPv4(0, 0, 0, 0)) || packet.SIAddr().Equal(net.IP{}) || packet.SIAddr().Equal(s.ip) {
|
||||||
|
|
||||||
|
returnPacket, err := s.ServeDHCP(packet)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Debug: Error Serving DHCP:" + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(returnPacket) > 0 {
|
||||||
|
log.Printf("Trace: Packet Returned ID:%v\n", returnPacket.XId())
|
||||||
|
log.Printf("Trace: Packet Options:%v\n", returnPacket.ParseOptions())
|
||||||
|
log.Printf("Trace: Packet Client IP : %v\n", returnPacket.CIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Your IP : %v\n", returnPacket.YIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Server IP : %v\n", returnPacket.SIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Gateway IP: %v\n", returnPacket.GIAddr().String())
|
||||||
|
log.Printf("Trace: Packet Client Mac: %v\n", returnPacket.CHAddr().String())
|
||||||
|
|
||||||
|
_, err = s.connection.WriteTo(returnPacket, control_message, &s.raddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Debug: Error Writing:" + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) ServeDHCP(packet dhcp4.Packet) (dhcp4.Packet, error) {
|
||||||
|
packetOptions := packet.ParseOptions()
|
||||||
|
|
||||||
|
switch dhcp4.MessageType(packetOptions[dhcp4.OptionDHCPMessageType][0]) {
|
||||||
|
case dhcp4.Discover:
|
||||||
|
|
||||||
|
//Discover Received from client
|
||||||
|
//Lets get the lease we're going to send them
|
||||||
|
found, lease, err := s.GetLease(packet)
|
||||||
|
if err != nil {
|
||||||
|
return dhcp4.Packet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
log.Println("Warning: It Looks Like Our Leases Are Depleted...")
|
||||||
|
return dhcp4.Packet{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
offerPacket := s.OfferPacket(packet)
|
||||||
|
offerPacket.SetYIAddr(lease.IP)
|
||||||
|
|
||||||
|
//Sort out the packet options
|
||||||
|
offerPacket.PadToMinSize()
|
||||||
|
|
||||||
|
lease.Status = leasepool.Reserved
|
||||||
|
lease.MACAddress = packet.CHAddr()
|
||||||
|
|
||||||
|
//If the lease expires within the next 5 Mins increase the lease expiary (Giving the Client 5 mins to complete)
|
||||||
|
if lease.Expiry.Before(time.Now().Add(time.Minute * 5)) {
|
||||||
|
lease.Expiry = time.Now().Add(time.Minute * 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packetOptions[dhcp4.OptionHostName] != nil && string(packetOptions[dhcp4.OptionHostName]) != "" {
|
||||||
|
lease.Hostname = string(packetOptions[dhcp4.OptionHostName])
|
||||||
|
}
|
||||||
|
|
||||||
|
updated, err := s.leasePool.UpdateLease(lease)
|
||||||
|
if err != nil {
|
||||||
|
return dhcp4.Packet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !updated {
|
||||||
|
//Unable to reserve lease (It's now active else where maybe?)
|
||||||
|
return dhcp4.Packet{}, errors.New("Unable to Reserve Lease:" + lease.IP.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return offerPacket, nil
|
||||||
|
case dhcp4.Request:
|
||||||
|
//Request Received from client
|
||||||
|
//Lets get the lease we're going to send them
|
||||||
|
found, lease, err := s.GetLease(packet)
|
||||||
|
if err != nil {
|
||||||
|
return dhcp4.Packet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
log.Println("Warning: It Looks Like Our Leases Are Depleted...")
|
||||||
|
return dhcp4.Packet{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the lease is not the one requested We should send a NAK..
|
||||||
|
if len(packetOptions) > 0 && !net.IP(packetOptions[dhcp4.OptionRequestedIPAddress]).Equal(lease.IP) {
|
||||||
|
//NAK
|
||||||
|
declinePacket := s.DeclinePacket(packet)
|
||||||
|
declinePacket.PadToMinSize()
|
||||||
|
|
||||||
|
return declinePacket, nil
|
||||||
|
} else {
|
||||||
|
lease.Status = leasepool.Active
|
||||||
|
lease.MACAddress = packet.CHAddr()
|
||||||
|
|
||||||
|
lease.Expiry = time.Now().Add(s.leaseDuration)
|
||||||
|
|
||||||
|
if packetOptions[dhcp4.OptionHostName] != nil && string(packetOptions[dhcp4.OptionHostName]) != "" {
|
||||||
|
lease.Hostname = string(packetOptions[dhcp4.OptionHostName])
|
||||||
|
}
|
||||||
|
|
||||||
|
updated, err := s.leasePool.UpdateLease(lease)
|
||||||
|
if err != nil {
|
||||||
|
return dhcp4.Packet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
//ACK
|
||||||
|
acknowledgementPacket := s.AcknowledgementPacket(packet)
|
||||||
|
acknowledgementPacket.SetYIAddr(lease.IP)
|
||||||
|
|
||||||
|
//Lease time.
|
||||||
|
acknowledgementPacket.AddOption(dhcp4.OptionIPAddressLeaseTime, dhcp4.OptionsLeaseTime(lease.Expiry.Sub(time.Now())))
|
||||||
|
acknowledgementPacket.PadToMinSize()
|
||||||
|
|
||||||
|
return acknowledgementPacket, nil
|
||||||
|
} else {
|
||||||
|
//NAK
|
||||||
|
declinePacket := s.DeclinePacket(packet)
|
||||||
|
declinePacket.PadToMinSize()
|
||||||
|
|
||||||
|
return declinePacket, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case dhcp4.Decline:
|
||||||
|
//Decline from the client:
|
||||||
|
log.Printf("Debug: Decline Message:%v\n", packet)
|
||||||
|
|
||||||
|
case dhcp4.Release:
|
||||||
|
//Decline from the client:
|
||||||
|
log.Printf("Debug: Release Message:%v\n", packet)
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Printf("Debug: Unexpected Packet Type:%v\n", dhcp4.MessageType(packetOptions[dhcp4.OptionDHCPMessageType][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return dhcp4.Packet{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create DHCP Offer Packet
|
||||||
|
*/
|
||||||
|
func (s *Server) OfferPacket(discoverPacket dhcp4.Packet) dhcp4.Packet {
|
||||||
|
|
||||||
|
offerPacket := dhcp4.NewPacket(dhcp4.BootReply)
|
||||||
|
offerPacket.SetXId(discoverPacket.XId())
|
||||||
|
offerPacket.SetFlags(discoverPacket.Flags())
|
||||||
|
|
||||||
|
offerPacket.SetCHAddr(discoverPacket.CHAddr())
|
||||||
|
offerPacket.SetGIAddr(discoverPacket.GIAddr())
|
||||||
|
offerPacket.SetSecs(discoverPacket.Secs())
|
||||||
|
|
||||||
|
//53
|
||||||
|
offerPacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.Offer)})
|
||||||
|
//54
|
||||||
|
offerPacket.AddOption(dhcp4.OptionServerIdentifier, s.ip.To4())
|
||||||
|
//51
|
||||||
|
offerPacket.AddOption(dhcp4.OptionIPAddressLeaseTime, dhcp4.OptionsLeaseTime(s.leaseDuration))
|
||||||
|
|
||||||
|
//Other options go in requested order...
|
||||||
|
discoverPacketOptions := discoverPacket.ParseOptions()
|
||||||
|
|
||||||
|
ourOptions := make(dhcp4.Options)
|
||||||
|
|
||||||
|
//1
|
||||||
|
ourOptions[dhcp4.OptionSubnetMask] = s.subnetMask.To4()
|
||||||
|
//3
|
||||||
|
ourOptions[dhcp4.OptionRouter] = s.defaultGateway.To4()
|
||||||
|
//6
|
||||||
|
ourOptions[dhcp4.OptionDomainNameServer] = dhcp4.JoinIPs(s.dnsServers)
|
||||||
|
|
||||||
|
if discoverPacketOptions[dhcp4.OptionParameterRequestList] != nil {
|
||||||
|
//Loop through the requested options and if we have them add them.
|
||||||
|
for _, optionCode := range discoverPacketOptions[dhcp4.OptionParameterRequestList] {
|
||||||
|
if !bytes.Equal(ourOptions[dhcp4.OptionCode(optionCode)], []byte{}) {
|
||||||
|
offerPacket.AddOption(dhcp4.OptionCode(optionCode), ourOptions[dhcp4.OptionCode(optionCode)])
|
||||||
|
delete(ourOptions, dhcp4.OptionCode(optionCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add all the options not requested.
|
||||||
|
for optionCode, optionValue := range ourOptions {
|
||||||
|
offerPacket.AddOption(optionCode, optionValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return offerPacket
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create DHCP Acknowledgement
|
||||||
|
*/
|
||||||
|
func (s *Server) AcknowledgementPacket(requestPacket dhcp4.Packet) dhcp4.Packet {
|
||||||
|
|
||||||
|
acknowledgementPacket := dhcp4.NewPacket(dhcp4.BootReply)
|
||||||
|
acknowledgementPacket.SetXId(requestPacket.XId())
|
||||||
|
acknowledgementPacket.SetFlags(requestPacket.Flags())
|
||||||
|
|
||||||
|
acknowledgementPacket.SetGIAddr(requestPacket.GIAddr())
|
||||||
|
acknowledgementPacket.SetCHAddr(requestPacket.CHAddr())
|
||||||
|
acknowledgementPacket.SetSecs(requestPacket.Secs())
|
||||||
|
|
||||||
|
acknowledgementPacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.ACK)})
|
||||||
|
acknowledgementPacket.AddOption(dhcp4.OptionSubnetMask, s.subnetMask.To4())
|
||||||
|
acknowledgementPacket.AddOption(dhcp4.OptionRouter, s.defaultGateway.To4())
|
||||||
|
acknowledgementPacket.AddOption(dhcp4.OptionDomainNameServer, dhcp4.JoinIPs(s.dnsServers))
|
||||||
|
acknowledgementPacket.AddOption(dhcp4.OptionServerIdentifier, s.ip.To4())
|
||||||
|
|
||||||
|
return acknowledgementPacket
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create DHCP Decline
|
||||||
|
*/
|
||||||
|
func (s *Server) DeclinePacket(requestPacket dhcp4.Packet) dhcp4.Packet {
|
||||||
|
|
||||||
|
declinePacket := dhcp4.NewPacket(dhcp4.BootReply)
|
||||||
|
declinePacket.SetXId(requestPacket.XId())
|
||||||
|
declinePacket.SetFlags(requestPacket.Flags())
|
||||||
|
|
||||||
|
declinePacket.SetGIAddr(requestPacket.GIAddr())
|
||||||
|
declinePacket.SetCHAddr(requestPacket.CHAddr())
|
||||||
|
declinePacket.SetSecs(requestPacket.Secs())
|
||||||
|
|
||||||
|
declinePacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.NAK)})
|
||||||
|
declinePacket.AddOption(dhcp4.OptionSubnetMask, s.subnetMask.To4())
|
||||||
|
declinePacket.AddOption(dhcp4.OptionRouter, s.defaultGateway.To4())
|
||||||
|
declinePacket.AddOption(dhcp4.OptionDomainNameServer, dhcp4.JoinIPs(s.dnsServers))
|
||||||
|
declinePacket.AddOption(dhcp4.OptionServerIdentifier, s.ip.To4())
|
||||||
|
|
||||||
|
return declinePacket
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get Lease tries to work out the best lease for the packet supplied.
|
||||||
|
* Taking into account all Requested IP, Exisitng MACAddresses and Free leases.
|
||||||
|
*/
|
||||||
|
func (s *Server) GetLease(packet dhcp4.Packet) (found bool, lease leasepool.Lease, err error) {
|
||||||
|
packetOptions := packet.ParseOptions()
|
||||||
|
|
||||||
|
//Requested an IP
|
||||||
|
if (len(packetOptions) > 0) &&
|
||||||
|
packetOptions[dhcp4.OptionRequestedIPAddress] != nil &&
|
||||||
|
!net.IP(packetOptions[dhcp4.OptionRequestedIPAddress]).Equal(net.IP{}) {
|
||||||
|
//An IP Has Been Requested Let's Try and Get that One.
|
||||||
|
|
||||||
|
found, lease, err = s.leasePool.GetLease(net.IP(packetOptions[dhcp4.OptionRequestedIPAddress]))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if found {
|
||||||
|
if lease.Status == leasepool.Free {
|
||||||
|
//Lease Is Free you Can Have it.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if lease.Status != leasepool.Free && bytes.Equal(lease.MACAddress, packet.CHAddr()) {
|
||||||
|
//Lease isn't free but it's yours
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Ok Even if you requested an IP you can't have it.
|
||||||
|
found, lease, err = s.leasePool.GetLeaseForHardwareAddress(packet.CHAddr())
|
||||||
|
if found || err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Just get the next free lease if you can.
|
||||||
|
found, lease, err = s.leasePool.GetNextFreeLease()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shutdown The Server Gracefully
|
||||||
|
*/
|
||||||
|
func (s *Server) Shutdown() {
|
||||||
|
s.shutdownLock.Lock()
|
||||||
|
defer s.shutdownLock.Unlock()
|
||||||
|
s.shutdown = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Garbage Collection
|
||||||
|
* Run Garbage Collection On Your Leases To Free Expired Leases.
|
||||||
|
*/
|
||||||
|
func (s *Server) GC() error {
|
||||||
|
leases, err := s.leasePool.GetLeases()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range leases {
|
||||||
|
if leases[i].Status != leasepool.Free {
|
||||||
|
//Lease Is Not Free
|
||||||
|
|
||||||
|
if time.Now().After(leases[i].Expiry) {
|
||||||
|
//Lease has expired.
|
||||||
|
leases[i].Status = leasepool.Free
|
||||||
|
updated, err := s.leasePool.UpdateLease(leases[i])
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Warning: Error trying to Free Lease %s \"%v\"\n", leases[i].IP.To4().String(), err)
|
||||||
|
}
|
||||||
|
if !updated {
|
||||||
|
log.Printf("Warning: Unable to Free Lease %s\n", leases[i].IP.To4().String())
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
426
vendor/github.com/d2g/dhcp4server/server_test.go
generated
vendored
Normal file
426
vendor/github.com/d2g/dhcp4server/server_test.go
generated
vendored
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
package dhcp4server_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/d2g/dhcp4"
|
||||||
|
"github.com/d2g/dhcp4client"
|
||||||
|
"github.com/d2g/dhcp4server"
|
||||||
|
"github.com/d2g/dhcp4server/leasepool"
|
||||||
|
"github.com/d2g/dhcp4server/leasepool/memorypool"
|
||||||
|
"github.com/d2g/hardwareaddr"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Example Server :D
|
||||||
|
*/
|
||||||
|
func ExampleServer() {
|
||||||
|
|
||||||
|
//Create a Lease Pool We're going to use a memory pool
|
||||||
|
//Remember the memory is cleared on restart so you will reissue the same IP Addresses.
|
||||||
|
myMemoryLeasePool := memorypool.MemoryPool{}
|
||||||
|
|
||||||
|
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||||
|
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||||
|
for i := 0; i < 30; i++ {
|
||||||
|
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Adding IP to pool:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We set the port numbers to over 1024 (1067 & 1068) as the automated test don't have root access
|
||||||
|
tServer, err := dhcp4server.New(
|
||||||
|
net.IPv4(192, 168, 1, 201),
|
||||||
|
&myMemoryLeasePool,
|
||||||
|
dhcp4server.SetLocalAddr(net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 1067}),
|
||||||
|
dhcp4server.SetRemoteAddr(net.UDPAddr{IP: net.IPv4bcast, Port: 1068}),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Configuring Server:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Start the Server...
|
||||||
|
err = tServer.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Starting Server:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test Discovering a Lease That's not Within Our Lease Range.
|
||||||
|
* This Happens When a devce switches network.
|
||||||
|
* Example: Mobile Phone on Mobile internet Has IP 100.123.123.123 Switch To Home Wifi
|
||||||
|
* The device requests 100.123.123.123 on Home Wifi which is out of range...
|
||||||
|
*/
|
||||||
|
func TestDiscoverOutOfRangeLease(test *testing.T) {
|
||||||
|
//Setup the Server
|
||||||
|
myServer, err := dhcp4server.New(
|
||||||
|
net.IPv4(192, 168, 1, 201),
|
||||||
|
getTestLeasePool(),
|
||||||
|
dhcp4server.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}),
|
||||||
|
dhcp4server.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Configure Server " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
err := myServer.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Starting Server:" + err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(5) * time.Second)
|
||||||
|
|
||||||
|
//Generate Hardware Address
|
||||||
|
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Lets Be A Client
|
||||||
|
|
||||||
|
//We need to set the connection ports to 1068 and 1067 so we don't need root access
|
||||||
|
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Client Conection Generation:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := dhcp4client.New(dhcp4client.HardwareAddr(HardwareMACAddress), dhcp4client.Connection(c))
|
||||||
|
defer client.Close()
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Conection Error:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
discoveryPacket := client.DiscoverPacket()
|
||||||
|
discoveryPacket.SetCIAddr(net.IPv4(100, 102, 96, 123))
|
||||||
|
discoveryPacket.PadToMinSize()
|
||||||
|
|
||||||
|
err = client.SendPacket(discoveryPacket)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Sending Discover Packet" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("--Discovery Packet--")
|
||||||
|
test.Logf("Client IP : %v\n", discoveryPacket.CIAddr().String())
|
||||||
|
test.Logf("Your IP : %v\n", discoveryPacket.YIAddr().String())
|
||||||
|
test.Logf("Server IP : %v\n", discoveryPacket.SIAddr().String())
|
||||||
|
test.Logf("Gateway IP: %v\n", discoveryPacket.GIAddr().String())
|
||||||
|
test.Logf("Client Mac: %v\n", discoveryPacket.CHAddr().String())
|
||||||
|
|
||||||
|
if !bytes.Equal(discoveryPacket.CHAddr(), HardwareMACAddress) {
|
||||||
|
test.Error("MACAddresses Don't Match??")
|
||||||
|
}
|
||||||
|
|
||||||
|
offerPacket, err := client.GetOffer(&discoveryPacket)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Getting Offer:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("--Offer Packet--")
|
||||||
|
test.Logf("Client IP : %v\n", offerPacket.CIAddr().String())
|
||||||
|
test.Logf("Your IP : %v\n", offerPacket.YIAddr().String())
|
||||||
|
test.Logf("Server IP : %v\n", offerPacket.SIAddr().String())
|
||||||
|
test.Logf("Gateway IP: %v\n", offerPacket.GIAddr().String())
|
||||||
|
test.Logf("Client Mac: %v\n", offerPacket.CHAddr().String())
|
||||||
|
|
||||||
|
requestPacket, err := client.SendRequest(&offerPacket)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Sending Request:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("--Request Packet--")
|
||||||
|
test.Logf("Client IP : %v\n", requestPacket.CIAddr().String())
|
||||||
|
test.Logf("Your IP : %v\n", requestPacket.YIAddr().String())
|
||||||
|
test.Logf("Server IP : %v\n", requestPacket.SIAddr().String())
|
||||||
|
test.Logf("Gateway IP: %v\n", requestPacket.GIAddr().String())
|
||||||
|
test.Logf("Client Mac: %v\n", requestPacket.CHAddr().String())
|
||||||
|
|
||||||
|
acknowledgement, err := client.GetAcknowledgement(&requestPacket)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Getting Acknowledgement:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("--Acknowledgement Packet--")
|
||||||
|
test.Logf("Client IP : %v\n", acknowledgement.CIAddr().String())
|
||||||
|
test.Logf("Your IP : %v\n", acknowledgement.YIAddr().String())
|
||||||
|
test.Logf("Server IP : %v\n", acknowledgement.SIAddr().String())
|
||||||
|
test.Logf("Gateway IP: %v\n", acknowledgement.GIAddr().String())
|
||||||
|
test.Logf("Client Mac: %v\n", acknowledgement.CHAddr().String())
|
||||||
|
|
||||||
|
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||||
|
if dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.ACK {
|
||||||
|
test.Error("Didn't get ACK?:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("Shutting Down Server")
|
||||||
|
myServer.Shutdown()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try Renewing A Lease From A Different Network.
|
||||||
|
*/
|
||||||
|
func TestRequestOutOfRangeLease(test *testing.T) {
|
||||||
|
//Setup the Server
|
||||||
|
myServer, err := dhcp4server.New(
|
||||||
|
net.IPv4(192, 168, 1, 201),
|
||||||
|
getTestLeasePool(),
|
||||||
|
dhcp4server.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}),
|
||||||
|
dhcp4server.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Configure Server " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
err := myServer.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Starting Server:" + err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
//Sleep some so the server starts....
|
||||||
|
time.Sleep(time.Duration(5) * time.Second)
|
||||||
|
|
||||||
|
//Generate Hardware Address
|
||||||
|
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
HardwareMACAddress, err = net.ParseMAC("58-94-6B-73-57-0C")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("MAC Error:%v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Lets Be A Client
|
||||||
|
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Client Conection Generation:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := dhcp4client.New(dhcp4client.HardwareAddr(HardwareMACAddress), dhcp4client.Connection(c))
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Conection Error:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create a dummy offer packet
|
||||||
|
offerPacket := client.DiscoverPacket()
|
||||||
|
|
||||||
|
offerPacket.SetCIAddr(net.IPv4(100, 102, 96, 123))
|
||||||
|
offerPacket.SetSIAddr(net.IPv4(192, 168, 1, 201))
|
||||||
|
offerPacket.SetYIAddr(net.IPv4(100, 102, 96, 123))
|
||||||
|
offerPacket.AddOption(dhcp4.OptionDHCPMessageType, []byte{byte(dhcp4.Offer)})
|
||||||
|
|
||||||
|
requestPacket, err := client.SendRequest(&offerPacket)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Sending Request:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("--Request Packet--")
|
||||||
|
test.Logf("Client IP : %v\n", requestPacket.CIAddr().String())
|
||||||
|
test.Logf("Your IP : %v\n", requestPacket.YIAddr().String())
|
||||||
|
test.Logf("Server IP : %v\n", requestPacket.SIAddr().String())
|
||||||
|
test.Logf("Gateway IP: %v\n", requestPacket.GIAddr().String())
|
||||||
|
test.Logf("Client Mac: %v\n", requestPacket.CHAddr().String())
|
||||||
|
|
||||||
|
acknowledgement, err := client.GetAcknowledgement(&requestPacket)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error Getting Acknowledgement:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("--Acknowledgement Packet--")
|
||||||
|
test.Logf("Client IP : %v\n", acknowledgement.CIAddr().String())
|
||||||
|
test.Logf("Your IP : %v\n", acknowledgement.YIAddr().String())
|
||||||
|
test.Logf("Server IP : %v\n", acknowledgement.SIAddr().String())
|
||||||
|
test.Logf("Gateway IP: %v\n", acknowledgement.GIAddr().String())
|
||||||
|
test.Logf("Client Mac: %v\n", acknowledgement.CHAddr().String())
|
||||||
|
|
||||||
|
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||||
|
if len(acknowledgementOptions[dhcp4.OptionDHCPMessageType]) <= 0 || dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.NAK {
|
||||||
|
test.Errorf("Didn't get NAK got DHCP4 Message Type:%v\n", dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Log("Shutting Down Server")
|
||||||
|
myServer.Shutdown()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
func TestConsumeLeases(test *testing.T) {
|
||||||
|
//Setup the Server
|
||||||
|
myServer, err := dhcp4server.New(
|
||||||
|
net.IPv4(127, 0, 0, 1),
|
||||||
|
getTestLeasePool(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Configure Server " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup A Client
|
||||||
|
// Although We Won't send the packets over the network we'll use the client to create the requests.
|
||||||
|
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Client Conection Generation:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := dhcp4client.New(dhcp4client.Connection(c))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Configure Client " + err.Error())
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
for i := 0; i < 30; i++ {
|
||||||
|
//Generate Hardware Address
|
||||||
|
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client.SetOption(dhcp4client.HardwareAddr(HardwareMACAddress))
|
||||||
|
test.Log("MAC:" + HardwareMACAddress.String())
|
||||||
|
|
||||||
|
discovery := client.DiscoverPacket()
|
||||||
|
|
||||||
|
//Run the Discovery On the Server
|
||||||
|
offer, err := myServer.ServeDHCP(discovery)
|
||||||
|
_, err = myServer.ServeDHCP(discovery)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Discovery Error:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
request := client.RequestPacket(&offer)
|
||||||
|
acknowledgement, err := myServer.ServeDHCP(request)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Acknowledge Error:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Logf("Received Lease:%v\n", acknowledgement.YIAddr().String())
|
||||||
|
if !dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).Equal(acknowledgement.YIAddr()) {
|
||||||
|
test.Error("Expected IP:" + dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i).String() + " Received:" + acknowledgement.YIAddr().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
//How long the lease is for?
|
||||||
|
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||||
|
if len(acknowledgementOptions) > 0 {
|
||||||
|
test.Logf("Lease Options:%v\n", acknowledgementOptions)
|
||||||
|
if acknowledgementOptions[dhcp4.OptionIPAddressLeaseTime] != nil {
|
||||||
|
var result uint32
|
||||||
|
buf := bytes.NewBuffer(acknowledgementOptions[dhcp4.OptionIPAddressLeaseTime])
|
||||||
|
binary.Read(buf, binary.BigEndian, &result)
|
||||||
|
test.Logf("Lease Time (Seconds):%d\n", result)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
test.Errorf("Lease:\"%v\" Has No Options\n", acknowledgement.YIAddr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Benchmark the ServeDHCP Function
|
||||||
|
*/
|
||||||
|
func BenchmarkServeDHCP(test *testing.B) {
|
||||||
|
//Create a Lease Pool We're going to use a memory pool
|
||||||
|
//Remember the memory is cleared on restart so you will reissue the same IP Addresses.
|
||||||
|
myMemoryLeasePool := memorypool.MemoryPool{}
|
||||||
|
|
||||||
|
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||||
|
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||||
|
for i := 0; i < test.N; i++ {
|
||||||
|
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Adding IP to pool:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup the Server
|
||||||
|
myServer, err := dhcp4server.New(
|
||||||
|
net.IPv4(127, 0, 0, 1),
|
||||||
|
&myMemoryLeasePool,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Configure Server " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup A Client
|
||||||
|
// Although We Won't send the packets over the network we'll use the client to create the requests.
|
||||||
|
c, err := dhcp4client.NewInetSock(dhcp4client.SetLocalAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1068}), dhcp4client.SetRemoteAddr(net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1067}))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Client Conection Generation:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := dhcp4client.New(dhcp4client.Connection(c))
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Configure Client " + err.Error())
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
test.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < test.N; i++ {
|
||||||
|
test.StopTimer()
|
||||||
|
//Generate Hardware Address
|
||||||
|
HardwareMACAddress, err := hardwareaddr.GenerateEUI48()
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Error: Can't Generate Valid MACAddress" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client.SetOption(dhcp4client.HardwareAddr(HardwareMACAddress))
|
||||||
|
discovery := client.DiscoverPacket()
|
||||||
|
|
||||||
|
//Run the Discovery On the Server
|
||||||
|
test.StartTimer()
|
||||||
|
offer, err := myServer.ServeDHCP(discovery)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Discovery Error:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(offer) == 0 {
|
||||||
|
test.Error("No Valid Offer")
|
||||||
|
} else {
|
||||||
|
request := client.RequestPacket(&offer)
|
||||||
|
_, err := myServer.ServeDHCP(request)
|
||||||
|
if err != nil {
|
||||||
|
test.Error("Acknowledge Error:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestLeasePool() *memorypool.MemoryPool {
|
||||||
|
//Create a Lease Pool We're going to use a memory pool
|
||||||
|
//Remember the memory is cleared on restart so you will reissue the same IP Addresses.
|
||||||
|
myMemoryLeasePool := memorypool.MemoryPool{}
|
||||||
|
|
||||||
|
//Lets add a list of IPs to the pool these will be served to the clients so make sure they work for you.
|
||||||
|
// So Create Array of IPs 192.168.1.1 to 192.168.1.30
|
||||||
|
for i := 0; i < 30; i++ {
|
||||||
|
err := myMemoryLeasePool.AddLease(leasepool.Lease{IP: dhcp4.IPAdd(net.IPv4(192, 168, 1, 1), i)})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error Adding IP to pool:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &myMemoryLeasePool
|
||||||
|
}
|
41
vendor/golang.org/x/net/bpf/asm.go
generated
vendored
Normal file
41
vendor/golang.org/x/net/bpf/asm.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Assemble converts insts into raw instructions suitable for loading
|
||||||
|
// into a BPF virtual machine.
|
||||||
|
//
|
||||||
|
// Currently, no optimization is attempted, the assembled program flow
|
||||||
|
// is exactly as provided.
|
||||||
|
func Assemble(insts []Instruction) ([]RawInstruction, error) {
|
||||||
|
ret := make([]RawInstruction, len(insts))
|
||||||
|
var err error
|
||||||
|
for i, inst := range insts {
|
||||||
|
ret[i], err = inst.Assemble()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disassemble attempts to parse raw back into
|
||||||
|
// Instructions. Unrecognized RawInstructions are assumed to be an
|
||||||
|
// extension not implemented by this package, and are passed through
|
||||||
|
// unchanged to the output. The allDecoded value reports whether insts
|
||||||
|
// contains no RawInstructions.
|
||||||
|
func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) {
|
||||||
|
insts = make([]Instruction, len(raw))
|
||||||
|
allDecoded = true
|
||||||
|
for i, r := range raw {
|
||||||
|
insts[i] = r.Disassemble()
|
||||||
|
if _, ok := insts[i].(RawInstruction); ok {
|
||||||
|
allDecoded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insts, allDecoded
|
||||||
|
}
|
215
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
Normal file
215
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
// A Register is a register of the BPF virtual machine.
|
||||||
|
type Register uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RegA is the accumulator register. RegA is always the
|
||||||
|
// destination register of ALU operations.
|
||||||
|
RegA Register = iota
|
||||||
|
// RegX is the indirection register, used by LoadIndirect
|
||||||
|
// operations.
|
||||||
|
RegX
|
||||||
|
)
|
||||||
|
|
||||||
|
// An ALUOp is an arithmetic or logic operation.
|
||||||
|
type ALUOp uint16
|
||||||
|
|
||||||
|
// ALU binary operation types.
|
||||||
|
const (
|
||||||
|
ALUOpAdd ALUOp = iota << 4
|
||||||
|
ALUOpSub
|
||||||
|
ALUOpMul
|
||||||
|
ALUOpDiv
|
||||||
|
ALUOpOr
|
||||||
|
ALUOpAnd
|
||||||
|
ALUOpShiftLeft
|
||||||
|
ALUOpShiftRight
|
||||||
|
aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type.
|
||||||
|
ALUOpMod
|
||||||
|
ALUOpXor
|
||||||
|
)
|
||||||
|
|
||||||
|
// A JumpTest is a comparison operator used in conditional jumps.
|
||||||
|
type JumpTest uint16
|
||||||
|
|
||||||
|
// Supported operators for conditional jumps.
|
||||||
|
const (
|
||||||
|
// K == A
|
||||||
|
JumpEqual JumpTest = iota
|
||||||
|
// K != A
|
||||||
|
JumpNotEqual
|
||||||
|
// K > A
|
||||||
|
JumpGreaterThan
|
||||||
|
// K < A
|
||||||
|
JumpLessThan
|
||||||
|
// K >= A
|
||||||
|
JumpGreaterOrEqual
|
||||||
|
// K <= A
|
||||||
|
JumpLessOrEqual
|
||||||
|
// K & A != 0
|
||||||
|
JumpBitsSet
|
||||||
|
// K & A == 0
|
||||||
|
JumpBitsNotSet
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Extension is a function call provided by the kernel that
|
||||||
|
// performs advanced operations that are expensive or impossible
|
||||||
|
// within the BPF virtual machine.
|
||||||
|
//
|
||||||
|
// Extensions are only implemented by the Linux kernel.
|
||||||
|
//
|
||||||
|
// TODO: should we prune this list? Some of these extensions seem
|
||||||
|
// either broken or near-impossible to use correctly, whereas other
|
||||||
|
// (len, random, ifindex) are quite useful.
|
||||||
|
type Extension int
|
||||||
|
|
||||||
|
// Extension functions available in the Linux kernel.
|
||||||
|
const (
|
||||||
|
// ExtLen returns the length of the packet.
|
||||||
|
ExtLen Extension = 1
|
||||||
|
// ExtProto returns the packet's L3 protocol type.
|
||||||
|
ExtProto = 0
|
||||||
|
// ExtType returns the packet's type (skb->pkt_type in the kernel)
|
||||||
|
//
|
||||||
|
// TODO: better documentation. How nice an API do we want to
|
||||||
|
// provide for these esoteric extensions?
|
||||||
|
ExtType = 4
|
||||||
|
// ExtPayloadOffset returns the offset of the packet payload, or
|
||||||
|
// the first protocol header that the kernel does not know how to
|
||||||
|
// parse.
|
||||||
|
ExtPayloadOffset = 52
|
||||||
|
// ExtInterfaceIndex returns the index of the interface on which
|
||||||
|
// the packet was received.
|
||||||
|
ExtInterfaceIndex = 8
|
||||||
|
// ExtNetlinkAttr returns the netlink attribute of type X at
|
||||||
|
// offset A.
|
||||||
|
ExtNetlinkAttr = 12
|
||||||
|
// ExtNetlinkAttrNested returns the nested netlink attribute of
|
||||||
|
// type X at offset A.
|
||||||
|
ExtNetlinkAttrNested = 16
|
||||||
|
// ExtMark returns the packet's mark value.
|
||||||
|
ExtMark = 20
|
||||||
|
// ExtQueue returns the packet's assigned hardware queue.
|
||||||
|
ExtQueue = 24
|
||||||
|
// ExtLinkLayerType returns the packet's hardware address type
|
||||||
|
// (e.g. Ethernet, Infiniband).
|
||||||
|
ExtLinkLayerType = 28
|
||||||
|
// ExtRXHash returns the packets receive hash.
|
||||||
|
//
|
||||||
|
// TODO: figure out what this rxhash actually is.
|
||||||
|
ExtRXHash = 32
|
||||||
|
// ExtCPUID returns the ID of the CPU processing the current
|
||||||
|
// packet.
|
||||||
|
ExtCPUID = 36
|
||||||
|
// ExtVLANTag returns the packet's VLAN tag.
|
||||||
|
ExtVLANTag = 44
|
||||||
|
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
|
||||||
|
// tag.
|
||||||
|
//
|
||||||
|
// TODO: I think this might be a lie: it reads bit 0x1000 of the
|
||||||
|
// VLAN header, which changed meaning in recent revisions of the
|
||||||
|
// spec - this extension may now return meaningless information.
|
||||||
|
ExtVLANTagPresent = 48
|
||||||
|
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
|
||||||
|
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
|
||||||
|
// other value if no VLAN information is present.
|
||||||
|
ExtVLANProto = 60
|
||||||
|
// ExtRand returns a uniformly random uint32.
|
||||||
|
ExtRand = 56
|
||||||
|
)
|
||||||
|
|
||||||
|
// The following gives names to various bit patterns used in opcode construction.
|
||||||
|
|
||||||
|
const (
|
||||||
|
opMaskCls uint16 = 0x7
|
||||||
|
// opClsLoad masks
|
||||||
|
opMaskLoadDest = 0x01
|
||||||
|
opMaskLoadWidth = 0x18
|
||||||
|
opMaskLoadMode = 0xe0
|
||||||
|
// opClsALU
|
||||||
|
opMaskOperandSrc = 0x08
|
||||||
|
opMaskOperator = 0xf0
|
||||||
|
// opClsJump
|
||||||
|
opMaskJumpConst = 0x0f
|
||||||
|
opMaskJumpCond = 0xf0
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsLoadA uint16 = iota
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsLoadX
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
opClsStoreA
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
opClsStoreX
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsALU
|
||||||
|
// +-----------------------------+---+---+---+---+
|
||||||
|
// | TestOperator (4b) | 0 | 1 | 0 | 1 |
|
||||||
|
// +-----------------------------+---+---+---+---+
|
||||||
|
opClsJump
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 |
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
opClsReturn
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 |
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
opClsMisc
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opAddrModeImmediate uint16 = iota << 5
|
||||||
|
opAddrModeAbsolute
|
||||||
|
opAddrModeIndirect
|
||||||
|
opAddrModeScratch
|
||||||
|
opAddrModePacketLen // actually an extension, not an addressing mode.
|
||||||
|
opAddrModeMemShift
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opLoadWidth4 uint16 = iota << 3
|
||||||
|
opLoadWidth2
|
||||||
|
opLoadWidth1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operator defined by ALUOp*
|
||||||
|
|
||||||
|
const (
|
||||||
|
opALUSrcConstant uint16 = iota << 3
|
||||||
|
opALUSrcX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opJumpAlways = iota << 4
|
||||||
|
opJumpEqual
|
||||||
|
opJumpGT
|
||||||
|
opJumpGE
|
||||||
|
opJumpSet
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opRetSrcConstant uint16 = iota << 4
|
||||||
|
opRetSrcA
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opMiscTAX = 0x00
|
||||||
|
opMiscTXA = 0x80
|
||||||
|
)
|
82
vendor/golang.org/x/net/bpf/doc.go
generated
vendored
Normal file
82
vendor/golang.org/x/net/bpf/doc.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Package bpf implements marshaling and unmarshaling of programs for the
|
||||||
|
Berkeley Packet Filter virtual machine, and provides a Go implementation
|
||||||
|
of the virtual machine.
|
||||||
|
|
||||||
|
BPF's main use is to specify a packet filter for network taps, so that
|
||||||
|
the kernel doesn't have to expensively copy every packet it sees to
|
||||||
|
userspace. However, it's been repurposed to other areas where running
|
||||||
|
user code in-kernel is needed. For example, Linux's seccomp uses BPF
|
||||||
|
to apply security policies to system calls. For simplicity, this
|
||||||
|
documentation refers only to packets, but other uses of BPF have their
|
||||||
|
own data payloads.
|
||||||
|
|
||||||
|
BPF programs run in a restricted virtual machine. It has almost no
|
||||||
|
access to kernel functions, and while conditional branches are
|
||||||
|
allowed, they can only jump forwards, to guarantee that there are no
|
||||||
|
infinite loops.
|
||||||
|
|
||||||
|
The virtual machine
|
||||||
|
|
||||||
|
The BPF VM is an accumulator machine. Its main register, called
|
||||||
|
register A, is an implicit source and destination in all arithmetic
|
||||||
|
and logic operations. The machine also has 16 scratch registers for
|
||||||
|
temporary storage, and an indirection register (register X) for
|
||||||
|
indirect memory access. All registers are 32 bits wide.
|
||||||
|
|
||||||
|
Each run of a BPF program is given one packet, which is placed in the
|
||||||
|
VM's read-only "main memory". LoadAbsolute and LoadIndirect
|
||||||
|
instructions can fetch up to 32 bits at a time into register A for
|
||||||
|
examination.
|
||||||
|
|
||||||
|
The goal of a BPF program is to produce and return a verdict (uint32),
|
||||||
|
which tells the kernel what to do with the packet. In the context of
|
||||||
|
packet filtering, the returned value is the number of bytes of the
|
||||||
|
packet to forward to userspace, or 0 to ignore the packet. Other
|
||||||
|
contexts like seccomp define their own return values.
|
||||||
|
|
||||||
|
In order to simplify programs, attempts to read past the end of the
|
||||||
|
packet terminate the program execution with a verdict of 0 (ignore
|
||||||
|
packet). This means that the vast majority of BPF programs don't need
|
||||||
|
to do any explicit bounds checking.
|
||||||
|
|
||||||
|
In addition to the bytes of the packet, some BPF programs have access
|
||||||
|
to extensions, which are essentially calls to kernel utility
|
||||||
|
functions. Currently, the only extensions supported by this package
|
||||||
|
are the Linux packet filter extensions.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
|
||||||
|
This packet filter selects all ARP packets.
|
||||||
|
|
||||||
|
bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Load "EtherType" field from the ethernet header.
|
||||||
|
bpf.LoadAbsolute{Off: 12, Size: 2},
|
||||||
|
// Skip over the next instruction if EtherType is not ARP.
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1},
|
||||||
|
// Verdict is "send up to 4k of the packet to userspace."
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Verdict is "ignore packet."
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
This packet filter captures a random 1% sample of traffic.
|
||||||
|
|
||||||
|
bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Get a 32-bit random number from the Linux kernel.
|
||||||
|
bpf.LoadExtension{Num: bpf.ExtRand},
|
||||||
|
// 1% dice roll?
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1},
|
||||||
|
// Capture.
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Ignore.
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
*/
|
||||||
|
package bpf // import "golang.org/x/net/bpf"
|
434
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
Normal file
434
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// An Instruction is one instruction executed by the BPF virtual
|
||||||
|
// machine.
|
||||||
|
type Instruction interface {
|
||||||
|
// Assemble assembles the Instruction into a RawInstruction.
|
||||||
|
Assemble() (RawInstruction, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RawInstruction is a raw BPF virtual machine instruction.
|
||||||
|
type RawInstruction struct {
|
||||||
|
// Operation to execute.
|
||||||
|
Op uint16
|
||||||
|
// For conditional jump instructions, the number of instructions
|
||||||
|
// to skip if the condition is true/false.
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
// Constant parameter. The meaning depends on the Op.
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
|
||||||
|
|
||||||
|
// Disassemble parses ri into an Instruction and returns it. If ri is
|
||||||
|
// not recognized by this package, ri itself is returned.
|
||||||
|
func (ri RawInstruction) Disassemble() Instruction {
|
||||||
|
switch ri.Op & opMaskCls {
|
||||||
|
case opClsLoadA, opClsLoadX:
|
||||||
|
reg := Register(ri.Op & opMaskLoadDest)
|
||||||
|
sz := 0
|
||||||
|
switch ri.Op & opMaskLoadWidth {
|
||||||
|
case opLoadWidth4:
|
||||||
|
sz = 4
|
||||||
|
case opLoadWidth2:
|
||||||
|
sz = 2
|
||||||
|
case opLoadWidth1:
|
||||||
|
sz = 1
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
switch ri.Op & opMaskLoadMode {
|
||||||
|
case opAddrModeImmediate:
|
||||||
|
if sz != 4 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadConstant{Dst: reg, Val: ri.K}
|
||||||
|
case opAddrModeScratch:
|
||||||
|
if sz != 4 || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadScratch{Dst: reg, N: int(ri.K)}
|
||||||
|
case opAddrModeAbsolute:
|
||||||
|
return LoadAbsolute{Size: sz, Off: ri.K}
|
||||||
|
case opAddrModeIndirect:
|
||||||
|
return LoadIndirect{Size: sz, Off: ri.K}
|
||||||
|
case opAddrModePacketLen:
|
||||||
|
if sz != 4 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadExtension{Num: ExtLen}
|
||||||
|
case opAddrModeMemShift:
|
||||||
|
return LoadMemShift{Off: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsStoreA:
|
||||||
|
if ri.Op != opClsStoreA || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return StoreScratch{Src: RegA, N: int(ri.K)}
|
||||||
|
|
||||||
|
case opClsStoreX:
|
||||||
|
if ri.Op != opClsStoreX || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return StoreScratch{Src: RegX, N: int(ri.K)}
|
||||||
|
|
||||||
|
case opClsALU:
|
||||||
|
switch op := ALUOp(ri.Op & opMaskOperator); op {
|
||||||
|
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
|
||||||
|
if ri.Op&opMaskOperandSrc != 0 {
|
||||||
|
return ALUOpX{Op: op}
|
||||||
|
}
|
||||||
|
return ALUOpConstant{Op: op, Val: ri.K}
|
||||||
|
case aluOpNeg:
|
||||||
|
return NegateA{}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsJump:
|
||||||
|
if ri.Op&opMaskJumpConst != opClsJump {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
switch ri.Op & opMaskJumpCond {
|
||||||
|
case opJumpAlways:
|
||||||
|
return Jump{Skip: ri.K}
|
||||||
|
case opJumpEqual:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpGT:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpGreaterThan,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpGE:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpGreaterOrEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpSet:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpBitsSet,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsReturn:
|
||||||
|
switch ri.Op {
|
||||||
|
case opClsReturn | opRetSrcA:
|
||||||
|
return RetA{}
|
||||||
|
case opClsReturn | opRetSrcConstant:
|
||||||
|
return RetConstant{Val: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsMisc:
|
||||||
|
switch ri.Op {
|
||||||
|
case opClsMisc | opMiscTAX:
|
||||||
|
return TAX{}
|
||||||
|
case opClsMisc | opMiscTXA:
|
||||||
|
return TXA{}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("unreachable") // switch is exhaustive on the bit pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConstant loads Val into register Dst.
|
||||||
|
type LoadConstant struct {
|
||||||
|
Dst Register
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadScratch loads scratch[N] into register Dst.
|
||||||
|
type LoadScratch struct {
|
||||||
|
Dst Register
|
||||||
|
N int // 0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadScratch) Assemble() (RawInstruction, error) {
|
||||||
|
if a.N < 0 || a.N > 15 {
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
|
||||||
|
}
|
||||||
|
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
||||||
|
// register A.
|
||||||
|
type LoadAbsolute struct {
|
||||||
|
Off uint32
|
||||||
|
Size int // 1, 2 or 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
||||||
|
// into register A.
|
||||||
|
type LoadIndirect struct {
|
||||||
|
Off uint32
|
||||||
|
Size int // 1, 2 or 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadIndirect) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
||||||
|
// by 4 and stores the result in register X.
|
||||||
|
//
|
||||||
|
// This instruction is mainly useful to load into X the length of an
|
||||||
|
// IPv4 packet header in a single instruction, rather than have to do
|
||||||
|
// the arithmetic on the header's first byte by hand.
|
||||||
|
type LoadMemShift struct {
|
||||||
|
Off uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadMemShift) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadExtension invokes a linux-specific extension and stores the
|
||||||
|
// result in register A.
|
||||||
|
type LoadExtension struct {
|
||||||
|
Num Extension
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadExtension) Assemble() (RawInstruction, error) {
|
||||||
|
if a.Num == ExtLen {
|
||||||
|
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
||||||
|
}
|
||||||
|
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(-0x1000+a.Num))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoreScratch stores register Src into scratch[N].
|
||||||
|
type StoreScratch struct {
|
||||||
|
Src Register
|
||||||
|
N int // 0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a StoreScratch) Assemble() (RawInstruction, error) {
|
||||||
|
if a.N < 0 || a.N > 15 {
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
|
||||||
|
}
|
||||||
|
var op uint16
|
||||||
|
switch a.Src {
|
||||||
|
case RegA:
|
||||||
|
op = opClsStoreA
|
||||||
|
case RegX:
|
||||||
|
op = opClsStoreX
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawInstruction{
|
||||||
|
Op: op,
|
||||||
|
K: uint32(a.N),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALUOpConstant executes A = A <Op> Val.
|
||||||
|
type ALUOpConstant struct {
|
||||||
|
Op ALUOp
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | opALUSrcConstant | uint16(a.Op),
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALUOpX executes A = A <Op> X
|
||||||
|
type ALUOpX struct {
|
||||||
|
Op ALUOp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a ALUOpX) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | opALUSrcX | uint16(a.Op),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NegateA executes A = -A.
|
||||||
|
type NegateA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a NegateA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | uint16(aluOpNeg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump skips the following Skip instructions in the program.
|
||||||
|
type Jump struct {
|
||||||
|
Skip uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a Jump) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsJump | opJumpAlways,
|
||||||
|
K: a.Skip,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// JumpIf skips the following Skip instructions in the program if A
|
||||||
|
// <Cond> Val is true.
|
||||||
|
type JumpIf struct {
|
||||||
|
Cond JumpTest
|
||||||
|
Val uint32
|
||||||
|
SkipTrue uint8
|
||||||
|
SkipFalse uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a JumpIf) Assemble() (RawInstruction, error) {
|
||||||
|
var (
|
||||||
|
cond uint16
|
||||||
|
flip bool
|
||||||
|
)
|
||||||
|
switch a.Cond {
|
||||||
|
case JumpEqual:
|
||||||
|
cond = opJumpEqual
|
||||||
|
case JumpNotEqual:
|
||||||
|
cond, flip = opJumpEqual, true
|
||||||
|
case JumpGreaterThan:
|
||||||
|
cond = opJumpGT
|
||||||
|
case JumpLessThan:
|
||||||
|
cond, flip = opJumpGE, true
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
cond = opJumpGE
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
cond, flip = opJumpGT, true
|
||||||
|
case JumpBitsSet:
|
||||||
|
cond = opJumpSet
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
cond, flip = opJumpSet, true
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond)
|
||||||
|
}
|
||||||
|
jt, jf := a.SkipTrue, a.SkipFalse
|
||||||
|
if flip {
|
||||||
|
jt, jf = jf, jt
|
||||||
|
}
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsJump | cond,
|
||||||
|
Jt: jt,
|
||||||
|
Jf: jf,
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetA exits the BPF program, returning the value of register A.
|
||||||
|
type RetA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a RetA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsReturn | opRetSrcA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetConstant exits the BPF program, returning a constant value.
|
||||||
|
type RetConstant struct {
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a RetConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsReturn | opRetSrcConstant,
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TXA copies the value of register X to register A.
|
||||||
|
type TXA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a TXA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsMisc | opMiscTXA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TAX copies the value of register A to register X.
|
||||||
|
type TAX struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a TAX) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsMisc | opMiscTAX,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
||||||
|
var (
|
||||||
|
cls uint16
|
||||||
|
sz uint16
|
||||||
|
)
|
||||||
|
switch dst {
|
||||||
|
case RegA:
|
||||||
|
cls = opClsLoadA
|
||||||
|
case RegX:
|
||||||
|
cls = opClsLoadX
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
|
||||||
|
}
|
||||||
|
switch loadSize {
|
||||||
|
case 1:
|
||||||
|
sz = opLoadWidth1
|
||||||
|
case 2:
|
||||||
|
sz = opLoadWidth2
|
||||||
|
case 4:
|
||||||
|
sz = opLoadWidth4
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
|
||||||
|
}
|
||||||
|
return RawInstruction{
|
||||||
|
Op: cls | sz | mode,
|
||||||
|
K: k,
|
||||||
|
}, nil
|
||||||
|
}
|
184
vendor/golang.org/x/net/bpf/instructions_test.go
generated
vendored
Normal file
184
vendor/golang.org/x/net/bpf/instructions_test.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a direct translation of the program in
|
||||||
|
// testdata/all_instructions.txt.
|
||||||
|
var allInstructions = []Instruction{
|
||||||
|
LoadConstant{Dst: RegA, Val: 42},
|
||||||
|
LoadConstant{Dst: RegX, Val: 42},
|
||||||
|
|
||||||
|
LoadScratch{Dst: RegA, N: 3},
|
||||||
|
LoadScratch{Dst: RegX, N: 3},
|
||||||
|
|
||||||
|
LoadAbsolute{Off: 42, Size: 1},
|
||||||
|
LoadAbsolute{Off: 42, Size: 2},
|
||||||
|
LoadAbsolute{Off: 42, Size: 4},
|
||||||
|
|
||||||
|
LoadIndirect{Off: 42, Size: 1},
|
||||||
|
LoadIndirect{Off: 42, Size: 2},
|
||||||
|
LoadIndirect{Off: 42, Size: 4},
|
||||||
|
|
||||||
|
LoadMemShift{Off: 42},
|
||||||
|
|
||||||
|
LoadExtension{Num: ExtLen},
|
||||||
|
LoadExtension{Num: ExtProto},
|
||||||
|
LoadExtension{Num: ExtType},
|
||||||
|
LoadExtension{Num: ExtRand},
|
||||||
|
|
||||||
|
StoreScratch{Src: RegA, N: 3},
|
||||||
|
StoreScratch{Src: RegX, N: 3},
|
||||||
|
|
||||||
|
ALUOpConstant{Op: ALUOpAdd, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpSub, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpMul, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpDiv, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpOr, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpAnd, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpShiftLeft, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpShiftRight, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpMod, Val: 42},
|
||||||
|
ALUOpConstant{Op: ALUOpXor, Val: 42},
|
||||||
|
|
||||||
|
ALUOpX{Op: ALUOpAdd},
|
||||||
|
ALUOpX{Op: ALUOpSub},
|
||||||
|
ALUOpX{Op: ALUOpMul},
|
||||||
|
ALUOpX{Op: ALUOpDiv},
|
||||||
|
ALUOpX{Op: ALUOpOr},
|
||||||
|
ALUOpX{Op: ALUOpAnd},
|
||||||
|
ALUOpX{Op: ALUOpShiftLeft},
|
||||||
|
ALUOpX{Op: ALUOpShiftRight},
|
||||||
|
ALUOpX{Op: ALUOpMod},
|
||||||
|
ALUOpX{Op: ALUOpXor},
|
||||||
|
|
||||||
|
NegateA{},
|
||||||
|
|
||||||
|
Jump{Skip: 10},
|
||||||
|
JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9},
|
||||||
|
JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8},
|
||||||
|
JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7},
|
||||||
|
JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6},
|
||||||
|
JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5},
|
||||||
|
JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4},
|
||||||
|
JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3},
|
||||||
|
|
||||||
|
TAX{},
|
||||||
|
TXA{},
|
||||||
|
|
||||||
|
RetA{},
|
||||||
|
RetConstant{Val: 42},
|
||||||
|
}
|
||||||
|
var allInstructionsExpected = "testdata/all_instructions.bpf"
|
||||||
|
|
||||||
|
// Check that we produce the same output as the canonical bpf_asm
|
||||||
|
// linux kernel tool.
|
||||||
|
func TestInterop(t *testing.T) {
|
||||||
|
out, err := Assemble(allInstructions)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("assembly of allInstructions program failed: %s", err)
|
||||||
|
}
|
||||||
|
t.Logf("Assembled program is %d instructions long", len(out))
|
||||||
|
|
||||||
|
bs, err := ioutil.ReadFile(allInstructionsExpected)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reading %s: %s", allInstructionsExpected, err)
|
||||||
|
}
|
||||||
|
// First statement is the number of statements, last statement is
|
||||||
|
// empty. We just ignore both and rely on slice length.
|
||||||
|
stmts := strings.Split(string(bs), ",")
|
||||||
|
if len(stmts)-2 != len(out) {
|
||||||
|
t.Fatalf("test program lengths don't match: %s has %d, Go implementation has %d", allInstructionsExpected, len(stmts)-2, len(allInstructions))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, stmt := range stmts[1 : len(stmts)-2] {
|
||||||
|
nums := strings.Split(stmt, " ")
|
||||||
|
if len(nums) != 4 {
|
||||||
|
t.Fatalf("malformed instruction %d in %s: %s", i+1, allInstructionsExpected, stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := out[i]
|
||||||
|
|
||||||
|
op, err := strconv.ParseUint(nums[0], 10, 16)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("malformed opcode %s in instruction %d of %s", nums[0], i+1, allInstructionsExpected)
|
||||||
|
}
|
||||||
|
if actual.Op != uint16(op) {
|
||||||
|
t.Errorf("opcode mismatch on instruction %d (%#v): got 0x%02x, want 0x%02x", i+1, allInstructions[i], actual.Op, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
jt, err := strconv.ParseUint(nums[1], 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("malformed jt offset %s in instruction %d of %s", nums[1], i+1, allInstructionsExpected)
|
||||||
|
}
|
||||||
|
if actual.Jt != uint8(jt) {
|
||||||
|
t.Errorf("jt mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jt, jt)
|
||||||
|
}
|
||||||
|
|
||||||
|
jf, err := strconv.ParseUint(nums[2], 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("malformed jf offset %s in instruction %d of %s", nums[2], i+1, allInstructionsExpected)
|
||||||
|
}
|
||||||
|
if actual.Jf != uint8(jf) {
|
||||||
|
t.Errorf("jf mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.Jf, jf)
|
||||||
|
}
|
||||||
|
|
||||||
|
k, err := strconv.ParseUint(nums[3], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("malformed constant %s in instruction %d of %s", nums[3], i+1, allInstructionsExpected)
|
||||||
|
}
|
||||||
|
if actual.K != uint32(k) {
|
||||||
|
t.Errorf("constant mismatch on instruction %d (%#v): got %d, want %d", i+1, allInstructions[i], actual.K, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that assembly and disassembly match each other.
|
||||||
|
//
|
||||||
|
// Because we offer "fake" jump conditions that don't appear in the
|
||||||
|
// machine code, disassembly won't be a 1:1 match with the original
|
||||||
|
// source, although the behavior will be identical. However,
|
||||||
|
// reassembling the disassembly should produce an identical program.
|
||||||
|
func TestAsmDisasm(t *testing.T) {
|
||||||
|
prog1, err := Assemble(allInstructions)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("assembly of allInstructions program failed: %s", err)
|
||||||
|
}
|
||||||
|
t.Logf("Assembled program is %d instructions long", len(prog1))
|
||||||
|
|
||||||
|
src, allDecoded := Disassemble(prog1)
|
||||||
|
if !allDecoded {
|
||||||
|
t.Errorf("Disassemble(Assemble(allInstructions)) produced unrecognized instructions:")
|
||||||
|
for i, inst := range src {
|
||||||
|
if r, ok := inst.(RawInstruction); ok {
|
||||||
|
t.Logf(" insn %d, %#v --> %#v", i+1, allInstructions[i], r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prog2, err := Assemble(src)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("assembly of Disassemble(Assemble(allInstructions)) failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(prog2) != len(prog1) {
|
||||||
|
t.Fatalf("disassembly changed program size: %d insns before, %d insns after", len(prog1), len(prog2))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(prog1, prog2) {
|
||||||
|
t.Errorf("program mutated by disassembly:")
|
||||||
|
for i := range prog2 {
|
||||||
|
if !reflect.DeepEqual(prog1[i], prog2[i]) {
|
||||||
|
t.Logf(" insn %d, s: %#v, p1: %#v, p2: %#v", i+1, allInstructions[i], prog1[i], prog2[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf
generated
vendored
Normal file
1
vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
50,0 0 0 42,1 0 0 42,96 0 0 3,97 0 0 3,48 0 0 42,40 0 0 42,32 0 0 42,80 0 0 42,72 0 0 42,64 0 0 42,177 0 0 42,128 0 0 0,32 0 0 4294963200,32 0 0 4294963204,32 0 0 4294963256,2 0 0 3,3 0 0 3,4 0 0 42,20 0 0 42,36 0 0 42,52 0 0 42,68 0 0 42,84 0 0 42,100 0 0 42,116 0 0 42,148 0 0 42,164 0 0 42,12 0 0 0,28 0 0 0,44 0 0 0,60 0 0 0,76 0 0 0,92 0 0 0,108 0 0 0,124 0 0 0,156 0 0 0,172 0 0 0,132 0 0 0,5 0 0 10,21 8 9 42,21 0 8 42,53 0 7 42,37 0 6 42,37 4 5 42,53 3 4 42,69 2 3 42,7 0 0 0,135 0 0 0,22 0 0 0,6 0 0 0,
|
79
vendor/golang.org/x/net/bpf/testdata/all_instructions.txt
generated
vendored
Normal file
79
vendor/golang.org/x/net/bpf/testdata/all_instructions.txt
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# This filter is compiled to all_instructions.bpf by the `bpf_asm`
|
||||||
|
# tool, which can be found in the linux kernel source tree under
|
||||||
|
# tools/net.
|
||||||
|
|
||||||
|
# Load immediate
|
||||||
|
ld #42
|
||||||
|
ldx #42
|
||||||
|
|
||||||
|
# Load scratch
|
||||||
|
ld M[3]
|
||||||
|
ldx M[3]
|
||||||
|
|
||||||
|
# Load absolute
|
||||||
|
ldb [42]
|
||||||
|
ldh [42]
|
||||||
|
ld [42]
|
||||||
|
|
||||||
|
# Load indirect
|
||||||
|
ldb [x + 42]
|
||||||
|
ldh [x + 42]
|
||||||
|
ld [x + 42]
|
||||||
|
|
||||||
|
# Load IPv4 header length
|
||||||
|
ldx 4*([42]&0xf)
|
||||||
|
|
||||||
|
# Run extension function
|
||||||
|
ld #len
|
||||||
|
ld #proto
|
||||||
|
ld #type
|
||||||
|
ld #rand
|
||||||
|
|
||||||
|
# Store scratch
|
||||||
|
st M[3]
|
||||||
|
stx M[3]
|
||||||
|
|
||||||
|
# A <op> constant
|
||||||
|
add #42
|
||||||
|
sub #42
|
||||||
|
mul #42
|
||||||
|
div #42
|
||||||
|
or #42
|
||||||
|
and #42
|
||||||
|
lsh #42
|
||||||
|
rsh #42
|
||||||
|
mod #42
|
||||||
|
xor #42
|
||||||
|
|
||||||
|
# A <op> X
|
||||||
|
add x
|
||||||
|
sub x
|
||||||
|
mul x
|
||||||
|
div x
|
||||||
|
or x
|
||||||
|
and x
|
||||||
|
lsh x
|
||||||
|
rsh x
|
||||||
|
mod x
|
||||||
|
xor x
|
||||||
|
|
||||||
|
# !A
|
||||||
|
neg
|
||||||
|
|
||||||
|
# Jumps
|
||||||
|
ja end
|
||||||
|
jeq #42,prev,end
|
||||||
|
jne #42,end
|
||||||
|
jlt #42,end
|
||||||
|
jle #42,end
|
||||||
|
jgt #42,prev,end
|
||||||
|
jge #42,prev,end
|
||||||
|
jset #42,prev,end
|
||||||
|
|
||||||
|
# Register transfers
|
||||||
|
tax
|
||||||
|
txa
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
prev: ret a
|
||||||
|
end: ret #42
|
140
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
Normal file
140
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A VM is an emulated BPF virtual machine.
|
||||||
|
type VM struct {
|
||||||
|
filter []Instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVM returns a new VM using the input BPF program.
|
||||||
|
func NewVM(filter []Instruction) (*VM, error) {
|
||||||
|
if len(filter) == 0 {
|
||||||
|
return nil, errors.New("one or more Instructions must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ins := range filter {
|
||||||
|
check := len(filter) - (i + 1)
|
||||||
|
switch ins := ins.(type) {
|
||||||
|
// Check for out-of-bounds jumps in instructions
|
||||||
|
case Jump:
|
||||||
|
if check <= int(ins.Skip) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
|
||||||
|
}
|
||||||
|
case JumpIf:
|
||||||
|
if check <= int(ins.SkipTrue) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
|
||||||
|
}
|
||||||
|
if check <= int(ins.SkipFalse) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
||||||
|
}
|
||||||
|
// Check for division or modulus by zero
|
||||||
|
case ALUOpConstant:
|
||||||
|
if ins.Val != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ins.Op {
|
||||||
|
case ALUOpDiv, ALUOpMod:
|
||||||
|
return nil, errors.New("cannot divide by zero using ALUOpConstant")
|
||||||
|
}
|
||||||
|
// Check for unknown extensions
|
||||||
|
case LoadExtension:
|
||||||
|
switch ins.Num {
|
||||||
|
case ExtLen:
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("extension %d not implemented", ins.Num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure last instruction is a return instruction
|
||||||
|
switch filter[len(filter)-1].(type) {
|
||||||
|
case RetA, RetConstant:
|
||||||
|
default:
|
||||||
|
return nil, errors.New("BPF program must end with RetA or RetConstant")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Though our VM works using disassembled instructions, we
|
||||||
|
// attempt to assemble the input filter anyway to ensure it is compatible
|
||||||
|
// with an operating system VM.
|
||||||
|
_, err := Assemble(filter)
|
||||||
|
|
||||||
|
return &VM{
|
||||||
|
filter: filter,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run runs the VM's BPF program against the input bytes.
|
||||||
|
// Run returns the number of bytes accepted by the BPF program, and any errors
|
||||||
|
// which occurred while processing the program.
|
||||||
|
func (v *VM) Run(in []byte) (int, error) {
|
||||||
|
var (
|
||||||
|
// Registers of the virtual machine
|
||||||
|
regA uint32
|
||||||
|
regX uint32
|
||||||
|
regScratch [16]uint32
|
||||||
|
|
||||||
|
// OK is true if the program should continue processing the next
|
||||||
|
// instruction, or false if not, causing the loop to break
|
||||||
|
ok = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(mdlayher): implement:
|
||||||
|
// - NegateA:
|
||||||
|
// - would require a change from uint32 registers to int32
|
||||||
|
// registers
|
||||||
|
|
||||||
|
// TODO(mdlayher): add interop tests that check signedness of ALU
|
||||||
|
// operations against kernel implementation, and make sure Go
|
||||||
|
// implementation matches behavior
|
||||||
|
|
||||||
|
for i := 0; i < len(v.filter) && ok; i++ {
|
||||||
|
ins := v.filter[i]
|
||||||
|
|
||||||
|
switch ins := ins.(type) {
|
||||||
|
case ALUOpConstant:
|
||||||
|
regA = aluOpConstant(ins, regA)
|
||||||
|
case ALUOpX:
|
||||||
|
regA, ok = aluOpX(ins, regA, regX)
|
||||||
|
case Jump:
|
||||||
|
i += int(ins.Skip)
|
||||||
|
case JumpIf:
|
||||||
|
jump := jumpIf(ins, regA)
|
||||||
|
i += jump
|
||||||
|
case LoadAbsolute:
|
||||||
|
regA, ok = loadAbsolute(ins, in)
|
||||||
|
case LoadConstant:
|
||||||
|
regA, regX = loadConstant(ins, regA, regX)
|
||||||
|
case LoadExtension:
|
||||||
|
regA = loadExtension(ins, in)
|
||||||
|
case LoadIndirect:
|
||||||
|
regA, ok = loadIndirect(ins, in, regX)
|
||||||
|
case LoadMemShift:
|
||||||
|
regX, ok = loadMemShift(ins, in)
|
||||||
|
case LoadScratch:
|
||||||
|
regA, regX = loadScratch(ins, regScratch, regA, regX)
|
||||||
|
case RetA:
|
||||||
|
return int(regA), nil
|
||||||
|
case RetConstant:
|
||||||
|
return int(ins.Val), nil
|
||||||
|
case StoreScratch:
|
||||||
|
regScratch = storeScratch(ins, regScratch, regA, regX)
|
||||||
|
case TAX:
|
||||||
|
regX = regA
|
||||||
|
case TXA:
|
||||||
|
regA = regX
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
512
vendor/golang.org/x/net/bpf/vm_aluop_test.go
generated
vendored
Normal file
512
vendor/golang.org/x/net/bpf/vm_aluop_test.go
generated
vendored
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMALUOpAdd(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpAdd,
|
||||||
|
Val: 3,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
8, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 3, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpSub(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.TAX{},
|
||||||
|
bpf.ALUOpX{
|
||||||
|
Op: bpf.ALUOpSub,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpMul(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpMul,
|
||||||
|
Val: 2,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
6, 2, 3, 4,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 4, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpDiv(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpDiv,
|
||||||
|
Val: 2,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
20, 2, 3, 4,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpDivByZeroALUOpConstant(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpDiv,
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "cannot divide by zero using ALUOpConstant" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpDivByZeroALUOpX(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
// Load byte 0 into X
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.TAX{},
|
||||||
|
// Load byte 1 into A
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 9,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Attempt to perform 1/0
|
||||||
|
bpf.ALUOpX{
|
||||||
|
Op: bpf.ALUOpDiv,
|
||||||
|
},
|
||||||
|
// Return 4 bytes if program does not terminate
|
||||||
|
bpf.LoadConstant{
|
||||||
|
Val: 12,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 3, 4,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpOr(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpOr,
|
||||||
|
Val: 0x01,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x10, 0x03, 0x04,
|
||||||
|
0x05, 0x06, 0x07, 0x08,
|
||||||
|
0x09, 0xff,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 9, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpAnd(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpAnd,
|
||||||
|
Val: 0x0019,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xaa, 0x09,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpShiftLeft(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpShiftLeft,
|
||||||
|
Val: 0x01,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 0x02,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x01, 0xaa,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpShiftRight(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpShiftRight,
|
||||||
|
Val: 0x01,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 0x04,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x08, 0xff, 0xff,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpMod(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpMod,
|
||||||
|
Val: 20,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
30, 0, 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpModByZeroALUOpConstant(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpMod,
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "cannot divide by zero using ALUOpConstant" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpModByZeroALUOpX(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
// Load byte 0 into X
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.TAX{},
|
||||||
|
// Load byte 1 into A
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 9,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Attempt to perform 1%0
|
||||||
|
bpf.ALUOpX{
|
||||||
|
Op: bpf.ALUOpMod,
|
||||||
|
},
|
||||||
|
// Return 4 bytes if program does not terminate
|
||||||
|
bpf.LoadConstant{
|
||||||
|
Val: 12,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 3, 4,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpXor(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpXor,
|
||||||
|
Val: 0x0a,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 0x01,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x0b, 0x00, 0x00, 0x00,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMALUOpUnknown(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: bpf.ALUOpAdd,
|
||||||
|
Val: 1,
|
||||||
|
},
|
||||||
|
// Verify that an unknown operation is a no-op
|
||||||
|
bpf.ALUOpConstant{
|
||||||
|
Op: 100,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 0x02,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
192
vendor/golang.org/x/net/bpf/vm_bpf_test.go
generated
vendored
Normal file
192
vendor/golang.org/x/net/bpf/vm_bpf_test.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A virtualMachine is a BPF virtual machine which can process an
|
||||||
|
// input packet against a BPF program and render a verdict.
|
||||||
|
type virtualMachine interface {
|
||||||
|
Run(in []byte) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// canUseOSVM indicates if the OS BPF VM is available on this platform.
|
||||||
|
func canUseOSVM() bool {
|
||||||
|
// OS BPF VM can only be used on platforms where x/net/ipv4 supports
|
||||||
|
// attaching a BPF program to a socket.
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All BPF tests against both the Go VM and OS VM are assumed to
|
||||||
|
// be used with a UDP socket. As a result, the entire contents
|
||||||
|
// of a UDP datagram is sent through the BPF program, but only
|
||||||
|
// the body after the UDP header will ever be returned in output.
|
||||||
|
|
||||||
|
// testVM sets up a Go BPF VM, and if available, a native OS BPF VM
|
||||||
|
// for integration testing.
|
||||||
|
func testVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func(), error) {
|
||||||
|
goVM, err := bpf.NewVM(filter)
|
||||||
|
if err != nil {
|
||||||
|
// Some tests expect an error, so this error must be returned
|
||||||
|
// instead of fatally exiting the test
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mvm := &multiVirtualMachine{
|
||||||
|
goVM: goVM,
|
||||||
|
|
||||||
|
t: t,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If available, add the OS VM for tests which verify that both the Go
|
||||||
|
// VM and OS VM have exactly the same output for the same input program
|
||||||
|
// and packet.
|
||||||
|
done := func() {}
|
||||||
|
if canUseOSVM() {
|
||||||
|
osVM, osVMDone := testOSVM(t, filter)
|
||||||
|
done = func() { osVMDone() }
|
||||||
|
mvm.osVM = osVM
|
||||||
|
}
|
||||||
|
|
||||||
|
return mvm, done, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// udpHeaderLen is the length of a UDP header.
|
||||||
|
const udpHeaderLen = 8
|
||||||
|
|
||||||
|
// A multiVirtualMachine is a virtualMachine which can call out to both the Go VM
|
||||||
|
// and the native OS VM, if the OS VM is available.
|
||||||
|
type multiVirtualMachine struct {
|
||||||
|
goVM virtualMachine
|
||||||
|
osVM virtualMachine
|
||||||
|
|
||||||
|
t *testing.T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mvm *multiVirtualMachine) Run(in []byte) (int, error) {
|
||||||
|
if len(in) < udpHeaderLen {
|
||||||
|
mvm.t.Fatalf("input must be at least length of UDP header (%d), got: %d",
|
||||||
|
udpHeaderLen, len(in))
|
||||||
|
}
|
||||||
|
|
||||||
|
// All tests have a UDP header as part of input, because the OS VM
|
||||||
|
// packets always will. For the Go VM, this output is trimmed before
|
||||||
|
// being sent back to tests.
|
||||||
|
goOut, goErr := mvm.goVM.Run(in)
|
||||||
|
if goOut >= udpHeaderLen {
|
||||||
|
goOut -= udpHeaderLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Go output is larger than the size of the packet, packet filtering
|
||||||
|
// interop tests must trim the output bytes to the length of the packet.
|
||||||
|
// The BPF VM should not do this on its own, as other uses of it do
|
||||||
|
// not trim the output byte count.
|
||||||
|
trim := len(in) - udpHeaderLen
|
||||||
|
if goOut > trim {
|
||||||
|
goOut = trim
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the OS VM is not available, process using the Go VM alone
|
||||||
|
if mvm.osVM == nil {
|
||||||
|
return goOut, goErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// The OS VM will apply its own UDP header, so remove the pseudo header
|
||||||
|
// that the Go VM needs.
|
||||||
|
osOut, err := mvm.osVM.Run(in[udpHeaderLen:])
|
||||||
|
if err != nil {
|
||||||
|
mvm.t.Fatalf("error while running OS VM: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify both VMs return same number of bytes
|
||||||
|
var mismatch bool
|
||||||
|
if goOut != osOut {
|
||||||
|
mismatch = true
|
||||||
|
mvm.t.Logf("output byte count does not match:\n- go: %v\n- os: %v", goOut, osOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mismatch {
|
||||||
|
mvm.t.Fatal("Go BPF and OS BPF packet outputs do not match")
|
||||||
|
}
|
||||||
|
|
||||||
|
return goOut, goErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// An osVirtualMachine is a virtualMachine which uses the OS's BPF VM for
|
||||||
|
// processing BPF programs.
|
||||||
|
type osVirtualMachine struct {
|
||||||
|
l net.PacketConn
|
||||||
|
s net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting
|
||||||
|
// packets into a UDP listener with a BPF program attached to it.
|
||||||
|
func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) {
|
||||||
|
l, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to open OS VM UDP listener: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
prog, err := bpf.Assemble(filter)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to compile BPF program: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := ipv4.NewPacketConn(l)
|
||||||
|
if err = p.SetBPF(prog); err != nil {
|
||||||
|
t.Fatalf("failed to attach BPF program to listener: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := net.Dial("udp4", l.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to dial connection to listener: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
done := func() {
|
||||||
|
_ = s.Close()
|
||||||
|
_ = l.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &osVirtualMachine{
|
||||||
|
l: l,
|
||||||
|
s: s,
|
||||||
|
}, done
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run sends the input bytes into the OS's BPF VM and returns its verdict.
|
||||||
|
func (vm *osVirtualMachine) Run(in []byte) (int, error) {
|
||||||
|
go func() {
|
||||||
|
_, _ = vm.s.Write(in)
|
||||||
|
}()
|
||||||
|
|
||||||
|
vm.l.SetDeadline(time.Now().Add(50 * time.Millisecond))
|
||||||
|
|
||||||
|
var b [512]byte
|
||||||
|
n, _, err := vm.l.ReadFrom(b[:])
|
||||||
|
if err != nil {
|
||||||
|
// A timeout indicates that BPF filtered out the packet, and thus,
|
||||||
|
// no input should be returned.
|
||||||
|
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
49
vendor/golang.org/x/net/bpf/vm_extension_test.go
generated
vendored
Normal file
49
vendor/golang.org/x/net/bpf/vm_extension_test.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMLoadExtensionNotImplemented(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadExtension{
|
||||||
|
Num: 100,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "extension 100 not implemented" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadExtensionExtLen(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadExtension{
|
||||||
|
Num: bpf.ExtLen,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 4, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
174
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
Normal file
174
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
|
||||||
|
return aluOpCommon(ins.Op, regA, ins.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
|
||||||
|
// Guard against division or modulus by zero by terminating
|
||||||
|
// the program, as the OS BPF VM does
|
||||||
|
if regX == 0 {
|
||||||
|
switch ins.Op {
|
||||||
|
case ALUOpDiv, ALUOpMod:
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aluOpCommon(ins.Op, regA, regX), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
|
||||||
|
switch op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return regA + value
|
||||||
|
case ALUOpSub:
|
||||||
|
return regA - value
|
||||||
|
case ALUOpMul:
|
||||||
|
return regA * value
|
||||||
|
case ALUOpDiv:
|
||||||
|
// Division by zero not permitted by NewVM and aluOpX checks
|
||||||
|
return regA / value
|
||||||
|
case ALUOpOr:
|
||||||
|
return regA | value
|
||||||
|
case ALUOpAnd:
|
||||||
|
return regA & value
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return regA << value
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return regA >> value
|
||||||
|
case ALUOpMod:
|
||||||
|
// Modulus by zero not permitted by NewVM and aluOpX checks
|
||||||
|
return regA % value
|
||||||
|
case ALUOpXor:
|
||||||
|
return regA ^ value
|
||||||
|
default:
|
||||||
|
return regA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func jumpIf(ins JumpIf, value uint32) int {
|
||||||
|
var ok bool
|
||||||
|
inV := uint32(ins.Val)
|
||||||
|
|
||||||
|
switch ins.Cond {
|
||||||
|
case JumpEqual:
|
||||||
|
ok = value == inV
|
||||||
|
case JumpNotEqual:
|
||||||
|
ok = value != inV
|
||||||
|
case JumpGreaterThan:
|
||||||
|
ok = value > inV
|
||||||
|
case JumpLessThan:
|
||||||
|
ok = value < inV
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
ok = value >= inV
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
ok = value <= inV
|
||||||
|
case JumpBitsSet:
|
||||||
|
ok = (value & inV) != 0
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
ok = (value & inV) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return int(ins.SkipTrue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(ins.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
|
||||||
|
offset := int(ins.Off)
|
||||||
|
size := int(ins.Size)
|
||||||
|
|
||||||
|
return loadCommon(in, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
|
||||||
|
switch ins.Dst {
|
||||||
|
case RegA:
|
||||||
|
regA = ins.Val
|
||||||
|
case RegX:
|
||||||
|
regX = ins.Val
|
||||||
|
}
|
||||||
|
|
||||||
|
return regA, regX
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadExtension(ins LoadExtension, in []byte) uint32 {
|
||||||
|
switch ins.Num {
|
||||||
|
case ExtLen:
|
||||||
|
return uint32(len(in))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
|
||||||
|
offset := int(ins.Off) + int(regX)
|
||||||
|
size := int(ins.Size)
|
||||||
|
|
||||||
|
return loadCommon(in, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
|
||||||
|
offset := int(ins.Off)
|
||||||
|
|
||||||
|
if !inBounds(len(in), offset, 0) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask off high 4 bits and multiply low 4 bits by 4
|
||||||
|
return uint32(in[offset]&0x0f) * 4, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func inBounds(inLen int, offset int, size int) bool {
|
||||||
|
return offset+size <= inLen
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadCommon(in []byte, offset int, size int) (uint32, bool) {
|
||||||
|
if !inBounds(len(in), offset, size) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint32(in[offset]), true
|
||||||
|
case 2:
|
||||||
|
return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
|
||||||
|
case 4:
|
||||||
|
return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid load size: %d", size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
|
||||||
|
switch ins.Dst {
|
||||||
|
case RegA:
|
||||||
|
regA = regScratch[ins.N]
|
||||||
|
case RegX:
|
||||||
|
regX = regScratch[ins.N]
|
||||||
|
}
|
||||||
|
|
||||||
|
return regA, regX
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
|
||||||
|
switch ins.Src {
|
||||||
|
case RegA:
|
||||||
|
regScratch[ins.N] = regA
|
||||||
|
case RegX:
|
||||||
|
regScratch[ins.N] = regX
|
||||||
|
}
|
||||||
|
|
||||||
|
return regScratch
|
||||||
|
}
|
380
vendor/golang.org/x/net/bpf/vm_jump_test.go
generated
vendored
Normal file
380
vendor/golang.org/x/net/bpf/vm_jump_test.go
generated
vendored
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMJumpOne(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.Jump{
|
||||||
|
Skip: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpOutOfProgram(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.Jump{
|
||||||
|
Skip: 1,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "cannot jump 1 instructions; jumping past program bounds" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfTrueOutOfProgram(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
SkipTrue: 2,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "cannot jump 2 instructions in true case; jumping past program bounds" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfFalseOutOfProgram(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
SkipFalse: 3,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "cannot jump 3 instructions in false case; jumping past program bounds" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfEqual(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 1,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfNotEqual(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpNotEqual,
|
||||||
|
Val: 1,
|
||||||
|
SkipFalse: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfGreaterThan(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 4,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpGreaterThan,
|
||||||
|
Val: 0x00010202,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 12,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 4, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfLessThan(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 4,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpLessThan,
|
||||||
|
Val: 0xff010203,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 12,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 4, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfGreaterOrEqual(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 4,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpGreaterOrEqual,
|
||||||
|
Val: 0x00010203,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 12,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 4, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfLessOrEqual(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 4,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpLessOrEqual,
|
||||||
|
Val: 0xff010203,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 12,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 4, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfBitsSet(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpBitsSet,
|
||||||
|
Val: 0x1122,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x01, 0x02,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMJumpIfBitsNotSet(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpBitsNotSet,
|
||||||
|
Val: 0x1221,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x01, 0x02,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
246
vendor/golang.org/x/net/bpf/vm_load_test.go
generated
vendored
Normal file
246
vendor/golang.org/x/net/bpf/vm_load_test.go
generated
vendored
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 100,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1, 2, 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadAbsoluteBadInstructionSize(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Size: 5,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid load byte length 0" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadConstantOK(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadConstant{
|
||||||
|
Dst: bpf.RegX,
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
bpf.TXA{},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadIndirectOutOfBounds(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadIndirect{
|
||||||
|
Off: 100,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadMemShiftOutOfBounds(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadMemShift{
|
||||||
|
Off: 100,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
dhcp4Port = 53
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMLoadMemShiftLoadIndirectNoResult(t *testing.T) {
|
||||||
|
vm, in, done := testDHCPv4(t)
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
// Append mostly empty UDP header with incorrect DHCPv4 port
|
||||||
|
in = append(in, []byte{
|
||||||
|
0, 0,
|
||||||
|
0, dhcp4Port + 1,
|
||||||
|
0, 0,
|
||||||
|
0, 0,
|
||||||
|
}...)
|
||||||
|
|
||||||
|
out, err := vm.Run(in)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 0, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadMemShiftLoadIndirectOK(t *testing.T) {
|
||||||
|
vm, in, done := testDHCPv4(t)
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
// Append mostly empty UDP header with correct DHCPv4 port
|
||||||
|
in = append(in, []byte{
|
||||||
|
0, 0,
|
||||||
|
0, dhcp4Port,
|
||||||
|
0, 0,
|
||||||
|
0, 0,
|
||||||
|
}...)
|
||||||
|
|
||||||
|
out, err := vm.Run(in)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := len(in)-8, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDHCPv4(t *testing.T) (virtualMachine, []byte, func()) {
|
||||||
|
// DHCPv4 test data courtesy of David Anderson:
|
||||||
|
// https://github.com/google/netboot/blob/master/dhcp4/conn_linux.go#L59-L70
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
// Load IPv4 packet length
|
||||||
|
bpf.LoadMemShift{Off: 8},
|
||||||
|
// Get UDP dport
|
||||||
|
bpf.LoadIndirect{Off: 8 + 2, Size: 2},
|
||||||
|
// Correct dport?
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpEqual, Val: dhcp4Port, SkipFalse: 1},
|
||||||
|
// Accept
|
||||||
|
bpf.RetConstant{Val: 1500},
|
||||||
|
// Ignore
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimal requirements to make a valid IPv4 header
|
||||||
|
h := &ipv4.Header{
|
||||||
|
Len: ipv4.HeaderLen,
|
||||||
|
Src: net.IPv4(192, 168, 1, 1),
|
||||||
|
Dst: net.IPv4(192, 168, 1, 2),
|
||||||
|
}
|
||||||
|
hb, err := h.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to marshal IPv4 header: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hb = append([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
}, hb...)
|
||||||
|
|
||||||
|
return vm, hb, done
|
||||||
|
}
|
115
vendor/golang.org/x/net/bpf/vm_ret_test.go
generated
vendored
Normal file
115
vendor/golang.org/x/net/bpf/vm_ret_test.go
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMRetA(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
9,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMRetALargerThanInput(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 2,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 255,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMRetConstant(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 9,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 1, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMRetConstantLargerThanInput(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 16,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0, 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
247
vendor/golang.org/x/net/bpf/vm_scratch_test.go
generated
vendored
Normal file
247
vendor/golang.org/x/net/bpf/vm_scratch_test.go
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegA,
|
||||||
|
N: -1,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegA,
|
||||||
|
N: 16,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMStoreScratchUnknownSourceRegister(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: 100,
|
||||||
|
N: 0,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid source register 100" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: bpf.RegX,
|
||||||
|
N: -1,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: bpf.RegX,
|
||||||
|
N: 16,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: 100,
|
||||||
|
N: 0,
|
||||||
|
},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if errStr(err) != "assembling instruction 1: invalid target register 100" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMStoreScratchLoadScratchOneValue(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
// Load byte 255
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Copy to X and store in scratch[0]
|
||||||
|
bpf.TAX{},
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegX,
|
||||||
|
N: 0,
|
||||||
|
},
|
||||||
|
// Load byte 1
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 9,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Overwrite 1 with 255 from scratch[0]
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: bpf.RegA,
|
||||||
|
N: 0,
|
||||||
|
},
|
||||||
|
// Return 255
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
255, 1, 2,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 3, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
// Load byte 10
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 8,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Store in scratch[0]
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegA,
|
||||||
|
N: 0,
|
||||||
|
},
|
||||||
|
// Load byte 20
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 9,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Store in scratch[1]
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegA,
|
||||||
|
N: 1,
|
||||||
|
},
|
||||||
|
// Load byte 30
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 10,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Store in scratch[2]
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegA,
|
||||||
|
N: 2,
|
||||||
|
},
|
||||||
|
// Load byte 1
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: 11,
|
||||||
|
Size: 1,
|
||||||
|
},
|
||||||
|
// Store in scratch[3]
|
||||||
|
bpf.StoreScratch{
|
||||||
|
Src: bpf.RegA,
|
||||||
|
N: 3,
|
||||||
|
},
|
||||||
|
// Load in byte 10 to X
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: bpf.RegX,
|
||||||
|
N: 0,
|
||||||
|
},
|
||||||
|
// Copy X -> A
|
||||||
|
bpf.TXA{},
|
||||||
|
// Verify value is 10
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 10,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
// Fail test if incorrect
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
// Load in byte 20 to A
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: bpf.RegA,
|
||||||
|
N: 1,
|
||||||
|
},
|
||||||
|
// Verify value is 20
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 20,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
// Fail test if incorrect
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
// Load in byte 30 to A
|
||||||
|
bpf.LoadScratch{
|
||||||
|
Dst: bpf.RegA,
|
||||||
|
N: 2,
|
||||||
|
},
|
||||||
|
// Verify value is 30
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: 30,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
// Fail test if incorrect
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
// Return first two bytes on success
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to load BPF program: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
out, err := vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
10, 20, 30, 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
if want, got := 2, out; want != got {
|
||||||
|
t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
|
||||||
|
want, got)
|
||||||
|
}
|
||||||
|
}
|
144
vendor/golang.org/x/net/bpf/vm_test.go
generated
vendored
Normal file
144
vendor/golang.org/x/net/bpf/vm_test.go
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package bpf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ bpf.Instruction = unknown{}
|
||||||
|
|
||||||
|
type unknown struct{}
|
||||||
|
|
||||||
|
func (unknown) Assemble() (bpf.RawInstruction, error) {
|
||||||
|
return bpf.RawInstruction{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMUnknownInstruction(t *testing.T) {
|
||||||
|
vm, done, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadConstant{
|
||||||
|
Dst: bpf.RegA,
|
||||||
|
Val: 100,
|
||||||
|
},
|
||||||
|
// Should terminate the program with an error immediately
|
||||||
|
unknown{},
|
||||||
|
bpf.RetA{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
_, err = vm.Run([]byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x00,
|
||||||
|
})
|
||||||
|
if errStr(err) != "unknown Instruction at index 1: bpf_test.unknown" {
|
||||||
|
t.Fatalf("unexpected error while running program: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMNoReturnInstruction(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{
|
||||||
|
bpf.LoadConstant{
|
||||||
|
Dst: bpf.RegA,
|
||||||
|
Val: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if errStr(err) != "BPF program must end with RetA or RetConstant" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMNoInputInstructions(t *testing.T) {
|
||||||
|
_, _, err := testVM(t, []bpf.Instruction{})
|
||||||
|
if errStr(err) != "one or more Instructions must be specified" {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExampleNewVM demonstrates usage of a VM, using an Ethernet frame
|
||||||
|
// as input and checking its EtherType to determine if it should be accepted.
|
||||||
|
func ExampleNewVM() {
|
||||||
|
// Offset | Length | Comment
|
||||||
|
// -------------------------
|
||||||
|
// 00 | 06 | Ethernet destination MAC address
|
||||||
|
// 06 | 06 | Ethernet source MAC address
|
||||||
|
// 12 | 02 | Ethernet EtherType
|
||||||
|
const (
|
||||||
|
etOff = 12
|
||||||
|
etLen = 2
|
||||||
|
|
||||||
|
etARP = 0x0806
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set up a VM to filter traffic based on if its EtherType
|
||||||
|
// matches the ARP EtherType.
|
||||||
|
vm, err := bpf.NewVM([]bpf.Instruction{
|
||||||
|
// Load EtherType value from Ethernet header
|
||||||
|
bpf.LoadAbsolute{
|
||||||
|
Off: etOff,
|
||||||
|
Size: etLen,
|
||||||
|
},
|
||||||
|
// If EtherType is equal to the ARP EtherType, jump to allow
|
||||||
|
// packet to be accepted
|
||||||
|
bpf.JumpIf{
|
||||||
|
Cond: bpf.JumpEqual,
|
||||||
|
Val: etARP,
|
||||||
|
SkipTrue: 1,
|
||||||
|
},
|
||||||
|
// EtherType does not match the ARP EtherType
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 0,
|
||||||
|
},
|
||||||
|
// EtherType matches the ARP EtherType, accept up to 1500
|
||||||
|
// bytes of packet
|
||||||
|
bpf.RetConstant{
|
||||||
|
Val: 1500,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to load BPF program: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an Ethernet frame with the ARP EtherType for testing
|
||||||
|
frame := []byte{
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
|
||||||
|
0x08, 0x06,
|
||||||
|
// Payload omitted for brevity
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run our VM's BPF program using the Ethernet frame as input
|
||||||
|
out, err := vm.Run(frame)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to accept Ethernet frame: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BPF VM can return a byte count greater than the number of input
|
||||||
|
// bytes, so trim the output to match the input byte length
|
||||||
|
if out > len(frame) {
|
||||||
|
out = len(frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("out: %d bytes", out)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// out: 14 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// errStr returns the string representation of an error, or
|
||||||
|
// "<nil>" if it is nil.
|
||||||
|
func errStr(err error) string {
|
||||||
|
if err == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
|
||||||
|
return err.Error()
|
||||||
|
}
|
180
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
Normal file
180
vendor/golang.org/x/net/internal/iana/const.go
generated
vendored
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
// go generate gen.go
|
||||||
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
|
||||||
|
package iana // import "golang.org/x/net/internal/iana"
|
||||||
|
|
||||||
|
// Differentiated Services Field Codepoints (DSCP), Updated: 2013-06-25
|
||||||
|
const (
|
||||||
|
DiffServCS0 = 0x0 // CS0
|
||||||
|
DiffServCS1 = 0x20 // CS1
|
||||||
|
DiffServCS2 = 0x40 // CS2
|
||||||
|
DiffServCS3 = 0x60 // CS3
|
||||||
|
DiffServCS4 = 0x80 // CS4
|
||||||
|
DiffServCS5 = 0xa0 // CS5
|
||||||
|
DiffServCS6 = 0xc0 // CS6
|
||||||
|
DiffServCS7 = 0xe0 // CS7
|
||||||
|
DiffServAF11 = 0x28 // AF11
|
||||||
|
DiffServAF12 = 0x30 // AF12
|
||||||
|
DiffServAF13 = 0x38 // AF13
|
||||||
|
DiffServAF21 = 0x48 // AF21
|
||||||
|
DiffServAF22 = 0x50 // AF22
|
||||||
|
DiffServAF23 = 0x58 // AF23
|
||||||
|
DiffServAF31 = 0x68 // AF31
|
||||||
|
DiffServAF32 = 0x70 // AF32
|
||||||
|
DiffServAF33 = 0x78 // AF33
|
||||||
|
DiffServAF41 = 0x88 // AF41
|
||||||
|
DiffServAF42 = 0x90 // AF42
|
||||||
|
DiffServAF43 = 0x98 // AF43
|
||||||
|
DiffServEFPHB = 0xb8 // EF PHB
|
||||||
|
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
||||||
|
)
|
||||||
|
|
||||||
|
// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
|
||||||
|
const (
|
||||||
|
NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
|
||||||
|
ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
|
||||||
|
ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
|
||||||
|
CongestionExperienced = 0x3 // CE (Congestion Experienced)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Protocol Numbers, Updated: 2015-10-06
|
||||||
|
const (
|
||||||
|
ProtocolIP = 0 // IPv4 encapsulation, pseudo protocol number
|
||||||
|
ProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
||||||
|
ProtocolICMP = 1 // Internet Control Message
|
||||||
|
ProtocolIGMP = 2 // Internet Group Management
|
||||||
|
ProtocolGGP = 3 // Gateway-to-Gateway
|
||||||
|
ProtocolIPv4 = 4 // IPv4 encapsulation
|
||||||
|
ProtocolST = 5 // Stream
|
||||||
|
ProtocolTCP = 6 // Transmission Control
|
||||||
|
ProtocolCBT = 7 // CBT
|
||||||
|
ProtocolEGP = 8 // Exterior Gateway Protocol
|
||||||
|
ProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
|
||||||
|
ProtocolBBNRCCMON = 10 // BBN RCC Monitoring
|
||||||
|
ProtocolNVPII = 11 // Network Voice Protocol
|
||||||
|
ProtocolPUP = 12 // PUP
|
||||||
|
ProtocolEMCON = 14 // EMCON
|
||||||
|
ProtocolXNET = 15 // Cross Net Debugger
|
||||||
|
ProtocolCHAOS = 16 // Chaos
|
||||||
|
ProtocolUDP = 17 // User Datagram
|
||||||
|
ProtocolMUX = 18 // Multiplexing
|
||||||
|
ProtocolDCNMEAS = 19 // DCN Measurement Subsystems
|
||||||
|
ProtocolHMP = 20 // Host Monitoring
|
||||||
|
ProtocolPRM = 21 // Packet Radio Measurement
|
||||||
|
ProtocolXNSIDP = 22 // XEROX NS IDP
|
||||||
|
ProtocolTRUNK1 = 23 // Trunk-1
|
||||||
|
ProtocolTRUNK2 = 24 // Trunk-2
|
||||||
|
ProtocolLEAF1 = 25 // Leaf-1
|
||||||
|
ProtocolLEAF2 = 26 // Leaf-2
|
||||||
|
ProtocolRDP = 27 // Reliable Data Protocol
|
||||||
|
ProtocolIRTP = 28 // Internet Reliable Transaction
|
||||||
|
ProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
|
||||||
|
ProtocolNETBLT = 30 // Bulk Data Transfer Protocol
|
||||||
|
ProtocolMFENSP = 31 // MFE Network Services Protocol
|
||||||
|
ProtocolMERITINP = 32 // MERIT Internodal Protocol
|
||||||
|
ProtocolDCCP = 33 // Datagram Congestion Control Protocol
|
||||||
|
Protocol3PC = 34 // Third Party Connect Protocol
|
||||||
|
ProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
|
||||||
|
ProtocolXTP = 36 // XTP
|
||||||
|
ProtocolDDP = 37 // Datagram Delivery Protocol
|
||||||
|
ProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
|
||||||
|
ProtocolTPPP = 39 // TP++ Transport Protocol
|
||||||
|
ProtocolIL = 40 // IL Transport Protocol
|
||||||
|
ProtocolIPv6 = 41 // IPv6 encapsulation
|
||||||
|
ProtocolSDRP = 42 // Source Demand Routing Protocol
|
||||||
|
ProtocolIPv6Route = 43 // Routing Header for IPv6
|
||||||
|
ProtocolIPv6Frag = 44 // Fragment Header for IPv6
|
||||||
|
ProtocolIDRP = 45 // Inter-Domain Routing Protocol
|
||||||
|
ProtocolRSVP = 46 // Reservation Protocol
|
||||||
|
ProtocolGRE = 47 // Generic Routing Encapsulation
|
||||||
|
ProtocolDSR = 48 // Dynamic Source Routing Protocol
|
||||||
|
ProtocolBNA = 49 // BNA
|
||||||
|
ProtocolESP = 50 // Encap Security Payload
|
||||||
|
ProtocolAH = 51 // Authentication Header
|
||||||
|
ProtocolINLSP = 52 // Integrated Net Layer Security TUBA
|
||||||
|
ProtocolNARP = 54 // NBMA Address Resolution Protocol
|
||||||
|
ProtocolMOBILE = 55 // IP Mobility
|
||||||
|
ProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
|
||||||
|
ProtocolSKIP = 57 // SKIP
|
||||||
|
ProtocolIPv6ICMP = 58 // ICMP for IPv6
|
||||||
|
ProtocolIPv6NoNxt = 59 // No Next Header for IPv6
|
||||||
|
ProtocolIPv6Opts = 60 // Destination Options for IPv6
|
||||||
|
ProtocolCFTP = 62 // CFTP
|
||||||
|
ProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
|
||||||
|
ProtocolKRYPTOLAN = 65 // Kryptolan
|
||||||
|
ProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
|
||||||
|
ProtocolIPPC = 67 // Internet Pluribus Packet Core
|
||||||
|
ProtocolSATMON = 69 // SATNET Monitoring
|
||||||
|
ProtocolVISA = 70 // VISA Protocol
|
||||||
|
ProtocolIPCV = 71 // Internet Packet Core Utility
|
||||||
|
ProtocolCPNX = 72 // Computer Protocol Network Executive
|
||||||
|
ProtocolCPHB = 73 // Computer Protocol Heart Beat
|
||||||
|
ProtocolWSN = 74 // Wang Span Network
|
||||||
|
ProtocolPVP = 75 // Packet Video Protocol
|
||||||
|
ProtocolBRSATMON = 76 // Backroom SATNET Monitoring
|
||||||
|
ProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
|
||||||
|
ProtocolWBMON = 78 // WIDEBAND Monitoring
|
||||||
|
ProtocolWBEXPAK = 79 // WIDEBAND EXPAK
|
||||||
|
ProtocolISOIP = 80 // ISO Internet Protocol
|
||||||
|
ProtocolVMTP = 81 // VMTP
|
||||||
|
ProtocolSECUREVMTP = 82 // SECURE-VMTP
|
||||||
|
ProtocolVINES = 83 // VINES
|
||||||
|
ProtocolTTP = 84 // Transaction Transport Protocol
|
||||||
|
ProtocolIPTM = 84 // Internet Protocol Traffic Manager
|
||||||
|
ProtocolNSFNETIGP = 85 // NSFNET-IGP
|
||||||
|
ProtocolDGP = 86 // Dissimilar Gateway Protocol
|
||||||
|
ProtocolTCF = 87 // TCF
|
||||||
|
ProtocolEIGRP = 88 // EIGRP
|
||||||
|
ProtocolOSPFIGP = 89 // OSPFIGP
|
||||||
|
ProtocolSpriteRPC = 90 // Sprite RPC Protocol
|
||||||
|
ProtocolLARP = 91 // Locus Address Resolution Protocol
|
||||||
|
ProtocolMTP = 92 // Multicast Transport Protocol
|
||||||
|
ProtocolAX25 = 93 // AX.25 Frames
|
||||||
|
ProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
|
||||||
|
ProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
|
||||||
|
ProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
|
||||||
|
ProtocolENCAP = 98 // Encapsulation Header
|
||||||
|
ProtocolGMTP = 100 // GMTP
|
||||||
|
ProtocolIFMP = 101 // Ipsilon Flow Management Protocol
|
||||||
|
ProtocolPNNI = 102 // PNNI over IP
|
||||||
|
ProtocolPIM = 103 // Protocol Independent Multicast
|
||||||
|
ProtocolARIS = 104 // ARIS
|
||||||
|
ProtocolSCPS = 105 // SCPS
|
||||||
|
ProtocolQNX = 106 // QNX
|
||||||
|
ProtocolAN = 107 // Active Networks
|
||||||
|
ProtocolIPComp = 108 // IP Payload Compression Protocol
|
||||||
|
ProtocolSNP = 109 // Sitara Networks Protocol
|
||||||
|
ProtocolCompaqPeer = 110 // Compaq Peer Protocol
|
||||||
|
ProtocolIPXinIP = 111 // IPX in IP
|
||||||
|
ProtocolVRRP = 112 // Virtual Router Redundancy Protocol
|
||||||
|
ProtocolPGM = 113 // PGM Reliable Transport Protocol
|
||||||
|
ProtocolL2TP = 115 // Layer Two Tunneling Protocol
|
||||||
|
ProtocolDDX = 116 // D-II Data Exchange (DDX)
|
||||||
|
ProtocolIATP = 117 // Interactive Agent Transfer Protocol
|
||||||
|
ProtocolSTP = 118 // Schedule Transfer Protocol
|
||||||
|
ProtocolSRP = 119 // SpectraLink Radio Protocol
|
||||||
|
ProtocolUTI = 120 // UTI
|
||||||
|
ProtocolSMP = 121 // Simple Message Protocol
|
||||||
|
ProtocolPTP = 123 // Performance Transparency Protocol
|
||||||
|
ProtocolISIS = 124 // ISIS over IPv4
|
||||||
|
ProtocolFIRE = 125 // FIRE
|
||||||
|
ProtocolCRTP = 126 // Combat Radio Transport Protocol
|
||||||
|
ProtocolCRUDP = 127 // Combat Radio User Datagram
|
||||||
|
ProtocolSSCOPMCE = 128 // SSCOPMCE
|
||||||
|
ProtocolIPLT = 129 // IPLT
|
||||||
|
ProtocolSPS = 130 // Secure Packet Shield
|
||||||
|
ProtocolPIPE = 131 // Private IP Encapsulation within IP
|
||||||
|
ProtocolSCTP = 132 // Stream Control Transmission Protocol
|
||||||
|
ProtocolFC = 133 // Fibre Channel
|
||||||
|
ProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
|
||||||
|
ProtocolMobilityHeader = 135 // Mobility Header
|
||||||
|
ProtocolUDPLite = 136 // UDPLite
|
||||||
|
ProtocolMPLSinIP = 137 // MPLS-in-IP
|
||||||
|
ProtocolMANET = 138 // MANET Protocols
|
||||||
|
ProtocolHIP = 139 // Host Identity Protocol
|
||||||
|
ProtocolShim6 = 140 // Shim6 Protocol
|
||||||
|
ProtocolWESP = 141 // Wrapped Encapsulating Security Payload
|
||||||
|
ProtocolROHC = 142 // Robust Header Compression
|
||||||
|
ProtocolReserved = 255 // Reserved
|
||||||
|
)
|
293
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
Normal file
293
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
//go:generate go run gen.go
|
||||||
|
|
||||||
|
// This program generates internet protocol constants and tables by
|
||||||
|
// reading IANA protocol registries.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var registries = []struct {
|
||||||
|
url string
|
||||||
|
parse func(io.Writer, io.Reader) error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
||||||
|
parseDSCPRegistry,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
|
||||||
|
parseTOSTCByte,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
||||||
|
parseProtocolNumbers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var bb bytes.Buffer
|
||||||
|
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||||
|
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
|
||||||
|
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
||||||
|
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
||||||
|
for _, r := range registries {
|
||||||
|
resp, err := http.Get(r.url)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := r.parse(&bb, resp.Body); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&bb, "\n")
|
||||||
|
}
|
||||||
|
b, err := format.Source(bb.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var dr dscpRegistry
|
||||||
|
if err := dec.Decode(&dr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
drs := dr.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, dr := range drs {
|
||||||
|
fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type dscpRegistry struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
Note string `xml:"note"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
PoolRecords []struct {
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Space string `xml:"space"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
Records []struct {
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Space string `xml:"space"`
|
||||||
|
} `xml:"registry>registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonDSCPRecord struct {
|
||||||
|
OrigName string
|
||||||
|
Name string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (drr *dscpRegistry) escape() []canonDSCPRecord {
|
||||||
|
drs := make([]canonDSCPRecord, len(drr.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"+", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, dr := range drr.Records {
|
||||||
|
s := strings.TrimSpace(dr.Name)
|
||||||
|
drs[i].OrigName = s
|
||||||
|
drs[i].Name = sr.Replace(s)
|
||||||
|
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
drs[i].Value = int(n) << 2
|
||||||
|
}
|
||||||
|
return drs
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTOSTCByte(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var ttb tosTCByte
|
||||||
|
if err := dec.Decode(&ttb); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
trs := ttb.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, tr := range trs {
|
||||||
|
fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type tosTCByte struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
Note string `xml:"note"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
Records []struct {
|
||||||
|
Binary string `xml:"binary"`
|
||||||
|
Keyword string `xml:"keyword"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonTOSTCByteRecord struct {
|
||||||
|
OrigKeyword string
|
||||||
|
Keyword string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
|
||||||
|
trs := make([]canonTOSTCByteRecord, len(ttb.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"Capable", "",
|
||||||
|
"(", "",
|
||||||
|
")", "",
|
||||||
|
"+", "",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, tr := range ttb.Records {
|
||||||
|
s := strings.TrimSpace(tr.Keyword)
|
||||||
|
trs[i].OrigKeyword = s
|
||||||
|
ss := strings.Split(s, " ")
|
||||||
|
if len(ss) > 1 {
|
||||||
|
trs[i].Keyword = strings.Join(ss[1:], " ")
|
||||||
|
} else {
|
||||||
|
trs[i].Keyword = ss[0]
|
||||||
|
}
|
||||||
|
trs[i].Keyword = sr.Replace(trs[i].Keyword)
|
||||||
|
n, err := strconv.ParseUint(tr.Binary, 2, 8)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
trs[i].Value = int(n)
|
||||||
|
}
|
||||||
|
return trs
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var pn protocolNumbers
|
||||||
|
if err := dec.Decode(&pn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prs := pn.escape()
|
||||||
|
prs = append([]canonProtocolRecord{{
|
||||||
|
Name: "IP",
|
||||||
|
Descr: "IPv4 encapsulation, pseudo protocol number",
|
||||||
|
Value: 0,
|
||||||
|
}}, prs...)
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
|
||||||
|
s := pr.Descr
|
||||||
|
if s == "" {
|
||||||
|
s = pr.OrigName
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "// %s\n", s)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type protocolNumbers struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
RegTitle string `xml:"registry>title"`
|
||||||
|
Note string `xml:"registry>note"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Name string `xml:"name"`
|
||||||
|
Descr string `xml:"description"`
|
||||||
|
} `xml:"registry>record"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonProtocolRecord struct {
|
||||||
|
OrigName string
|
||||||
|
Name string
|
||||||
|
Descr string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
||||||
|
prs := make([]canonProtocolRecord, len(pn.Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"-in-", "in",
|
||||||
|
"-within-", "within",
|
||||||
|
"-over-", "over",
|
||||||
|
"+", "P",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, pr := range pn.Records {
|
||||||
|
if strings.Contains(pr.Name, "Deprecated") ||
|
||||||
|
strings.Contains(pr.Name, "deprecated") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
prs[i].OrigName = pr.Name
|
||||||
|
s := strings.TrimSpace(pr.Name)
|
||||||
|
switch pr.Name {
|
||||||
|
case "ISIS over IPv4":
|
||||||
|
prs[i].Name = "ISIS"
|
||||||
|
case "manet":
|
||||||
|
prs[i].Name = "MANET"
|
||||||
|
default:
|
||||||
|
prs[i].Name = sr.Replace(s)
|
||||||
|
}
|
||||||
|
ss := strings.Split(pr.Descr, "\n")
|
||||||
|
for i := range ss {
|
||||||
|
ss[i] = strings.TrimSpace(ss[i])
|
||||||
|
}
|
||||||
|
if len(ss) > 1 {
|
||||||
|
prs[i].Descr = strings.Join(ss, " ")
|
||||||
|
} else {
|
||||||
|
prs[i].Descr = ss[0]
|
||||||
|
}
|
||||||
|
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||||
|
}
|
||||||
|
return prs
|
||||||
|
}
|
93
vendor/golang.org/x/net/ipv4/bpf_test.go
generated
vendored
Normal file
93
vendor/golang.org/x/net/ipv4/bpf_test.go
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBPF(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
p := ipv4.NewPacketConn(l)
|
||||||
|
|
||||||
|
// This filter accepts UDP packets whose first payload byte is
|
||||||
|
// even.
|
||||||
|
prog, err := bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Load the first byte of the payload (skipping UDP header).
|
||||||
|
bpf.LoadAbsolute{Off: 8, Size: 1},
|
||||||
|
// Select LSB of the byte.
|
||||||
|
bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
|
||||||
|
// Byte is even?
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
|
||||||
|
// Accept.
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Ignore.
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("compiling BPF: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.SetBPF(prog); err != nil {
|
||||||
|
t.Fatalf("attaching filter to Conn: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := net.Dial("udp4", l.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
go func() {
|
||||||
|
for i := byte(0); i < 10; i++ {
|
||||||
|
s.Write([]byte{i})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
l.SetDeadline(time.Now().Add(2 * time.Second))
|
||||||
|
seen := make([]bool, 5)
|
||||||
|
for {
|
||||||
|
var b [512]byte
|
||||||
|
n, _, err := l.ReadFrom(b[:])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reading from listener: %s", err)
|
||||||
|
}
|
||||||
|
if n != 1 {
|
||||||
|
t.Fatalf("unexpected packet length, want 1, got %d", n)
|
||||||
|
}
|
||||||
|
if b[0] >= 10 {
|
||||||
|
t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
|
||||||
|
}
|
||||||
|
if b[0]%2 != 0 {
|
||||||
|
t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
|
||||||
|
}
|
||||||
|
seen[b[0]/2] = true
|
||||||
|
|
||||||
|
seenAll := true
|
||||||
|
for _, v := range seen {
|
||||||
|
if !v {
|
||||||
|
seenAll = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if seenAll {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
vendor/golang.org/x/net/ipv4/bpfopt_linux.go
generated
vendored
Normal file
27
vendor/golang.org/x/net/ipv4/bpfopt_linux.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetBPF attaches a BPF program to the connection.
|
||||||
|
//
|
||||||
|
// Only supported on Linux.
|
||||||
|
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prog := sysSockFProg{
|
||||||
|
Len: uint16(len(filter)),
|
||||||
|
Filter: (*sysSockFilter)(unsafe.Pointer(&filter[0])),
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, sysSOL_SOCKET, sysSO_ATTACH_FILTER, unsafe.Pointer(&prog), uint32(unsafe.Sizeof(prog))))
|
||||||
|
}
|
16
vendor/golang.org/x/net/ipv4/bpfopt_stub.go
generated
vendored
Normal file
16
vendor/golang.org/x/net/ipv4/bpfopt_stub.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "golang.org/x/net/bpf"
|
||||||
|
|
||||||
|
// SetBPF attaches a BPF program to the connection.
|
||||||
|
//
|
||||||
|
// Only supported on Linux.
|
||||||
|
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
70
vendor/golang.org/x/net/ipv4/control.go
generated
vendored
Normal file
70
vendor/golang.org/x/net/ipv4/control.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rawOpt struct {
|
||||||
|
sync.RWMutex
|
||||||
|
cflags ControlFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rawOpt) set(f ControlFlags) { c.cflags |= f }
|
||||||
|
func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f }
|
||||||
|
func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 }
|
||||||
|
|
||||||
|
type ControlFlags uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
FlagTTL ControlFlags = 1 << iota // pass the TTL on the received packet
|
||||||
|
FlagSrc // pass the source address on the received packet
|
||||||
|
FlagDst // pass the destination address on the received packet
|
||||||
|
FlagInterface // pass the interface index on the received packet
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ControlMessage represents per packet basis IP-level socket options.
|
||||||
|
type ControlMessage struct {
|
||||||
|
// Receiving socket options: SetControlMessage allows to
|
||||||
|
// receive the options from the protocol stack using ReadFrom
|
||||||
|
// method of PacketConn or RawConn.
|
||||||
|
//
|
||||||
|
// Specifying socket options: ControlMessage for WriteTo
|
||||||
|
// method of PacketConn or RawConn allows to send the options
|
||||||
|
// to the protocol stack.
|
||||||
|
//
|
||||||
|
TTL int // time-to-live, receiving only
|
||||||
|
Src net.IP // source address, specifying only
|
||||||
|
Dst net.IP // destination address, receiving only
|
||||||
|
IfIndex int // interface index, must be 1 <= value when specifying
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cm *ControlMessage) String() string {
|
||||||
|
if cm == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ttl=%d src=%v dst=%v ifindex=%d", cm.TTL, cm.Src, cm.Dst, cm.IfIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ancillary data socket options
|
||||||
|
const (
|
||||||
|
ctlTTL = iota // header field
|
||||||
|
ctlSrc // header field
|
||||||
|
ctlDst // header field
|
||||||
|
ctlInterface // inbound or outbound interface
|
||||||
|
ctlPacketInfo // inbound or outbound packet path
|
||||||
|
ctlMax
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ctlOpt represents a binding for ancillary data socket option.
|
||||||
|
type ctlOpt struct {
|
||||||
|
name int // option name, must be equal or greater than 1
|
||||||
|
length int // option length
|
||||||
|
marshal func([]byte, *ControlMessage) []byte
|
||||||
|
parse func(*ControlMessage, []byte)
|
||||||
|
}
|
40
vendor/golang.org/x/net/ipv4/control_bsd.go
generated
vendored
Normal file
40
vendor/golang.org/x/net/ipv4/control_bsd.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func marshalDst(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIP
|
||||||
|
m.Type = sysIP_RECVDSTADDR
|
||||||
|
m.SetLen(syscall.CmsgLen(net.IPv4len))
|
||||||
|
return b[syscall.CmsgSpace(net.IPv4len):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDst(cm *ControlMessage, b []byte) {
|
||||||
|
cm.Dst = b[:net.IPv4len]
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalInterface(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIP
|
||||||
|
m.Type = sysIP_RECVIF
|
||||||
|
m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
|
||||||
|
return b[syscall.CmsgSpace(syscall.SizeofSockaddrDatalink):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInterface(cm *ControlMessage, b []byte) {
|
||||||
|
sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0]))
|
||||||
|
cm.IfIndex = int(sadl.Index)
|
||||||
|
}
|
37
vendor/golang.org/x/net/ipv4/control_pktinfo.go
generated
vendored
Normal file
37
vendor/golang.org/x/net/ipv4/control_pktinfo.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin linux
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func marshalPacketInfo(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIP
|
||||||
|
m.Type = sysIP_PKTINFO
|
||||||
|
m.SetLen(syscall.CmsgLen(sysSizeofInetPktinfo))
|
||||||
|
if cm != nil {
|
||||||
|
pi := (*sysInetPktinfo)(unsafe.Pointer(&b[syscall.CmsgLen(0)]))
|
||||||
|
if ip := cm.Src.To4(); ip != nil {
|
||||||
|
copy(pi.Spec_dst[:], ip)
|
||||||
|
}
|
||||||
|
if cm.IfIndex > 0 {
|
||||||
|
pi.setIfindex(cm.IfIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b[syscall.CmsgSpace(sysSizeofInetPktinfo):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePacketInfo(cm *ControlMessage, b []byte) {
|
||||||
|
pi := (*sysInetPktinfo)(unsafe.Pointer(&b[0]))
|
||||||
|
cm.IfIndex = int(pi.Ifindex)
|
||||||
|
cm.Dst = pi.Addr[:]
|
||||||
|
}
|
23
vendor/golang.org/x/net/ipv4/control_stub.go
generated
vendored
Normal file
23
vendor/golang.org/x/net/ipv4/control_stub.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlMessage(opt *rawOpt) []byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalControlMessage(cm *ControlMessage) []byte {
|
||||||
|
return nil
|
||||||
|
}
|
164
vendor/golang.org/x/net/ipv4/control_unix.go
generated
vendored
Normal file
164
vendor/golang.org/x/net/ipv4/control_unix.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
|
opt.Lock()
|
||||||
|
defer opt.Unlock()
|
||||||
|
if cf&FlagTTL != 0 && sockOpts[ssoReceiveTTL].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceiveTTL], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(FlagTTL)
|
||||||
|
} else {
|
||||||
|
opt.clear(FlagTTL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sockOpts[ssoPacketInfo].name > 0 {
|
||||||
|
if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoPacketInfo], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
|
||||||
|
} else {
|
||||||
|
opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if cf&FlagDst != 0 && sockOpts[ssoReceiveDst].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceiveDst], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(FlagDst)
|
||||||
|
} else {
|
||||||
|
opt.clear(FlagDst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cf&FlagInterface != 0 && sockOpts[ssoReceiveInterface].name > 0 {
|
||||||
|
if err := setInt(fd, &sockOpts[ssoReceiveInterface], boolint(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if on {
|
||||||
|
opt.set(FlagInterface)
|
||||||
|
} else {
|
||||||
|
opt.clear(FlagInterface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||||
|
opt.RLock()
|
||||||
|
var l int
|
||||||
|
if opt.isset(FlagTTL) && ctlOpts[ctlTTL].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlTTL].length)
|
||||||
|
}
|
||||||
|
if ctlOpts[ctlPacketInfo].name > 0 {
|
||||||
|
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if opt.isset(FlagDst) && ctlOpts[ctlDst].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlDst].length)
|
||||||
|
}
|
||||||
|
if opt.isset(FlagInterface) && ctlOpts[ctlInterface].name > 0 {
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlInterface].length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if l > 0 {
|
||||||
|
oob = make([]byte, l)
|
||||||
|
b := oob
|
||||||
|
if opt.isset(FlagTTL) && ctlOpts[ctlTTL].name > 0 {
|
||||||
|
b = ctlOpts[ctlTTL].marshal(b, nil)
|
||||||
|
}
|
||||||
|
if ctlOpts[ctlPacketInfo].name > 0 {
|
||||||
|
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
|
||||||
|
b = ctlOpts[ctlPacketInfo].marshal(b, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if opt.isset(FlagDst) && ctlOpts[ctlDst].name > 0 {
|
||||||
|
b = ctlOpts[ctlDst].marshal(b, nil)
|
||||||
|
}
|
||||||
|
if opt.isset(FlagInterface) && ctlOpts[ctlInterface].name > 0 {
|
||||||
|
b = ctlOpts[ctlInterface].marshal(b, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
cmsgs, err := syscall.ParseSocketControlMessage(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, os.NewSyscallError("parse socket control message", err)
|
||||||
|
}
|
||||||
|
cm := &ControlMessage{}
|
||||||
|
for _, m := range cmsgs {
|
||||||
|
if m.Header.Level != iana.ProtocolIP {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch int(m.Header.Type) {
|
||||||
|
case ctlOpts[ctlTTL].name:
|
||||||
|
ctlOpts[ctlTTL].parse(cm, m.Data[:])
|
||||||
|
case ctlOpts[ctlDst].name:
|
||||||
|
ctlOpts[ctlDst].parse(cm, m.Data[:])
|
||||||
|
case ctlOpts[ctlInterface].name:
|
||||||
|
ctlOpts[ctlInterface].parse(cm, m.Data[:])
|
||||||
|
case ctlOpts[ctlPacketInfo].name:
|
||||||
|
ctlOpts[ctlPacketInfo].parse(cm, m.Data[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||||
|
if cm == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var l int
|
||||||
|
pktinfo := false
|
||||||
|
if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To4() != nil || cm.IfIndex > 0) {
|
||||||
|
pktinfo = true
|
||||||
|
l += syscall.CmsgSpace(ctlOpts[ctlPacketInfo].length)
|
||||||
|
}
|
||||||
|
if l > 0 {
|
||||||
|
oob = make([]byte, l)
|
||||||
|
b := oob
|
||||||
|
if pktinfo {
|
||||||
|
b = ctlOpts[ctlPacketInfo].marshal(b, cm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalTTL(b []byte, cm *ControlMessage) []byte {
|
||||||
|
m := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
|
m.Level = iana.ProtocolIP
|
||||||
|
m.Type = sysIP_RECVTTL
|
||||||
|
m.SetLen(syscall.CmsgLen(1))
|
||||||
|
return b[syscall.CmsgSpace(1):]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTTL(cm *ControlMessage, b []byte) {
|
||||||
|
cm.TTL = int(*(*byte)(unsafe.Pointer(&b[:1][0])))
|
||||||
|
}
|
27
vendor/golang.org/x/net/ipv4/control_windows.go
generated
vendored
Normal file
27
vendor/golang.org/x/net/ipv4/control_windows.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func setControlMessage(fd syscall.Handle, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return syscall.EWINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
func newControlMessage(opt *rawOpt) []byte {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return nil, syscall.EWINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalControlMessage(cm *ControlMessage) []byte {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return nil
|
||||||
|
}
|
77
vendor/golang.org/x/net/ipv4/defs_darwin.go
generated
vendored
Normal file
77
vendor/golang.org/x/net/ipv4/defs_darwin.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_RECVIF = C.IP_RECVIF
|
||||||
|
sysIP_STRIPHDR = C.IP_STRIPHDR
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
sysIP_BOUND_IF = C.IP_BOUND_IF
|
||||||
|
sysIP_PKTINFO = C.IP_PKTINFO
|
||||||
|
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
||||||
|
sysIP_MULTICAST_IFINDEX = C.IP_MULTICAST_IFINDEX
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||||
|
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||||
|
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||||
|
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||||
|
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||||
|
sysSizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||||
|
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||||
|
sysSizeofGroupReq = C.sizeof_struct_group_req
|
||||||
|
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage C.struct_sockaddr_storage
|
||||||
|
|
||||||
|
type sysSockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sysInetPktinfo C.struct_in_pktinfo
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
||||||
|
|
||||||
|
type sysIPMreqn C.struct_ip_mreqn
|
||||||
|
|
||||||
|
type sysIPMreqSource C.struct_ip_mreq_source
|
||||||
|
|
||||||
|
type sysGroupReq C.struct_group_req
|
||||||
|
|
||||||
|
type sysGroupSourceReq C.struct_group_source_req
|
38
vendor/golang.org/x/net/ipv4/defs_dragonfly.go
generated
vendored
Normal file
38
vendor/golang.org/x/net/ipv4/defs_dragonfly.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_RECVIF = C.IP_RECVIF
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
75
vendor/golang.org/x/net/ipv4/defs_freebsd.go
generated
vendored
Normal file
75
vendor/golang.org/x/net/ipv4/defs_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||||
|
sysIP_SENDSRCADDR = C.IP_SENDSRCADDR
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_RECVIF = C.IP_RECVIF
|
||||||
|
sysIP_ONESBCAST = C.IP_ONESBCAST
|
||||||
|
sysIP_BINDANY = C.IP_BINDANY
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
sysIP_MINTTL = C.IP_MINTTL
|
||||||
|
sysIP_DONTFRAG = C.IP_DONTFRAG
|
||||||
|
sysIP_RECVTOS = C.IP_RECVTOS
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||||
|
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||||
|
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||||
|
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||||
|
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
||||||
|
sysSizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||||
|
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||||
|
sysSizeofGroupReq = C.sizeof_struct_group_req
|
||||||
|
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage C.struct_sockaddr_storage
|
||||||
|
|
||||||
|
type sysSockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
||||||
|
|
||||||
|
type sysIPMreqn C.struct_ip_mreqn
|
||||||
|
|
||||||
|
type sysIPMreqSource C.struct_ip_mreq_source
|
||||||
|
|
||||||
|
type sysGroupReq C.struct_group_req
|
||||||
|
|
||||||
|
type sysGroupSourceReq C.struct_group_source_req
|
120
vendor/golang.org/x/net/ipv4/defs_linux.go
generated
vendored
Normal file
120
vendor/golang.org/x/net/ipv4/defs_linux.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <linux/errqueue.h>
|
||||||
|
#include <linux/icmp.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/filter.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_ROUTER_ALERT = C.IP_ROUTER_ALERT
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_PKTINFO = C.IP_PKTINFO
|
||||||
|
sysIP_PKTOPTIONS = C.IP_PKTOPTIONS
|
||||||
|
sysIP_MTU_DISCOVER = C.IP_MTU_DISCOVER
|
||||||
|
sysIP_RECVERR = C.IP_RECVERR
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
sysIP_RECVTOS = C.IP_RECVTOS
|
||||||
|
sysIP_MTU = C.IP_MTU
|
||||||
|
sysIP_FREEBIND = C.IP_FREEBIND
|
||||||
|
sysIP_TRANSPARENT = C.IP_TRANSPARENT
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_ORIGDSTADDR = C.IP_ORIGDSTADDR
|
||||||
|
sysIP_RECVORIGDSTADDR = C.IP_RECVORIGDSTADDR
|
||||||
|
sysIP_MINTTL = C.IP_MINTTL
|
||||||
|
sysIP_NODEFRAG = C.IP_NODEFRAG
|
||||||
|
sysIP_UNICAST_IF = C.IP_UNICAST_IF
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||||
|
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_MSFILTER = C.IP_MSFILTER
|
||||||
|
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
||||||
|
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
||||||
|
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
||||||
|
sysMCAST_MSFILTER = C.MCAST_MSFILTER
|
||||||
|
sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL
|
||||||
|
|
||||||
|
//sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
|
||||||
|
//sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
|
||||||
|
//sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
|
||||||
|
//sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
|
||||||
|
//sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
|
||||||
|
//sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
|
||||||
|
|
||||||
|
sysICMP_FILTER = C.ICMP_FILTER
|
||||||
|
|
||||||
|
sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE
|
||||||
|
sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL
|
||||||
|
sysSO_EE_ORIGIN_ICMP = C.SO_EE_ORIGIN_ICMP
|
||||||
|
sysSO_EE_ORIGIN_ICMP6 = C.SO_EE_ORIGIN_ICMP6
|
||||||
|
sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
|
||||||
|
sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
|
||||||
|
|
||||||
|
sysSOL_SOCKET = C.SOL_SOCKET
|
||||||
|
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
||||||
|
|
||||||
|
sysSizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
||||||
|
sysSizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
||||||
|
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
||||||
|
sysSizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
sysSizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||||
|
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||||
|
sysSizeofGroupReq = C.sizeof_struct_group_req
|
||||||
|
sysSizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
||||||
|
|
||||||
|
sysSizeofICMPFilter = C.sizeof_struct_icmp_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysKernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
||||||
|
|
||||||
|
type sysSockaddrInet C.struct_sockaddr_in
|
||||||
|
|
||||||
|
type sysInetPktinfo C.struct_in_pktinfo
|
||||||
|
|
||||||
|
type sysSockExtendedErr C.struct_sock_extended_err
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
||||||
|
|
||||||
|
type sysIPMreqn C.struct_ip_mreqn
|
||||||
|
|
||||||
|
type sysIPMreqSource C.struct_ip_mreq_source
|
||||||
|
|
||||||
|
type sysGroupReq C.struct_group_req
|
||||||
|
|
||||||
|
type sysGroupSourceReq C.struct_group_source_req
|
||||||
|
|
||||||
|
type sysICMPFilter C.struct_icmp_filter
|
||||||
|
|
||||||
|
type sysSockFProg C.struct_sock_fprog
|
||||||
|
|
||||||
|
type sysSockFilter C.struct_sock_filter
|
37
vendor/golang.org/x/net/ipv4/defs_netbsd.go
generated
vendored
Normal file
37
vendor/golang.org/x/net/ipv4/defs_netbsd.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_RECVIF = C.IP_RECVIF
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
37
vendor/golang.org/x/net/ipv4/defs_openbsd.go
generated
vendored
Normal file
37
vendor/golang.org/x/net/ipv4/defs_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_RECVIF = C.IP_RECVIF
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
57
vendor/golang.org/x/net/ipv4/defs_solaris.go
generated
vendored
Normal file
57
vendor/golang.org/x/net/ipv4/defs_solaris.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = C.IP_OPTIONS
|
||||||
|
sysIP_HDRINCL = C.IP_HDRINCL
|
||||||
|
sysIP_TOS = C.IP_TOS
|
||||||
|
sysIP_TTL = C.IP_TTL
|
||||||
|
sysIP_RECVOPTS = C.IP_RECVOPTS
|
||||||
|
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
||||||
|
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
||||||
|
sysIP_RETOPTS = C.IP_RETOPTS
|
||||||
|
sysIP_RECVIF = C.IP_RECVIF
|
||||||
|
sysIP_RECVSLLA = C.IP_RECVSLLA
|
||||||
|
sysIP_RECVTTL = C.IP_RECVTTL
|
||||||
|
sysIP_NEXTHOP = C.IP_NEXTHOP
|
||||||
|
sysIP_PKTINFO = C.IP_PKTINFO
|
||||||
|
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
||||||
|
sysIP_DONTFRAG = C.IP_DONTFRAG
|
||||||
|
sysIP_BOUND_IF = C.IP_BOUND_IF
|
||||||
|
sysIP_UNSPEC_SRC = C.IP_UNSPEC_SRC
|
||||||
|
sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL
|
||||||
|
sysIP_DHCPINIT_IF = C.IP_DHCPINIT_IF
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
||||||
|
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
||||||
|
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
||||||
|
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
||||||
|
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
||||||
|
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
||||||
|
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
||||||
|
|
||||||
|
sysSizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
||||||
|
|
||||||
|
sysSizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||||
|
sysSizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysInetPktinfo C.struct_in_pktinfo
|
||||||
|
|
||||||
|
type sysIPMreq C.struct_ip_mreq
|
||||||
|
|
||||||
|
type sysIPMreqSource C.struct_ip_mreq_source
|
251
vendor/golang.org/x/net/ipv4/dgramopt_posix.go
generated
vendored
Normal file
251
vendor/golang.org/x/net/ipv4/dgramopt_posix.go
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MulticastTTL returns the time-to-live field value for outgoing
|
||||||
|
// multicast packets.
|
||||||
|
func (c *dgramOpt) MulticastTTL() (int, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return getInt(fd, &sockOpts[ssoMulticastTTL])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastTTL sets the time-to-live field value for future
|
||||||
|
// outgoing multicast packets.
|
||||||
|
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoMulticastTTL], ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulticastInterface returns the default interface for multicast
|
||||||
|
// packet transmissions.
|
||||||
|
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return getInterface(fd, &sockOpts[ssoMulticastInterface])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastInterface sets the default interface for future
|
||||||
|
// multicast packet transmissions.
|
||||||
|
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInterface(fd, &sockOpts[ssoMulticastInterface], ifi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulticastLoopback reports whether transmitted multicast packets
|
||||||
|
// should be copied and send back to the originator.
|
||||||
|
func (c *dgramOpt) MulticastLoopback() (bool, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return false, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
on, err := getInt(fd, &sockOpts[ssoMulticastLoopback])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return on == 1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastLoopback sets whether transmitted multicast packets
|
||||||
|
// should be copied and send back to the originator.
|
||||||
|
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoMulticastLoopback], boolint(on))
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinGroup joins the group address group on the interface ifi.
|
||||||
|
// By default all sources that can cast data to group are accepted.
|
||||||
|
// It's possible to mute and unmute data transmission from a specific
|
||||||
|
// source by using ExcludeSourceSpecificGroup and
|
||||||
|
// IncludeSourceSpecificGroup.
|
||||||
|
// JoinGroup uses the system assigned multicast interface when ifi is
|
||||||
|
// nil, although this is not recommended because the assignment
|
||||||
|
// depends on platforms and sometimes it might require routing
|
||||||
|
// configuration.
|
||||||
|
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
grp := netAddrToIP4(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setGroup(fd, &sockOpts[ssoJoinGroup], ifi, grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeaveGroup leaves the group address group on the interface ifi
|
||||||
|
// regardless of whether the group is any-source group or
|
||||||
|
// source-specific group.
|
||||||
|
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
grp := netAddrToIP4(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setGroup(fd, &sockOpts[ssoLeaveGroup], ifi, grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinSourceSpecificGroup joins the source-specific group comprising
|
||||||
|
// group and source on the interface ifi.
|
||||||
|
// JoinSourceSpecificGroup uses the system assigned multicast
|
||||||
|
// interface when ifi is nil, although this is not recommended because
|
||||||
|
// the assignment depends on platforms and sometimes it might require
|
||||||
|
// routing configuration.
|
||||||
|
func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
grp := netAddrToIP4(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP4(source)
|
||||||
|
if src == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setSourceGroup(fd, &sockOpts[ssoJoinSourceGroup], ifi, grp, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeaveSourceSpecificGroup leaves the source-specific group on the
|
||||||
|
// interface ifi.
|
||||||
|
func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
grp := netAddrToIP4(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP4(source)
|
||||||
|
if src == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setSourceGroup(fd, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExcludeSourceSpecificGroup excludes the source-specific group from
|
||||||
|
// the already joined any-source groups by JoinGroup on the interface
|
||||||
|
// ifi.
|
||||||
|
func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
grp := netAddrToIP4(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP4(source)
|
||||||
|
if src == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setSourceGroup(fd, &sockOpts[ssoBlockSourceGroup], ifi, grp, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncludeSourceSpecificGroup includes the excluded source-specific
|
||||||
|
// group by ExcludeSourceSpecificGroup again on the interface ifi.
|
||||||
|
func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
grp := netAddrToIP4(group)
|
||||||
|
if grp == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
src := netAddrToIP4(source)
|
||||||
|
if src == nil {
|
||||||
|
return errMissingAddress
|
||||||
|
}
|
||||||
|
return setSourceGroup(fd, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICMPFilter returns an ICMP filter.
|
||||||
|
// Currently only Linux supports this.
|
||||||
|
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return getICMPFilter(fd, &sockOpts[ssoICMPFilter])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetICMPFilter deploys the ICMP filter.
|
||||||
|
// Currently only Linux supports this.
|
||||||
|
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setICMPFilter(fd, &sockOpts[ssoICMPFilter], f)
|
||||||
|
}
|
106
vendor/golang.org/x/net/ipv4/dgramopt_stub.go
generated
vendored
Normal file
106
vendor/golang.org/x/net/ipv4/dgramopt_stub.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// MulticastTTL returns the time-to-live field value for outgoing
|
||||||
|
// multicast packets.
|
||||||
|
func (c *dgramOpt) MulticastTTL() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastTTL sets the time-to-live field value for future
|
||||||
|
// outgoing multicast packets.
|
||||||
|
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulticastInterface returns the default interface for multicast
|
||||||
|
// packet transmissions.
|
||||||
|
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastInterface sets the default interface for future
|
||||||
|
// multicast packet transmissions.
|
||||||
|
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// MulticastLoopback reports whether transmitted multicast packets
|
||||||
|
// should be copied and send back to the originator.
|
||||||
|
func (c *dgramOpt) MulticastLoopback() (bool, error) {
|
||||||
|
return false, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMulticastLoopback sets whether transmitted multicast packets
|
||||||
|
// should be copied and send back to the originator.
|
||||||
|
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinGroup joins the group address group on the interface ifi.
|
||||||
|
// By default all sources that can cast data to group are accepted.
|
||||||
|
// It's possible to mute and unmute data transmission from a specific
|
||||||
|
// source by using ExcludeSourceSpecificGroup and
|
||||||
|
// IncludeSourceSpecificGroup.
|
||||||
|
// JoinGroup uses the system assigned multicast interface when ifi is
|
||||||
|
// nil, although this is not recommended because the assignment
|
||||||
|
// depends on platforms and sometimes it might require routing
|
||||||
|
// configuration.
|
||||||
|
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeaveGroup leaves the group address group on the interface ifi
|
||||||
|
// regardless of whether the group is any-source group or
|
||||||
|
// source-specific group.
|
||||||
|
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinSourceSpecificGroup joins the source-specific group comprising
|
||||||
|
// group and source on the interface ifi.
|
||||||
|
// JoinSourceSpecificGroup uses the system assigned multicast
|
||||||
|
// interface when ifi is nil, although this is not recommended because
|
||||||
|
// the assignment depends on platforms and sometimes it might require
|
||||||
|
// routing configuration.
|
||||||
|
func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeaveSourceSpecificGroup leaves the source-specific group on the
|
||||||
|
// interface ifi.
|
||||||
|
func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExcludeSourceSpecificGroup excludes the source-specific group from
|
||||||
|
// the already joined any-source groups by JoinGroup on the interface
|
||||||
|
// ifi.
|
||||||
|
func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncludeSourceSpecificGroup includes the excluded source-specific
|
||||||
|
// group by ExcludeSourceSpecificGroup again on the interface ifi.
|
||||||
|
func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICMPFilter returns an ICMP filter.
|
||||||
|
// Currently only Linux supports this.
|
||||||
|
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetICMPFilter deploys the ICMP filter.
|
||||||
|
// Currently only Linux supports this.
|
||||||
|
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
242
vendor/golang.org/x/net/ipv4/doc.go
generated
vendored
Normal file
242
vendor/golang.org/x/net/ipv4/doc.go
generated
vendored
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package ipv4 implements IP-level socket options for the Internet
|
||||||
|
// Protocol version 4.
|
||||||
|
//
|
||||||
|
// The package provides IP-level socket options that allow
|
||||||
|
// manipulation of IPv4 facilities.
|
||||||
|
//
|
||||||
|
// The IPv4 protocol and basic host requirements for IPv4 are defined
|
||||||
|
// in RFC 791 and RFC 1122.
|
||||||
|
// Host extensions for multicasting and socket interface extensions
|
||||||
|
// for multicast source filters are defined in RFC 1112 and RFC 3678.
|
||||||
|
// IGMPv1, IGMPv2 and IGMPv3 are defined in RFC 1112, RFC 2236 and RFC
|
||||||
|
// 3376.
|
||||||
|
// Source-specific multicast is defined in RFC 4607.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Unicasting
|
||||||
|
//
|
||||||
|
// The options for unicasting are available for net.TCPConn,
|
||||||
|
// net.UDPConn and net.IPConn which are created as network connections
|
||||||
|
// that use the IPv4 transport. When a single TCP connection carrying
|
||||||
|
// a data flow of multiple packets needs to indicate the flow is
|
||||||
|
// important, ipv4.Conn is used to set the type-of-service field on
|
||||||
|
// the IPv4 header for each packet.
|
||||||
|
//
|
||||||
|
// ln, err := net.Listen("tcp4", "0.0.0.0:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer ln.Close()
|
||||||
|
// for {
|
||||||
|
// c, err := ln.Accept()
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// go func(c net.Conn) {
|
||||||
|
// defer c.Close()
|
||||||
|
//
|
||||||
|
// The outgoing packets will be labeled DiffServ assured forwarding
|
||||||
|
// class 1 low drop precedence, known as AF11 packets.
|
||||||
|
//
|
||||||
|
// if err := ipv4.NewConn(c).SetTOS(0x28); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if _, err := c.Write(data); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// }(c)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Multicasting
|
||||||
|
//
|
||||||
|
// The options for multicasting are available for net.UDPConn and
|
||||||
|
// net.IPconn which are created as network connections that use the
|
||||||
|
// IPv4 transport. A few network facilities must be prepared before
|
||||||
|
// you begin multicasting, at a minimum joining network interfaces and
|
||||||
|
// multicast groups.
|
||||||
|
//
|
||||||
|
// en0, err := net.InterfaceByName("en0")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// en1, err := net.InterfaceByIndex(911)
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// group := net.IPv4(224, 0, 0, 250)
|
||||||
|
//
|
||||||
|
// First, an application listens to an appropriate address with an
|
||||||
|
// appropriate service port.
|
||||||
|
//
|
||||||
|
// c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c.Close()
|
||||||
|
//
|
||||||
|
// Second, the application joins multicast groups, starts listening to
|
||||||
|
// the groups on the specified network interfaces. Note that the
|
||||||
|
// service port for transport layer protocol does not matter with this
|
||||||
|
// operation as joining groups affects only network and link layer
|
||||||
|
// protocols, such as IPv4 and Ethernet.
|
||||||
|
//
|
||||||
|
// p := ipv4.NewPacketConn(c)
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The application might set per packet control message transmissions
|
||||||
|
// between the protocol stack within the kernel. When the application
|
||||||
|
// needs a destination address on an incoming packet,
|
||||||
|
// SetControlMessage of ipv4.PacketConn is used to enable control
|
||||||
|
// message transmissons.
|
||||||
|
//
|
||||||
|
// if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The application could identify whether the received packets are
|
||||||
|
// of interest by using the control message that contains the
|
||||||
|
// destination address of the received packet.
|
||||||
|
//
|
||||||
|
// b := make([]byte, 1500)
|
||||||
|
// for {
|
||||||
|
// n, cm, src, err := p.ReadFrom(b)
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if cm.Dst.IsMulticast() {
|
||||||
|
// if cm.Dst.Equal(group) {
|
||||||
|
// // joined group, do something
|
||||||
|
// } else {
|
||||||
|
// // unknown group, discard
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The application can also send both unicast and multicast packets.
|
||||||
|
//
|
||||||
|
// p.SetTOS(0x0)
|
||||||
|
// p.SetTTL(16)
|
||||||
|
// if _, err := p.WriteTo(data, nil, src); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// dst := &net.UDPAddr{IP: group, Port: 1024}
|
||||||
|
// for _, ifi := range []*net.Interface{en0, en1} {
|
||||||
|
// if err := p.SetMulticastInterface(ifi); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// p.SetMulticastTTL(2)
|
||||||
|
// if _, err := p.WriteTo(data, nil, dst); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// More multicasting
|
||||||
|
//
|
||||||
|
// An application that uses PacketConn or RawConn may join multiple
|
||||||
|
// multicast groups. For example, a UDP listener with port 1024 might
|
||||||
|
// join two different groups across over two different network
|
||||||
|
// interfaces by using:
|
||||||
|
//
|
||||||
|
// c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c.Close()
|
||||||
|
// p := ipv4.NewPacketConn(c)
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// It is possible for multiple UDP listeners that listen on the same
|
||||||
|
// UDP port to join the same multicast group. The net package will
|
||||||
|
// provide a socket that listens to a wildcard address with reusable
|
||||||
|
// UDP port when an appropriate multicast address prefix is passed to
|
||||||
|
// the net.ListenPacket or net.ListenUDP.
|
||||||
|
//
|
||||||
|
// c1, err := net.ListenPacket("udp4", "224.0.0.0:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c1.Close()
|
||||||
|
// c2, err := net.ListenPacket("udp4", "224.0.0.0:1024")
|
||||||
|
// if err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// defer c2.Close()
|
||||||
|
// p1 := ipv4.NewPacketConn(c1)
|
||||||
|
// if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// p2 := ipv4.NewPacketConn(c2)
|
||||||
|
// if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Also it is possible for the application to leave or rejoin a
|
||||||
|
// multicast group on the network interface.
|
||||||
|
//
|
||||||
|
// if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)}); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Source-specific multicasting
|
||||||
|
//
|
||||||
|
// An application that uses PacketConn or RawConn on IGMPv3 supported
|
||||||
|
// platform is able to join source-specific multicast groups.
|
||||||
|
// The application may use JoinSourceSpecificGroup and
|
||||||
|
// LeaveSourceSpecificGroup for the operation known as "include" mode,
|
||||||
|
//
|
||||||
|
// ssmgroup := net.UDPAddr{IP: net.IPv4(232, 7, 8, 9)}
|
||||||
|
// ssmsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)})
|
||||||
|
// if err := p.JoinSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.LeaveSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// or JoinGroup, ExcludeSourceSpecificGroup,
|
||||||
|
// IncludeSourceSpecificGroup and LeaveGroup for the operation known
|
||||||
|
// as "exclude" mode.
|
||||||
|
//
|
||||||
|
// exclsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 254)}
|
||||||
|
// if err := p.JoinGroup(en0, &ssmgroup); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.ExcludeSourceSpecificGroup(en0, &ssmgroup, &exclsource); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
// if err := p.LeaveGroup(en0, &ssmgroup); err != nil {
|
||||||
|
// // error handling
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Note that it depends on each platform implementation what happens
|
||||||
|
// when an application which runs on IGMPv3 unsupported platform uses
|
||||||
|
// JoinSourceSpecificGroup and LeaveSourceSpecificGroup.
|
||||||
|
// In general the platform tries to fall back to conversations using
|
||||||
|
// IGMPv1 or IGMPv2 and starts to listen to multicast traffic.
|
||||||
|
// In the fallback case, ExcludeSourceSpecificGroup and
|
||||||
|
// IncludeSourceSpecificGroup may return an error.
|
||||||
|
package ipv4 // import "golang.org/x/net/ipv4"
|
187
vendor/golang.org/x/net/ipv4/endpoint.go
generated
vendored
Normal file
187
vendor/golang.org/x/net/ipv4/endpoint.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Conn represents a network endpoint that uses the IPv4 transport.
|
||||||
|
// It is used to control basic IP-level socket options such as TOS and
|
||||||
|
// TTL.
|
||||||
|
type Conn struct {
|
||||||
|
genericOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
type genericOpt struct {
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil }
|
||||||
|
|
||||||
|
// NewConn returns a new Conn.
|
||||||
|
func NewConn(c net.Conn) *Conn {
|
||||||
|
return &Conn{
|
||||||
|
genericOpt: genericOpt{Conn: c},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A PacketConn represents a packet network endpoint that uses the
|
||||||
|
// IPv4 transport. It is used to control several IP-level socket
|
||||||
|
// options including multicasting. It also provides datagram based
|
||||||
|
// network I/O methods specific to the IPv4 and higher layer protocols
|
||||||
|
// such as UDP.
|
||||||
|
type PacketConn struct {
|
||||||
|
genericOpt
|
||||||
|
dgramOpt
|
||||||
|
payloadHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type dgramOpt struct {
|
||||||
|
net.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) ok() bool { return c != nil && c.PacketConn != nil }
|
||||||
|
|
||||||
|
// SetControlMessage sets the per packet IP-level socket options.
|
||||||
|
func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.payloadHandler.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setControlMessage(fd, &c.payloadHandler.rawOpt, cf, on)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline sets the read and write deadlines associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *PacketConn) SetDeadline(t time.Time) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.PacketConn.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline sets the read deadline associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *PacketConn) SetReadDeadline(t time.Time) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.PacketConn.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline sets the write deadline associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *PacketConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.PacketConn.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the endpoint.
|
||||||
|
func (c *PacketConn) Close() error {
|
||||||
|
if !c.payloadHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.payloadHandler.PacketConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPacketConn returns a new PacketConn using c as its underlying
|
||||||
|
// transport.
|
||||||
|
func NewPacketConn(c net.PacketConn) *PacketConn {
|
||||||
|
p := &PacketConn{
|
||||||
|
genericOpt: genericOpt{Conn: c.(net.Conn)},
|
||||||
|
dgramOpt: dgramOpt{PacketConn: c},
|
||||||
|
payloadHandler: payloadHandler{PacketConn: c},
|
||||||
|
}
|
||||||
|
if _, ok := c.(*net.IPConn); ok && sockOpts[ssoStripHeader].name > 0 {
|
||||||
|
if fd, err := p.payloadHandler.sysfd(); err == nil {
|
||||||
|
setInt(fd, &sockOpts[ssoStripHeader], boolint(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RawConn represents a packet network endpoint that uses the IPv4
|
||||||
|
// transport. It is used to control several IP-level socket options
|
||||||
|
// including IPv4 header manipulation. It also provides datagram
|
||||||
|
// based network I/O methods specific to the IPv4 and higher layer
|
||||||
|
// protocols that handle IPv4 datagram directly such as OSPF, GRE.
|
||||||
|
type RawConn struct {
|
||||||
|
genericOpt
|
||||||
|
dgramOpt
|
||||||
|
packetHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetControlMessage sets the per packet IP-level socket options.
|
||||||
|
func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error {
|
||||||
|
if !c.packetHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.packetHandler.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setControlMessage(fd, &c.packetHandler.rawOpt, cf, on)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline sets the read and write deadlines associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *RawConn) SetDeadline(t time.Time) error {
|
||||||
|
if !c.packetHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.packetHandler.c.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline sets the read deadline associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *RawConn) SetReadDeadline(t time.Time) error {
|
||||||
|
if !c.packetHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.packetHandler.c.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline sets the write deadline associated with the
|
||||||
|
// endpoint.
|
||||||
|
func (c *RawConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
if !c.packetHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.packetHandler.c.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the endpoint.
|
||||||
|
func (c *RawConn) Close() error {
|
||||||
|
if !c.packetHandler.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
return c.packetHandler.c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRawConn returns a new RawConn using c as its underlying
|
||||||
|
// transport.
|
||||||
|
func NewRawConn(c net.PacketConn) (*RawConn, error) {
|
||||||
|
r := &RawConn{
|
||||||
|
genericOpt: genericOpt{Conn: c.(net.Conn)},
|
||||||
|
dgramOpt: dgramOpt{PacketConn: c},
|
||||||
|
packetHandler: packetHandler{c: c.(*net.IPConn)},
|
||||||
|
}
|
||||||
|
fd, err := r.packetHandler.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := setInt(fd, &sockOpts[ssoHeaderPrepend], boolint(true)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
224
vendor/golang.org/x/net/ipv4/example_test.go
generated
vendored
Normal file
224
vendor/golang.org/x/net/ipv4/example_test.go
generated
vendored
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleConn_markingTCP() {
|
||||||
|
ln, err := net.Listen("tcp", "0.0.0.0:1024")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
c, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
go func(c net.Conn) {
|
||||||
|
defer c.Close()
|
||||||
|
if c.RemoteAddr().(*net.TCPAddr).IP.To4() != nil {
|
||||||
|
p := ipv4.NewConn(c)
|
||||||
|
if err := p.SetTOS(0x28); err != nil { // DSCP AF11
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetTTL(128); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExamplePacketConn_servingOneShotMulticastDNS() {
|
||||||
|
c, err := net.ListenPacket("udp4", "0.0.0.0:5353") // mDNS over UDP
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
|
||||||
|
en0, err := net.InterfaceByName("en0")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
mDNSLinkLocal := net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)}
|
||||||
|
if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveGroup(en0, &mDNSLinkLocal)
|
||||||
|
if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make([]byte, 1500)
|
||||||
|
for {
|
||||||
|
_, cm, peer, err := p.ReadFrom(b)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if !cm.Dst.IsMulticast() || !cm.Dst.Equal(mDNSLinkLocal.IP) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this
|
||||||
|
if _, err := p.WriteTo(answers, nil, peer); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExamplePacketConn_tracingIPPacketRoute() {
|
||||||
|
// Tracing an IP packet route to www.google.com.
|
||||||
|
|
||||||
|
const host = "www.google.com"
|
||||||
|
ips, err := net.LookupIP(host)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
var dst net.IPAddr
|
||||||
|
for _, ip := range ips {
|
||||||
|
if ip.To4() != nil {
|
||||||
|
dst.IP = ip
|
||||||
|
fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dst.IP == nil {
|
||||||
|
log.Fatal("no A record found")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip4:1", "0.0.0.0") // ICMP for IPv4
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
|
||||||
|
if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
wm := icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rb := make([]byte, 1500)
|
||||||
|
for i := 1; i <= 64; i++ { // up to 64 hops
|
||||||
|
wm.Body.(*icmp.Echo).Seq = i
|
||||||
|
wb, err := wm.Marshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetTTL(i); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the real world usually there are several
|
||||||
|
// multiple traffic-engineered paths for each hop.
|
||||||
|
// You may need to probe a few times to each hop.
|
||||||
|
begin := time.Now()
|
||||||
|
if _, err := p.WriteTo(wb, nil, &dst); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
n, cm, peer, err := p.ReadFrom(rb)
|
||||||
|
if err != nil {
|
||||||
|
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||||
|
fmt.Printf("%v\t*\n", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
rm, err := icmp.ParseMessage(1, rb[:n])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
rtt := time.Since(begin)
|
||||||
|
|
||||||
|
// In the real world you need to determine whether the
|
||||||
|
// received message is yours using ControlMessage.Src,
|
||||||
|
// ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
|
||||||
|
switch rm.Type {
|
||||||
|
case ipv4.ICMPTypeTimeExceeded:
|
||||||
|
names, _ := net.LookupAddr(peer.String())
|
||||||
|
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
|
||||||
|
case ipv4.ICMPTypeEchoReply:
|
||||||
|
names, _ := net.LookupAddr(peer.String())
|
||||||
|
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
log.Printf("unknown ICMP message: %+v\n", rm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRawConn_advertisingOSPFHello() {
|
||||||
|
c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSPF for IPv4
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
en0, err := net.InterfaceByName("en0")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
allSPFRouters := net.IPAddr{IP: net.IPv4(224, 0, 0, 5)}
|
||||||
|
if err := r.JoinGroup(en0, &allSPFRouters); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.LeaveGroup(en0, &allSPFRouters)
|
||||||
|
|
||||||
|
hello := make([]byte, 24) // fake hello data, you need to implement this
|
||||||
|
ospf := make([]byte, 24) // fake ospf header, you need to implement this
|
||||||
|
ospf[0] = 2 // version 2
|
||||||
|
ospf[1] = 1 // hello packet
|
||||||
|
ospf = append(ospf, hello...)
|
||||||
|
iph := &ipv4.Header{
|
||||||
|
Version: ipv4.Version,
|
||||||
|
Len: ipv4.HeaderLen,
|
||||||
|
TOS: 0xc0, // DSCP CS6
|
||||||
|
TotalLen: ipv4.HeaderLen + len(ospf),
|
||||||
|
TTL: 1,
|
||||||
|
Protocol: 89,
|
||||||
|
Dst: allSPFRouters.IP.To4(),
|
||||||
|
}
|
||||||
|
|
||||||
|
var cm *ipv4.ControlMessage
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "linux":
|
||||||
|
cm = &ipv4.ControlMessage{IfIndex: en0.Index}
|
||||||
|
default:
|
||||||
|
if err := r.SetMulticastInterface(en0); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := r.WriteTo(iph, ospf, cm); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
208
vendor/golang.org/x/net/ipv4/gen.go
generated
vendored
Normal file
208
vendor/golang.org/x/net/ipv4/gen.go
generated
vendored
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
//go:generate go run gen.go
|
||||||
|
|
||||||
|
// This program generates system adaptation constants and types,
|
||||||
|
// internet protocol constants and tables by reading template files
|
||||||
|
// and IANA protocol registries.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := genzsys(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := geniana(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func genzsys() error {
|
||||||
|
defs := "defs_" + runtime.GOOS + ".go"
|
||||||
|
f, err := os.Open(defs)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
||||||
|
b, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// The ipv4 package still supports go1.2, and so we need to
|
||||||
|
// take care of additional platforms in go1.3 and above for
|
||||||
|
// working with go1.2.
|
||||||
|
switch {
|
||||||
|
case runtime.GOOS == "dragonfly" || runtime.GOOS == "solaris":
|
||||||
|
b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv4\n"), 1)
|
||||||
|
case runtime.GOOS == "linux" && (runtime.GOARCH == "arm64" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" || runtime.GOARCH == "ppc" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"):
|
||||||
|
b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+","+runtime.GOARCH+"\n\npackage ipv4\n"), 1)
|
||||||
|
}
|
||||||
|
b, err = format.Source(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
zsys := "zsys_" + runtime.GOOS + ".go"
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "freebsd", "linux":
|
||||||
|
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var registries = []struct {
|
||||||
|
url string
|
||||||
|
parse func(io.Writer, io.Reader) error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
|
||||||
|
parseICMPv4Parameters,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func geniana() error {
|
||||||
|
var bb bytes.Buffer
|
||||||
|
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
||||||
|
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
|
||||||
|
fmt.Fprintf(&bb, "package ipv4\n\n")
|
||||||
|
for _, r := range registries {
|
||||||
|
resp, err := http.Get(r.url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||||
|
}
|
||||||
|
if err := r.parse(&bb, resp.Body); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&bb, "\n")
|
||||||
|
}
|
||||||
|
b, err := format.Source(bb.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
var icp icmpv4Parameters
|
||||||
|
if err := dec.Decode(&icp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prs := icp.escape()
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||||
|
fmt.Fprintf(w, "const (\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Descr == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
|
||||||
|
fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ")\n\n")
|
||||||
|
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||||
|
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
||||||
|
for _, pr := range prs {
|
||||||
|
if pr.Descr == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "}\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type icmpv4Parameters struct {
|
||||||
|
XMLName xml.Name `xml:"registry"`
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Updated string `xml:"updated"`
|
||||||
|
Registries []struct {
|
||||||
|
Title string `xml:"title"`
|
||||||
|
Records []struct {
|
||||||
|
Value string `xml:"value"`
|
||||||
|
Descr string `xml:"description"`
|
||||||
|
} `xml:"record"`
|
||||||
|
} `xml:"registry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type canonICMPv4ParamRecord struct {
|
||||||
|
OrigDescr string
|
||||||
|
Descr string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
|
||||||
|
id := -1
|
||||||
|
for i, r := range icp.Registries {
|
||||||
|
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
||||||
|
id = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if id < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
|
||||||
|
sr := strings.NewReplacer(
|
||||||
|
"Messages", "",
|
||||||
|
"Message", "",
|
||||||
|
"ICMP", "",
|
||||||
|
"+", "P",
|
||||||
|
"-", "",
|
||||||
|
"/", "",
|
||||||
|
".", "",
|
||||||
|
" ", "",
|
||||||
|
)
|
||||||
|
for i, pr := range icp.Registries[id].Records {
|
||||||
|
if strings.Contains(pr.Descr, "Reserved") ||
|
||||||
|
strings.Contains(pr.Descr, "Unassigned") ||
|
||||||
|
strings.Contains(pr.Descr, "Deprecated") ||
|
||||||
|
strings.Contains(pr.Descr, "Experiment") ||
|
||||||
|
strings.Contains(pr.Descr, "experiment") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ss := strings.Split(pr.Descr, "\n")
|
||||||
|
if len(ss) > 1 {
|
||||||
|
prs[i].Descr = strings.Join(ss, " ")
|
||||||
|
} else {
|
||||||
|
prs[i].Descr = ss[0]
|
||||||
|
}
|
||||||
|
s := strings.TrimSpace(prs[i].Descr)
|
||||||
|
prs[i].OrigDescr = s
|
||||||
|
prs[i].Descr = sr.Replace(s)
|
||||||
|
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||||
|
}
|
||||||
|
return prs
|
||||||
|
}
|
59
vendor/golang.org/x/net/ipv4/genericopt_posix.go
generated
vendored
Normal file
59
vendor/golang.org/x/net/ipv4/genericopt_posix.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// TOS returns the type-of-service field value for outgoing packets.
|
||||||
|
func (c *genericOpt) TOS() (int, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return getInt(fd, &sockOpts[ssoTOS])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTOS sets the type-of-service field value for future outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) SetTOS(tos int) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoTOS], tos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TTL returns the time-to-live field value for outgoing packets.
|
||||||
|
func (c *genericOpt) TTL() (int, error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return getInt(fd, &sockOpts[ssoTTL])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTTL sets the time-to-live field value for future outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) SetTTL(ttl int) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
fd, err := c.sysfd()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setInt(fd, &sockOpts[ssoTTL], ttl)
|
||||||
|
}
|
29
vendor/golang.org/x/net/ipv4/genericopt_stub.go
generated
vendored
Normal file
29
vendor/golang.org/x/net/ipv4/genericopt_stub.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
// TOS returns the type-of-service field value for outgoing packets.
|
||||||
|
func (c *genericOpt) TOS() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTOS sets the type-of-service field value for future outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) SetTOS(tos int) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// TTL returns the time-to-live field value for outgoing packets.
|
||||||
|
func (c *genericOpt) TTL() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTTL sets the time-to-live field value for future outgoing
|
||||||
|
// packets.
|
||||||
|
func (c *genericOpt) SetTTL(ttl int) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
132
vendor/golang.org/x/net/ipv4/header.go
generated
vendored
Normal file
132
vendor/golang.org/x/net/ipv4/header.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Version = 4 // protocol version
|
||||||
|
HeaderLen = 20 // header length without extension headers
|
||||||
|
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
|
||||||
|
)
|
||||||
|
|
||||||
|
type HeaderFlags int
|
||||||
|
|
||||||
|
const (
|
||||||
|
MoreFragments HeaderFlags = 1 << iota // more fragments flag
|
||||||
|
DontFragment // don't fragment flag
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Header represents an IPv4 header.
|
||||||
|
type Header struct {
|
||||||
|
Version int // protocol version
|
||||||
|
Len int // header length
|
||||||
|
TOS int // type-of-service
|
||||||
|
TotalLen int // packet total length
|
||||||
|
ID int // identification
|
||||||
|
Flags HeaderFlags // flags
|
||||||
|
FragOff int // fragment offset
|
||||||
|
TTL int // time-to-live
|
||||||
|
Protocol int // next protocol
|
||||||
|
Checksum int // checksum
|
||||||
|
Src net.IP // source address
|
||||||
|
Dst net.IP // destination address
|
||||||
|
Options []byte // options, extension headers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Header) String() string {
|
||||||
|
if h == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ver=%d hdrlen=%d tos=%#x totallen=%d id=%#x flags=%#x fragoff=%#x ttl=%d proto=%d cksum=%#x src=%v dst=%v", h.Version, h.Len, h.TOS, h.TotalLen, h.ID, h.Flags, h.FragOff, h.TTL, h.Protocol, h.Checksum, h.Src, h.Dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal returns the binary encoding of the IPv4 header h.
|
||||||
|
func (h *Header) Marshal() ([]byte, error) {
|
||||||
|
if h == nil {
|
||||||
|
return nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
if h.Len < HeaderLen {
|
||||||
|
return nil, errHeaderTooShort
|
||||||
|
}
|
||||||
|
hdrlen := HeaderLen + len(h.Options)
|
||||||
|
b := make([]byte, hdrlen)
|
||||||
|
b[0] = byte(Version<<4 | (hdrlen >> 2 & 0x0f))
|
||||||
|
b[1] = byte(h.TOS)
|
||||||
|
flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "dragonfly", "freebsd", "netbsd":
|
||||||
|
nativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||||
|
nativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||||
|
default:
|
||||||
|
binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
|
||||||
|
binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
|
||||||
|
}
|
||||||
|
binary.BigEndian.PutUint16(b[4:6], uint16(h.ID))
|
||||||
|
b[8] = byte(h.TTL)
|
||||||
|
b[9] = byte(h.Protocol)
|
||||||
|
binary.BigEndian.PutUint16(b[10:12], uint16(h.Checksum))
|
||||||
|
if ip := h.Src.To4(); ip != nil {
|
||||||
|
copy(b[12:16], ip[:net.IPv4len])
|
||||||
|
}
|
||||||
|
if ip := h.Dst.To4(); ip != nil {
|
||||||
|
copy(b[16:20], ip[:net.IPv4len])
|
||||||
|
} else {
|
||||||
|
return nil, errMissingAddress
|
||||||
|
}
|
||||||
|
if len(h.Options) > 0 {
|
||||||
|
copy(b[HeaderLen:], h.Options)
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseHeader parses b as an IPv4 header.
|
||||||
|
func ParseHeader(b []byte) (*Header, error) {
|
||||||
|
if len(b) < HeaderLen {
|
||||||
|
return nil, errHeaderTooShort
|
||||||
|
}
|
||||||
|
hdrlen := int(b[0]&0x0f) << 2
|
||||||
|
if hdrlen > len(b) {
|
||||||
|
return nil, errBufferTooShort
|
||||||
|
}
|
||||||
|
h := &Header{
|
||||||
|
Version: int(b[0] >> 4),
|
||||||
|
Len: hdrlen,
|
||||||
|
TOS: int(b[1]),
|
||||||
|
ID: int(binary.BigEndian.Uint16(b[4:6])),
|
||||||
|
TTL: int(b[8]),
|
||||||
|
Protocol: int(b[9]),
|
||||||
|
Checksum: int(binary.BigEndian.Uint16(b[10:12])),
|
||||||
|
Src: net.IPv4(b[12], b[13], b[14], b[15]),
|
||||||
|
Dst: net.IPv4(b[16], b[17], b[18], b[19]),
|
||||||
|
}
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "dragonfly", "netbsd":
|
||||||
|
h.TotalLen = int(nativeEndian.Uint16(b[2:4])) + hdrlen
|
||||||
|
h.FragOff = int(nativeEndian.Uint16(b[6:8]))
|
||||||
|
case "freebsd":
|
||||||
|
h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
|
||||||
|
if freebsdVersion < 1000000 {
|
||||||
|
h.TotalLen += hdrlen
|
||||||
|
}
|
||||||
|
h.FragOff = int(nativeEndian.Uint16(b[6:8]))
|
||||||
|
default:
|
||||||
|
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||||
|
h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
|
||||||
|
}
|
||||||
|
h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
|
||||||
|
h.FragOff = h.FragOff & 0x1fff
|
||||||
|
if hdrlen-HeaderLen > 0 {
|
||||||
|
h.Options = make([]byte, hdrlen-HeaderLen)
|
||||||
|
copy(h.Options, b[HeaderLen:])
|
||||||
|
}
|
||||||
|
return h, nil
|
||||||
|
}
|
138
vendor/golang.org/x/net/ipv4/header_test.go
generated
vendored
Normal file
138
vendor/golang.org/x/net/ipv4/header_test.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type headerTest struct {
|
||||||
|
wireHeaderFromKernel [HeaderLen]byte
|
||||||
|
wireHeaderToKernel [HeaderLen]byte
|
||||||
|
wireHeaderFromTradBSDKernel [HeaderLen]byte
|
||||||
|
wireHeaderFromFreeBSD10Kernel [HeaderLen]byte
|
||||||
|
wireHeaderToTradBSDKernel [HeaderLen]byte
|
||||||
|
*Header
|
||||||
|
}
|
||||||
|
|
||||||
|
var headerLittleEndianTest = headerTest{
|
||||||
|
// TODO(mikio): Add platform dependent wire header formats when
|
||||||
|
// we support new platforms.
|
||||||
|
wireHeaderFromKernel: [HeaderLen]byte{
|
||||||
|
0x45, 0x01, 0xbe, 0xef,
|
||||||
|
0xca, 0xfe, 0x45, 0xdc,
|
||||||
|
0xff, 0x01, 0xde, 0xad,
|
||||||
|
172, 16, 254, 254,
|
||||||
|
192, 168, 0, 1,
|
||||||
|
},
|
||||||
|
wireHeaderToKernel: [HeaderLen]byte{
|
||||||
|
0x45, 0x01, 0xbe, 0xef,
|
||||||
|
0xca, 0xfe, 0x45, 0xdc,
|
||||||
|
0xff, 0x01, 0xde, 0xad,
|
||||||
|
172, 16, 254, 254,
|
||||||
|
192, 168, 0, 1,
|
||||||
|
},
|
||||||
|
wireHeaderFromTradBSDKernel: [HeaderLen]byte{
|
||||||
|
0x45, 0x01, 0xdb, 0xbe,
|
||||||
|
0xca, 0xfe, 0xdc, 0x45,
|
||||||
|
0xff, 0x01, 0xde, 0xad,
|
||||||
|
172, 16, 254, 254,
|
||||||
|
192, 168, 0, 1,
|
||||||
|
},
|
||||||
|
wireHeaderFromFreeBSD10Kernel: [HeaderLen]byte{
|
||||||
|
0x45, 0x01, 0xef, 0xbe,
|
||||||
|
0xca, 0xfe, 0xdc, 0x45,
|
||||||
|
0xff, 0x01, 0xde, 0xad,
|
||||||
|
172, 16, 254, 254,
|
||||||
|
192, 168, 0, 1,
|
||||||
|
},
|
||||||
|
wireHeaderToTradBSDKernel: [HeaderLen]byte{
|
||||||
|
0x45, 0x01, 0xef, 0xbe,
|
||||||
|
0xca, 0xfe, 0xdc, 0x45,
|
||||||
|
0xff, 0x01, 0xde, 0xad,
|
||||||
|
172, 16, 254, 254,
|
||||||
|
192, 168, 0, 1,
|
||||||
|
},
|
||||||
|
Header: &Header{
|
||||||
|
Version: Version,
|
||||||
|
Len: HeaderLen,
|
||||||
|
TOS: 1,
|
||||||
|
TotalLen: 0xbeef,
|
||||||
|
ID: 0xcafe,
|
||||||
|
Flags: DontFragment,
|
||||||
|
FragOff: 1500,
|
||||||
|
TTL: 255,
|
||||||
|
Protocol: 1,
|
||||||
|
Checksum: 0xdead,
|
||||||
|
Src: net.IPv4(172, 16, 254, 254),
|
||||||
|
Dst: net.IPv4(192, 168, 0, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalHeader(t *testing.T) {
|
||||||
|
tt := &headerLittleEndianTest
|
||||||
|
if nativeEndian != binary.LittleEndian {
|
||||||
|
t.Skip("no test for non-little endian machine yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := tt.Header.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var wh []byte
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "dragonfly", "netbsd":
|
||||||
|
wh = tt.wireHeaderToTradBSDKernel[:]
|
||||||
|
case "freebsd":
|
||||||
|
if freebsdVersion < 1000000 {
|
||||||
|
wh = tt.wireHeaderToTradBSDKernel[:]
|
||||||
|
} else {
|
||||||
|
wh = tt.wireHeaderFromFreeBSD10Kernel[:]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
wh = tt.wireHeaderToKernel[:]
|
||||||
|
}
|
||||||
|
if !bytes.Equal(b, wh) {
|
||||||
|
t.Fatalf("got %#v; want %#v", b, wh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseHeader(t *testing.T) {
|
||||||
|
tt := &headerLittleEndianTest
|
||||||
|
if nativeEndian != binary.LittleEndian {
|
||||||
|
t.Skip("no test for big endian machine yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
var wh []byte
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin", "dragonfly", "netbsd":
|
||||||
|
wh = tt.wireHeaderFromTradBSDKernel[:]
|
||||||
|
case "freebsd":
|
||||||
|
if freebsdVersion < 1000000 {
|
||||||
|
wh = tt.wireHeaderFromTradBSDKernel[:]
|
||||||
|
} else {
|
||||||
|
wh = tt.wireHeaderFromFreeBSD10Kernel[:]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
wh = tt.wireHeaderFromKernel[:]
|
||||||
|
}
|
||||||
|
h, err := ParseHeader(wh)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(h, tt.Header) {
|
||||||
|
t.Fatalf("got %#v; want %#v", h, tt.Header)
|
||||||
|
}
|
||||||
|
s := h.String()
|
||||||
|
if strings.Contains(s, ",") {
|
||||||
|
t.Fatalf("should be space-separated values: %s", s)
|
||||||
|
}
|
||||||
|
}
|
59
vendor/golang.org/x/net/ipv4/helper.go
generated
vendored
Normal file
59
vendor/golang.org/x/net/ipv4/helper.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errMissingAddress = errors.New("missing address")
|
||||||
|
errMissingHeader = errors.New("missing header")
|
||||||
|
errHeaderTooShort = errors.New("header too short")
|
||||||
|
errBufferTooShort = errors.New("buffer too short")
|
||||||
|
errInvalidConnType = errors.New("invalid conn type")
|
||||||
|
errOpNoSupport = errors.New("operation not supported")
|
||||||
|
errNoSuchInterface = errors.New("no such interface")
|
||||||
|
errNoSuchMulticastInterface = errors.New("no such multicast interface")
|
||||||
|
|
||||||
|
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
|
||||||
|
freebsdVersion uint32
|
||||||
|
|
||||||
|
nativeEndian binary.ByteOrder
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
i := uint32(1)
|
||||||
|
b := (*[4]byte)(unsafe.Pointer(&i))
|
||||||
|
if b[0] == 1 {
|
||||||
|
nativeEndian = binary.LittleEndian
|
||||||
|
} else {
|
||||||
|
nativeEndian = binary.BigEndian
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolint(b bool) int {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func netAddrToIP4(a net.Addr) net.IP {
|
||||||
|
switch v := a.(type) {
|
||||||
|
case *net.UDPAddr:
|
||||||
|
if ip := v.IP.To4(); ip != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
case *net.IPAddr:
|
||||||
|
if ip := v.IP.To4(); ip != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
23
vendor/golang.org/x/net/ipv4/helper_stub.go
generated
vendored
Normal file
23
vendor/golang.org/x/net/ipv4/helper_stub.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
func (c *genericOpt) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *packetHandler) sysfd() (int, error) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
50
vendor/golang.org/x/net/ipv4/helper_unix.go
generated
vendored
Normal file
50
vendor/golang.org/x/net/ipv4/helper_unix.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *genericOpt) sysfd() (int, error) {
|
||||||
|
switch p := c.Conn.(type) {
|
||||||
|
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p)
|
||||||
|
}
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) sysfd() (int, error) {
|
||||||
|
switch p := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p.(net.Conn))
|
||||||
|
}
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) sysfd() (int, error) {
|
||||||
|
return sysfd(c.PacketConn.(net.Conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *packetHandler) sysfd() (int, error) {
|
||||||
|
return sysfd(c.c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysfd(c net.Conn) (int, error) {
|
||||||
|
cv := reflect.ValueOf(c)
|
||||||
|
switch ce := cv.Elem(); ce.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
netfd := ce.FieldByName("conn").FieldByName("fd")
|
||||||
|
switch fe := netfd.Elem(); fe.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
fd := fe.FieldByName("sysfd")
|
||||||
|
return int(fd.Int()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
49
vendor/golang.org/x/net/ipv4/helper_windows.go
generated
vendored
Normal file
49
vendor/golang.org/x/net/ipv4/helper_windows.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *genericOpt) sysfd() (syscall.Handle, error) {
|
||||||
|
switch p := c.Conn.(type) {
|
||||||
|
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p)
|
||||||
|
}
|
||||||
|
return syscall.InvalidHandle, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dgramOpt) sysfd() (syscall.Handle, error) {
|
||||||
|
switch p := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn, *net.IPConn:
|
||||||
|
return sysfd(p.(net.Conn))
|
||||||
|
}
|
||||||
|
return syscall.InvalidHandle, errInvalidConnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) sysfd() (syscall.Handle, error) {
|
||||||
|
return sysfd(c.PacketConn.(net.Conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *packetHandler) sysfd() (syscall.Handle, error) {
|
||||||
|
return sysfd(c.c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysfd(c net.Conn) (syscall.Handle, error) {
|
||||||
|
cv := reflect.ValueOf(c)
|
||||||
|
switch ce := cv.Elem(); ce.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
netfd := ce.FieldByName("conn").FieldByName("fd")
|
||||||
|
switch fe := netfd.Elem(); fe.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
fd := fe.FieldByName("sysfd")
|
||||||
|
return syscall.Handle(fd.Uint()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syscall.InvalidHandle, errInvalidConnType
|
||||||
|
}
|
34
vendor/golang.org/x/net/ipv4/iana.go
generated
vendored
Normal file
34
vendor/golang.org/x/net/ipv4/iana.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// go generate gen.go
|
||||||
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
// Internet Control Message Protocol (ICMP) Parameters, Updated: 2013-04-19
|
||||||
|
const (
|
||||||
|
ICMPTypeEchoReply ICMPType = 0 // Echo Reply
|
||||||
|
ICMPTypeDestinationUnreachable ICMPType = 3 // Destination Unreachable
|
||||||
|
ICMPTypeRedirect ICMPType = 5 // Redirect
|
||||||
|
ICMPTypeEcho ICMPType = 8 // Echo
|
||||||
|
ICMPTypeRouterAdvertisement ICMPType = 9 // Router Advertisement
|
||||||
|
ICMPTypeRouterSolicitation ICMPType = 10 // Router Solicitation
|
||||||
|
ICMPTypeTimeExceeded ICMPType = 11 // Time Exceeded
|
||||||
|
ICMPTypeParameterProblem ICMPType = 12 // Parameter Problem
|
||||||
|
ICMPTypeTimestamp ICMPType = 13 // Timestamp
|
||||||
|
ICMPTypeTimestampReply ICMPType = 14 // Timestamp Reply
|
||||||
|
ICMPTypePhoturis ICMPType = 40 // Photuris
|
||||||
|
)
|
||||||
|
|
||||||
|
// Internet Control Message Protocol (ICMP) Parameters, Updated: 2013-04-19
|
||||||
|
var icmpTypes = map[ICMPType]string{
|
||||||
|
0: "echo reply",
|
||||||
|
3: "destination unreachable",
|
||||||
|
5: "redirect",
|
||||||
|
8: "echo",
|
||||||
|
9: "router advertisement",
|
||||||
|
10: "router solicitation",
|
||||||
|
11: "time exceeded",
|
||||||
|
12: "parameter problem",
|
||||||
|
13: "timestamp",
|
||||||
|
14: "timestamp reply",
|
||||||
|
40: "photuris",
|
||||||
|
}
|
57
vendor/golang.org/x/net/ipv4/icmp.go
generated
vendored
Normal file
57
vendor/golang.org/x/net/ipv4/icmp.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "golang.org/x/net/internal/iana"
|
||||||
|
|
||||||
|
// An ICMPType represents a type of ICMP message.
|
||||||
|
type ICMPType int
|
||||||
|
|
||||||
|
func (typ ICMPType) String() string {
|
||||||
|
s, ok := icmpTypes[typ]
|
||||||
|
if !ok {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocol returns the ICMPv4 protocol number.
|
||||||
|
func (typ ICMPType) Protocol() int {
|
||||||
|
return iana.ProtocolICMP
|
||||||
|
}
|
||||||
|
|
||||||
|
// An ICMPFilter represents an ICMP message filter for incoming
|
||||||
|
// packets. The filter belongs to a packet delivery path on a host and
|
||||||
|
// it cannot interact with forwarding packets or tunnel-outer packets.
|
||||||
|
//
|
||||||
|
// Note: RFC 2460 defines a reasonable role model and it works not
|
||||||
|
// only for IPv6 but IPv4. A node means a device that implements IP.
|
||||||
|
// A router means a node that forwards IP packets not explicitly
|
||||||
|
// addressed to itself, and a host means a node that is not a router.
|
||||||
|
type ICMPFilter struct {
|
||||||
|
sysICMPFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept accepts incoming ICMP packets including the type field value
|
||||||
|
// typ.
|
||||||
|
func (f *ICMPFilter) Accept(typ ICMPType) {
|
||||||
|
f.accept(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block blocks incoming ICMP packets including the type field value
|
||||||
|
// typ.
|
||||||
|
func (f *ICMPFilter) Block(typ ICMPType) {
|
||||||
|
f.block(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAll sets the filter action to the filter.
|
||||||
|
func (f *ICMPFilter) SetAll(block bool) {
|
||||||
|
f.setAll(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WillBlock reports whether the ICMP type will be blocked.
|
||||||
|
func (f *ICMPFilter) WillBlock(typ ICMPType) bool {
|
||||||
|
return f.willBlock(typ)
|
||||||
|
}
|
25
vendor/golang.org/x/net/ipv4/icmp_linux.go
generated
vendored
Normal file
25
vendor/golang.org/x/net/ipv4/icmp_linux.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) accept(typ ICMPType) {
|
||||||
|
f.Data &^= 1 << (uint32(typ) & 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) block(typ ICMPType) {
|
||||||
|
f.Data |= 1 << (uint32(typ) & 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) setAll(block bool) {
|
||||||
|
if block {
|
||||||
|
f.Data = 1<<32 - 1
|
||||||
|
} else {
|
||||||
|
f.Data = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
|
||||||
|
return f.Data&(1<<(uint32(typ)&31)) != 0
|
||||||
|
}
|
25
vendor/golang.org/x/net/ipv4/icmp_stub.go
generated
vendored
Normal file
25
vendor/golang.org/x/net/ipv4/icmp_stub.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
const sysSizeofICMPFilter = 0x0
|
||||||
|
|
||||||
|
type sysICMPFilter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) accept(typ ICMPType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) block(typ ICMPType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) setAll(block bool) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
|
||||||
|
return false
|
||||||
|
}
|
95
vendor/golang.org/x/net/ipv4/icmp_test.go
generated
vendored
Normal file
95
vendor/golang.org/x/net/ipv4/icmp_test.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var icmpStringTests = []struct {
|
||||||
|
in ipv4.ICMPType
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
{ipv4.ICMPTypeDestinationUnreachable, "destination unreachable"},
|
||||||
|
|
||||||
|
{256, "<nil>"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestICMPString(t *testing.T) {
|
||||||
|
for _, tt := range icmpStringTests {
|
||||||
|
s := tt.in.String()
|
||||||
|
if s != tt.out {
|
||||||
|
t.Errorf("got %s; want %s", s, tt.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestICMPFilter(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
default:
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
var f ipv4.ICMPFilter
|
||||||
|
for _, toggle := range []bool{false, true} {
|
||||||
|
f.SetAll(toggle)
|
||||||
|
for _, typ := range []ipv4.ICMPType{
|
||||||
|
ipv4.ICMPTypeDestinationUnreachable,
|
||||||
|
ipv4.ICMPTypeEchoReply,
|
||||||
|
ipv4.ICMPTypeTimeExceeded,
|
||||||
|
ipv4.ICMPTypeParameterProblem,
|
||||||
|
} {
|
||||||
|
f.Accept(typ)
|
||||||
|
if f.WillBlock(typ) {
|
||||||
|
t.Errorf("ipv4.ICMPFilter.Set(%v, false) failed", typ)
|
||||||
|
}
|
||||||
|
f.Block(typ)
|
||||||
|
if !f.WillBlock(typ) {
|
||||||
|
t.Errorf("ipv4.ICMPFilter.Set(%v, true) failed", typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetICMPFilter(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
default:
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
|
||||||
|
var f ipv4.ICMPFilter
|
||||||
|
f.SetAll(true)
|
||||||
|
f.Accept(ipv4.ICMPTypeEcho)
|
||||||
|
f.Accept(ipv4.ICMPTypeEchoReply)
|
||||||
|
if err := p.SetICMPFilter(&f); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
kf, err := p.ICMPFilter()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(kf, &f) {
|
||||||
|
t.Fatalf("got %#v; want %#v", kf, f)
|
||||||
|
}
|
||||||
|
}
|
21
vendor/golang.org/x/net/ipv4/mocktransponder_test.go
generated
vendored
Normal file
21
vendor/golang.org/x/net/ipv4/mocktransponder_test.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
|
||||||
|
defer func() { done <- true }()
|
||||||
|
|
||||||
|
c, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}
|
330
vendor/golang.org/x/net/ipv4/multicast_test.go
generated
vendored
Normal file
330
vendor/golang.org/x/net/ipv4/multicast_test.go
generated
vendored
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packetConnReadWriteMulticastUDPTests = []struct {
|
||||||
|
addr string
|
||||||
|
grp, src *net.UDPAddr
|
||||||
|
}{
|
||||||
|
{"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range packetConnReadWriteMulticastUDPTests {
|
||||||
|
c, err := net.ListenPacket("udp4", tt.addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
grp := *tt.grp
|
||||||
|
grp.Port = c.LocalAddr().(*net.UDPAddr).Port
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
if tt.src == nil {
|
||||||
|
if err := p.JoinGroup(ifi, &grp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveGroup(ifi, &grp)
|
||||||
|
} else {
|
||||||
|
if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "freebsd", "linux":
|
||||||
|
default: // platforms that don't support IGMPv2/3 fail here
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
|
||||||
|
}
|
||||||
|
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := p.MulticastInterface(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetMulticastLoopback(true); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := p.MulticastLoopback(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
wb := []byte("HELLO-R-U-THERE")
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p.SetMulticastTTL(i + 1)
|
||||||
|
if n, err := p.WriteTo(wb, nil, &grp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if !bytes.Equal(rb[:n], wb) {
|
||||||
|
t.Fatalf("got %v; want %v", rb[:n], wb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetConnReadWriteMulticastICMPTests = []struct {
|
||||||
|
grp, src *net.IPAddr
|
||||||
|
}{
|
||||||
|
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range packetConnReadWriteMulticastICMPTests {
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
if tt.src == nil {
|
||||||
|
if err := p.JoinGroup(ifi, tt.grp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveGroup(ifi, tt.grp)
|
||||||
|
} else {
|
||||||
|
if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "freebsd", "linux":
|
||||||
|
default: // platforms that don't support IGMPv2/3 fail here
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
|
||||||
|
}
|
||||||
|
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := p.MulticastInterface(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetMulticastLoopback(true); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := p.MulticastLoopback(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
wb, err := (&icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p.SetMulticastTTL(i + 1)
|
||||||
|
if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
|
||||||
|
case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
|
||||||
|
default:
|
||||||
|
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawConnReadWriteMulticastICMPTests = []struct {
|
||||||
|
grp, src *net.IPAddr
|
||||||
|
}{
|
||||||
|
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawConnReadWriteMulticastICMP(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("to avoid external network")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range rawConnReadWriteMulticastICMPTests {
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
if tt.src == nil {
|
||||||
|
if err := r.JoinGroup(ifi, tt.grp); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.LeaveGroup(ifi, tt.grp)
|
||||||
|
} else {
|
||||||
|
if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "freebsd", "linux":
|
||||||
|
default: // platforms that don't support IGMPv2/3 fail here
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
|
||||||
|
}
|
||||||
|
if err := r.SetMulticastInterface(ifi); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := r.MulticastInterface(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := r.SetMulticastLoopback(true); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := r.MulticastLoopback(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
wb, err := (&icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
wh := &ipv4.Header{
|
||||||
|
Version: ipv4.Version,
|
||||||
|
Len: ipv4.HeaderLen,
|
||||||
|
TOS: i + 1,
|
||||||
|
TotalLen: ipv4.HeaderLen + len(wb),
|
||||||
|
Protocol: 1,
|
||||||
|
Dst: tt.grp.IP,
|
||||||
|
}
|
||||||
|
if err := r.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
r.SetMulticastTTL(i + 1)
|
||||||
|
if err := r.WriteTo(wh, wb, nil); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
rb := make([]byte, ipv4.HeaderLen+128)
|
||||||
|
if rh, b, _, err := r.ReadFrom(rb); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
|
||||||
|
case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
|
||||||
|
default:
|
||||||
|
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
249
vendor/golang.org/x/net/ipv4/multicastlistener_test.go
generated
vendored
Normal file
249
vendor/golang.org/x/net/ipv4/multicastlistener_test.go
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var udpMultipleGroupListenerTests = []net.Addr{
|
||||||
|
&net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, // see RFC 4727
|
||||||
|
&net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)},
|
||||||
|
&net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("to avoid external network")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||||
|
c, err := net.ListenPacket("udp4", "0.0.0.0:0") // wildcard address with no reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
var mift []*net.Interface
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mift = append(mift, &ift[i])
|
||||||
|
}
|
||||||
|
for _, ifi := range mift {
|
||||||
|
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("to avoid external network")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||||
|
c1, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c1.Close()
|
||||||
|
|
||||||
|
c2, err := net.ListenPacket("udp4", "224.0.0.0:1024") // wildcard address with reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
var ps [2]*ipv4.PacketConn
|
||||||
|
ps[0] = ipv4.NewPacketConn(c1)
|
||||||
|
ps[1] = ipv4.NewPacketConn(c2)
|
||||||
|
var mift []*net.Interface
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, p := range ps {
|
||||||
|
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mift = append(mift, &ift[i])
|
||||||
|
}
|
||||||
|
for _, ifi := range mift {
|
||||||
|
for _, p := range ps {
|
||||||
|
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("to avoid external network")
|
||||||
|
}
|
||||||
|
|
||||||
|
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
|
||||||
|
type ml struct {
|
||||||
|
c *ipv4.PacketConn
|
||||||
|
ifi *net.Interface
|
||||||
|
}
|
||||||
|
var mlt []*ml
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket("udp4", ip.String()+":"+"1024") // unicast address with non-reusable port
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mlt = append(mlt, &ml{p, &ift[i]})
|
||||||
|
}
|
||||||
|
for _, m := range mlt {
|
||||||
|
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("to avoid external network")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") // wildcard address
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
|
||||||
|
var mift []*net.Interface
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := r.JoinGroup(&ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mift = append(mift, &ift[i])
|
||||||
|
}
|
||||||
|
for _, ifi := range mift {
|
||||||
|
if err := r.LeaveGroup(ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("to avoid external network")
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727
|
||||||
|
type ml struct {
|
||||||
|
c *ipv4.RawConn
|
||||||
|
ifi *net.Interface
|
||||||
|
}
|
||||||
|
var mlt []*ml
|
||||||
|
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, ifi := range ift {
|
||||||
|
ip, ok := nettest.IsMulticastCapable("ip4", &ifi)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket("ip4:253", ip.String()) // unicast address
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := r.JoinGroup(&ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
mlt = append(mlt, &ml{r, &ift[i]})
|
||||||
|
}
|
||||||
|
for _, m := range mlt {
|
||||||
|
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
195
vendor/golang.org/x/net/ipv4/multicastsockopt_test.go
generated
vendored
Normal file
195
vendor/golang.org/x/net/ipv4/multicastsockopt_test.go
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packetConnMulticastSocketOptionTests = []struct {
|
||||||
|
net, proto, addr string
|
||||||
|
grp, src net.Addr
|
||||||
|
}{
|
||||||
|
{"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727
|
||||||
|
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||||
|
{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnMulticastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
m, ok := nettest.SupportsRawIPSocket()
|
||||||
|
for _, tt := range packetConnMulticastSocketOptionTests {
|
||||||
|
if tt.net == "ip4" && !ok {
|
||||||
|
t.Log(m)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
if tt.src == nil {
|
||||||
|
testMulticastSocketOptions(t, p, ifi, tt.grp)
|
||||||
|
} else {
|
||||||
|
testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawConnMulticastSocketOptionTests = []struct {
|
||||||
|
grp, src net.Addr
|
||||||
|
}{
|
||||||
|
{&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
|
||||||
|
|
||||||
|
{&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawConnMulticastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range rawConnMulticastSocketOptionTests {
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
if tt.src == nil {
|
||||||
|
testMulticastSocketOptions(t, r, ifi, tt.grp)
|
||||||
|
} else {
|
||||||
|
testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testIPv4MulticastConn interface {
|
||||||
|
MulticastTTL() (int, error)
|
||||||
|
SetMulticastTTL(ttl int) error
|
||||||
|
MulticastLoopback() (bool, error)
|
||||||
|
SetMulticastLoopback(bool) error
|
||||||
|
JoinGroup(*net.Interface, net.Addr) error
|
||||||
|
LeaveGroup(*net.Interface, net.Addr) error
|
||||||
|
JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||||
|
LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||||
|
ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||||
|
IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) {
|
||||||
|
const ttl = 255
|
||||||
|
if err := c.SetMulticastTTL(ttl); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, err := c.MulticastTTL(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if v != ttl {
|
||||||
|
t.Errorf("got %v; want %v", v, ttl)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, toggle := range []bool{true, false} {
|
||||||
|
if err := c.SetMulticastLoopback(toggle); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, err := c.MulticastLoopback(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if v != toggle {
|
||||||
|
t.Errorf("got %v; want %v", v, toggle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.JoinGroup(ifi, grp); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) {
|
||||||
|
// MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
|
||||||
|
if err := c.JoinGroup(ifi, grp); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "freebsd", "linux":
|
||||||
|
default: // platforms that don't support IGMPv2/3 fail here
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
|
||||||
|
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
|
||||||
|
if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := c.LeaveGroup(ifi, grp); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
97
vendor/golang.org/x/net/ipv4/packet.go
generated
vendored
Normal file
97
vendor/golang.org/x/net/ipv4/packet.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A packetHandler represents the IPv4 datagram handler.
|
||||||
|
type packetHandler struct {
|
||||||
|
c *net.IPConn
|
||||||
|
rawOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *packetHandler) ok() bool { return c != nil && c.c != nil }
|
||||||
|
|
||||||
|
// ReadFrom reads an IPv4 datagram from the endpoint c, copying the
|
||||||
|
// datagram into b. It returns the received datagram as the IPv4
|
||||||
|
// header h, the payload p and the control message cm.
|
||||||
|
func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return nil, nil, nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
oob := newControlMessage(&c.rawOpt)
|
||||||
|
n, oobn, _, src, err := c.c.ReadMsgIP(b, oob)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
var hs []byte
|
||||||
|
if hs, p, err = slicePacket(b[:n]); err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
if h, err = ParseHeader(hs); err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
if cm, err = parseControlMessage(oob[:oobn]); err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
if src != nil && cm != nil {
|
||||||
|
cm.Src = src.IP
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func slicePacket(b []byte) (h, p []byte, err error) {
|
||||||
|
if len(b) < HeaderLen {
|
||||||
|
return nil, nil, errHeaderTooShort
|
||||||
|
}
|
||||||
|
hdrlen := int(b[0]&0x0f) << 2
|
||||||
|
return b[:hdrlen], b[hdrlen:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo writes an IPv4 datagram through the endpoint c, copying the
|
||||||
|
// datagram from the IPv4 header h and the payload p. The control
|
||||||
|
// message cm allows the datagram path and the outgoing interface to be
|
||||||
|
// specified. Currently only Darwin and Linux support this. The cm
|
||||||
|
// may be nil if control of the outgoing datagram is not required.
|
||||||
|
//
|
||||||
|
// The IPv4 header h must contain appropriate fields that include:
|
||||||
|
//
|
||||||
|
// Version = ipv4.Version
|
||||||
|
// Len = <must be specified>
|
||||||
|
// TOS = <must be specified>
|
||||||
|
// TotalLen = <must be specified>
|
||||||
|
// ID = platform sets an appropriate value if ID is zero
|
||||||
|
// FragOff = <must be specified>
|
||||||
|
// TTL = <must be specified>
|
||||||
|
// Protocol = <must be specified>
|
||||||
|
// Checksum = platform sets an appropriate value if Checksum is zero
|
||||||
|
// Src = platform sets an appropriate value if Src is nil
|
||||||
|
// Dst = <must be specified>
|
||||||
|
// Options = optional
|
||||||
|
func (c *packetHandler) WriteTo(h *Header, p []byte, cm *ControlMessage) error {
|
||||||
|
if !c.ok() {
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
oob := marshalControlMessage(cm)
|
||||||
|
wh, err := h.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dst := &net.IPAddr{}
|
||||||
|
if cm != nil {
|
||||||
|
if ip := cm.Dst.To4(); ip != nil {
|
||||||
|
dst.IP = ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dst.IP == nil {
|
||||||
|
dst.IP = h.Dst
|
||||||
|
}
|
||||||
|
wh = append(wh, p...)
|
||||||
|
_, _, err = c.c.WriteMsgIP(wh, oob, dst)
|
||||||
|
return err
|
||||||
|
}
|
15
vendor/golang.org/x/net/ipv4/payload.go
generated
vendored
Normal file
15
vendor/golang.org/x/net/ipv4/payload.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// A payloadHandler represents the IPv4 datagram payload handler.
|
||||||
|
type payloadHandler struct {
|
||||||
|
net.PacketConn
|
||||||
|
rawOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil }
|
81
vendor/golang.org/x/net/ipv4/payload_cmsg.go
generated
vendored
Normal file
81
vendor/golang.org/x/net/ipv4/payload_cmsg.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !plan9,!solaris,!windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadFrom reads a payload of the received IPv4 datagram, from the
|
||||||
|
// endpoint c, copying the payload into b. It returns the number of
|
||||||
|
// bytes copied into b, the control message cm and the source address
|
||||||
|
// src of the received datagram.
|
||||||
|
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, nil, nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
oob := newControlMessage(&c.rawOpt)
|
||||||
|
var oobn int
|
||||||
|
switch c := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn:
|
||||||
|
if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
case *net.IPConn:
|
||||||
|
if sockOpts[ssoStripHeader].name > 0 {
|
||||||
|
if n, oobn, _, src, err = c.ReadMsgIP(b, oob); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nb := make([]byte, maxHeaderLen+len(b))
|
||||||
|
if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
hdrlen := int(nb[0]&0x0f) << 2
|
||||||
|
copy(b, nb[hdrlen:])
|
||||||
|
n -= hdrlen
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0, nil, nil, errInvalidConnType
|
||||||
|
}
|
||||||
|
if cm, err = parseControlMessage(oob[:oobn]); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
if cm != nil {
|
||||||
|
cm.Src = netAddrToIP4(src)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo writes a payload of the IPv4 datagram, to the destination
|
||||||
|
// address dst through the endpoint c, copying the payload from b. It
|
||||||
|
// returns the number of bytes written. The control message cm allows
|
||||||
|
// the datagram path and the outgoing interface to be specified.
|
||||||
|
// Currently only Darwin and Linux support this. The cm may be nil if
|
||||||
|
// control of the outgoing datagram is not required.
|
||||||
|
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
oob := marshalControlMessage(cm)
|
||||||
|
if dst == nil {
|
||||||
|
return 0, errMissingAddress
|
||||||
|
}
|
||||||
|
switch c := c.PacketConn.(type) {
|
||||||
|
case *net.UDPConn:
|
||||||
|
n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
|
||||||
|
case *net.IPConn:
|
||||||
|
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
|
||||||
|
default:
|
||||||
|
return 0, errInvalidConnType
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
42
vendor/golang.org/x/net/ipv4/payload_nocmsg.go
generated
vendored
Normal file
42
vendor/golang.org/x/net/ipv4/payload_nocmsg.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build plan9 solaris windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadFrom reads a payload of the received IPv4 datagram, from the
|
||||||
|
// endpoint c, copying the payload into b. It returns the number of
|
||||||
|
// bytes copied into b, the control message cm and the source address
|
||||||
|
// src of the received datagram.
|
||||||
|
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, nil, nil, syscall.EINVAL
|
||||||
|
}
|
||||||
|
if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo writes a payload of the IPv4 datagram, to the destination
|
||||||
|
// address dst through the endpoint c, copying the payload from b. It
|
||||||
|
// returns the number of bytes written. The control message cm allows
|
||||||
|
// the datagram path and the outgoing interface to be specified.
|
||||||
|
// Currently only Darwin and Linux support this. The cm may be nil if
|
||||||
|
// control of the outgoing datagram is not required.
|
||||||
|
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||||
|
if !c.ok() {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
if dst == nil {
|
||||||
|
return 0, errMissingAddress
|
||||||
|
}
|
||||||
|
return c.PacketConn.WriteTo(b, dst)
|
||||||
|
}
|
174
vendor/golang.org/x/net/ipv4/readwrite_test.go
generated
vendored
Normal file
174
vendor/golang.org/x/net/ipv4/readwrite_test.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
|
||||||
|
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return c, dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkReadWriteNetUDP(b *testing.B) {
|
||||||
|
c, dst, err := benchmarkUDPListener()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
|
||||||
|
if _, err := c.WriteTo(wb, dst); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, _, err := c.ReadFrom(rb); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkReadWriteIPv4UDP(b *testing.B) {
|
||||||
|
c, dst, err := benchmarkUDPListener()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagInterface
|
||||||
|
if err := p.SetControlMessage(cf, true); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
|
||||||
|
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
|
||||||
|
cm := ipv4.ControlMessage{TTL: 1}
|
||||||
|
if ifi != nil {
|
||||||
|
cm.IfIndex = ifi.Index
|
||||||
|
}
|
||||||
|
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
b.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
if _, _, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
wb := []byte("HELLO-R-U-THERE")
|
||||||
|
|
||||||
|
if err := p.SetControlMessage(cf, true); err != nil { // probe before test
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
reader := func() {
|
||||||
|
defer wg.Done()
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if !bytes.Equal(rb[:n], wb) {
|
||||||
|
t.Errorf("got %v; want %v", rb[:n], wb)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
s := cm.String()
|
||||||
|
if strings.Contains(s, ",") {
|
||||||
|
t.Errorf("should be space-separated values: %s", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer := func(toggle bool) {
|
||||||
|
defer wg.Done()
|
||||||
|
cm := ipv4.ControlMessage{
|
||||||
|
Src: net.IPv4(127, 0, 0, 1),
|
||||||
|
}
|
||||||
|
if ifi != nil {
|
||||||
|
cm.IfIndex = ifi.Index
|
||||||
|
}
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Errorf("short write: %v", n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const N = 10
|
||||||
|
wg.Add(N)
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
go reader()
|
||||||
|
}
|
||||||
|
wg.Add(2 * N)
|
||||||
|
for i := 0; i < 2*N; i++ {
|
||||||
|
go writer(i%2 != 0)
|
||||||
|
}
|
||||||
|
wg.Add(N)
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
go reader()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
46
vendor/golang.org/x/net/ipv4/sockopt.go
generated
vendored
Normal file
46
vendor/golang.org/x/net/ipv4/sockopt.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
// Sticky socket options
|
||||||
|
const (
|
||||||
|
ssoTOS = iota // header field for unicast packet
|
||||||
|
ssoTTL // header field for unicast packet
|
||||||
|
ssoMulticastTTL // header field for multicast packet
|
||||||
|
ssoMulticastInterface // outbound interface for multicast packet
|
||||||
|
ssoMulticastLoopback // loopback for multicast packet
|
||||||
|
ssoReceiveTTL // header field on received packet
|
||||||
|
ssoReceiveDst // header field on received packet
|
||||||
|
ssoReceiveInterface // inbound interface on received packet
|
||||||
|
ssoPacketInfo // incbound or outbound packet path
|
||||||
|
ssoHeaderPrepend // ipv4 header prepend
|
||||||
|
ssoStripHeader // strip ipv4 header
|
||||||
|
ssoICMPFilter // icmp filter
|
||||||
|
ssoJoinGroup // any-source multicast
|
||||||
|
ssoLeaveGroup // any-source multicast
|
||||||
|
ssoJoinSourceGroup // source-specific multicast
|
||||||
|
ssoLeaveSourceGroup // source-specific multicast
|
||||||
|
ssoBlockSourceGroup // any-source or source-specific multicast
|
||||||
|
ssoUnblockSourceGroup // any-source or source-specific multicast
|
||||||
|
ssoMax
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sticky socket option value types
|
||||||
|
const (
|
||||||
|
ssoTypeByte = iota + 1
|
||||||
|
ssoTypeInt
|
||||||
|
ssoTypeInterface
|
||||||
|
ssoTypeICMPFilter
|
||||||
|
ssoTypeIPMreq
|
||||||
|
ssoTypeIPMreqn
|
||||||
|
ssoTypeGroupReq
|
||||||
|
ssoTypeGroupSourceReq
|
||||||
|
)
|
||||||
|
|
||||||
|
// A sockOpt represents a binding for sticky socket option.
|
||||||
|
type sockOpt struct {
|
||||||
|
name int // option name, must be equal or greater than 1
|
||||||
|
typ int // option value type, must be equal or greater than 1
|
||||||
|
}
|
83
vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
generated
vendored
Normal file
83
vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func setIPMreqInterface(mreq *sysIPMreq, ifi *net.Interface) error {
|
||||||
|
if ifi == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ifat, err := ifi.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, ifa := range ifat {
|
||||||
|
switch ifa := ifa.(type) {
|
||||||
|
case *net.IPAddr:
|
||||||
|
if ip := ifa.IP.To4(); ip != nil {
|
||||||
|
copy(mreq.Interface[:], ip)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case *net.IPNet:
|
||||||
|
if ip := ifa.IP.To4(); ip != nil {
|
||||||
|
copy(mreq.Interface[:], ip)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errNoSuchInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func netIP4ToInterface(ip net.IP) (*net.Interface, error) {
|
||||||
|
ift, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, ifi := range ift {
|
||||||
|
ifat, err := ifi.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, ifa := range ifat {
|
||||||
|
switch ifa := ifa.(type) {
|
||||||
|
case *net.IPAddr:
|
||||||
|
if ip.Equal(ifa.IP) {
|
||||||
|
return &ifi, nil
|
||||||
|
}
|
||||||
|
case *net.IPNet:
|
||||||
|
if ip.Equal(ifa.IP) {
|
||||||
|
return &ifi, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errNoSuchInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func netInterfaceToIP4(ifi *net.Interface) (net.IP, error) {
|
||||||
|
if ifi == nil {
|
||||||
|
return net.IPv4zero.To4(), nil
|
||||||
|
}
|
||||||
|
ifat, err := ifi.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, ifa := range ifat {
|
||||||
|
switch ifa := ifa.(type) {
|
||||||
|
case *net.IPAddr:
|
||||||
|
if ip := ifa.IP.To4(); ip != nil {
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
case *net.IPNet:
|
||||||
|
if ip := ifa.IP.To4(); ip != nil {
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errNoSuchInterface
|
||||||
|
}
|
21
vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
generated
vendored
Normal file
21
vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func setsockoptIPMreq(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func getsockoptInterface(fd, name int) (*net.Interface, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptInterface(fd, name int, ifi *net.Interface) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
46
vendor/golang.org/x/net/ipv4/sockopt_asmreq_unix.go
generated
vendored
Normal file
46
vendor/golang.org/x/net/ipv4/sockopt_asmreq_unix.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setsockoptIPMreq(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
mreq := sysIPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||||
|
if err := setIPMreqInterface(&mreq, ifi); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&mreq), sysSizeofIPMreq))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getsockoptInterface(fd, name int) (*net.Interface, error) {
|
||||||
|
var b [4]byte
|
||||||
|
l := uint32(4)
|
||||||
|
if err := getsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&b[0]), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ifi, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptInterface(fd, name int, ifi *net.Interface) error {
|
||||||
|
ip, err := netInterfaceToIP4(ifi)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var b [4]byte
|
||||||
|
copy(b[:], ip)
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&b[0]), uint32(4)))
|
||||||
|
}
|
45
vendor/golang.org/x/net/ipv4/sockopt_asmreq_windows.go
generated
vendored
Normal file
45
vendor/golang.org/x/net/ipv4/sockopt_asmreq_windows.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setsockoptIPMreq(fd syscall.Handle, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
mreq := sysIPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||||
|
if err := setIPMreqInterface(&mreq, ifi); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, iana.ProtocolIP, int32(name), (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofIPMreq)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getsockoptInterface(fd syscall.Handle, name int) (*net.Interface, error) {
|
||||||
|
var b [4]byte
|
||||||
|
l := int32(4)
|
||||||
|
if err := syscall.Getsockopt(fd, iana.ProtocolIP, int32(name), (*byte)(unsafe.Pointer(&b[0])), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ifi, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptInterface(fd syscall.Handle, name int, ifi *net.Interface) error {
|
||||||
|
ip, err := netInterfaceToIP4(ifi)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var b [4]byte
|
||||||
|
copy(b[:], ip)
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, iana.ProtocolIP, int32(name), (*byte)(unsafe.Pointer(&b[0])), 4))
|
||||||
|
}
|
17
vendor/golang.org/x/net/ipv4/sockopt_asmreqn_stub.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/ipv4/sockopt_asmreqn_stub.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!freebsd,!linux,!windows
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func getsockoptIPMreqn(fd, name int) (*net.Interface, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptIPMreqn(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
42
vendor/golang.org/x/net/ipv4/sockopt_asmreqn_unix.go
generated
vendored
Normal file
42
vendor/golang.org/x/net/ipv4/sockopt_asmreqn_unix.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin freebsd linux
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getsockoptIPMreqn(fd, name int) (*net.Interface, error) {
|
||||||
|
var mreqn sysIPMreqn
|
||||||
|
l := uint32(sysSizeofIPMreqn)
|
||||||
|
if err := getsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&mreqn), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
if mreqn.Ifindex == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
ifi, err := net.InterfaceByIndex(int(mreqn.Ifindex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ifi, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptIPMreqn(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
var mreqn sysIPMreqn
|
||||||
|
if ifi != nil {
|
||||||
|
mreqn.Ifindex = int32(ifi.Index)
|
||||||
|
}
|
||||||
|
if grp != nil {
|
||||||
|
mreqn.Multiaddr = [4]byte{grp[0], grp[1], grp[2], grp[3]}
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&mreqn), sysSizeofIPMreqn))
|
||||||
|
}
|
17
vendor/golang.org/x/net/ipv4/sockopt_ssmreq_stub.go
generated
vendored
Normal file
17
vendor/golang.org/x/net/ipv4/sockopt_ssmreq_stub.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !darwin,!freebsd,!linux
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func setsockoptGroupReq(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptGroupSourceReq(fd, name int, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
61
vendor/golang.org/x/net/ipv4/sockopt_ssmreq_unix.go
generated
vendored
Normal file
61
vendor/golang.org/x/net/ipv4/sockopt_ssmreq_unix.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin freebsd linux
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
var freebsd32o64 bool
|
||||||
|
|
||||||
|
func setsockoptGroupReq(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||||
|
var gr sysGroupReq
|
||||||
|
if ifi != nil {
|
||||||
|
gr.Interface = uint32(ifi.Index)
|
||||||
|
}
|
||||||
|
gr.setGroup(grp)
|
||||||
|
var p unsafe.Pointer
|
||||||
|
var l uint32
|
||||||
|
if freebsd32o64 {
|
||||||
|
var d [sysSizeofGroupReq + 4]byte
|
||||||
|
s := (*[sysSizeofGroupReq]byte)(unsafe.Pointer(&gr))
|
||||||
|
copy(d[:4], s[:4])
|
||||||
|
copy(d[8:], s[4:])
|
||||||
|
p = unsafe.Pointer(&d[0])
|
||||||
|
l = sysSizeofGroupReq + 4
|
||||||
|
} else {
|
||||||
|
p = unsafe.Pointer(&gr)
|
||||||
|
l = sysSizeofGroupReq
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, p, l))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockoptGroupSourceReq(fd, name int, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
var gsr sysGroupSourceReq
|
||||||
|
if ifi != nil {
|
||||||
|
gsr.Interface = uint32(ifi.Index)
|
||||||
|
}
|
||||||
|
gsr.setSourceGroup(grp, src)
|
||||||
|
var p unsafe.Pointer
|
||||||
|
var l uint32
|
||||||
|
if freebsd32o64 {
|
||||||
|
var d [sysSizeofGroupSourceReq + 4]byte
|
||||||
|
s := (*[sysSizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
|
||||||
|
copy(d[:4], s[:4])
|
||||||
|
copy(d[8:], s[4:])
|
||||||
|
p = unsafe.Pointer(&d[0])
|
||||||
|
l = sysSizeofGroupSourceReq + 4
|
||||||
|
} else {
|
||||||
|
p = unsafe.Pointer(&gsr)
|
||||||
|
l = sysSizeofGroupSourceReq
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, p, l))
|
||||||
|
}
|
11
vendor/golang.org/x/net/ipv4/sockopt_stub.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/ipv4/sockopt_stub.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
func setInt(fd int, opt *sockOpt, v int) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
122
vendor/golang.org/x/net/ipv4/sockopt_unix.go
generated
vendored
Normal file
122
vendor/golang.org/x/net/ipv4/sockopt_unix.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getInt(fd int, opt *sockOpt) (int, error) {
|
||||||
|
if opt.name < 1 || (opt.typ != ssoTypeByte && opt.typ != ssoTypeInt) {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
var b byte
|
||||||
|
p := unsafe.Pointer(&i)
|
||||||
|
l := uint32(4)
|
||||||
|
if opt.typ == ssoTypeByte {
|
||||||
|
p = unsafe.Pointer(&b)
|
||||||
|
l = 1
|
||||||
|
}
|
||||||
|
if err := getsockopt(fd, iana.ProtocolIP, opt.name, p, &l); err != nil {
|
||||||
|
return 0, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
if opt.typ == ssoTypeByte {
|
||||||
|
return int(b), nil
|
||||||
|
}
|
||||||
|
return int(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInt(fd int, opt *sockOpt, v int) error {
|
||||||
|
if opt.name < 1 || (opt.typ != ssoTypeByte && opt.typ != ssoTypeInt) {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
i := int32(v)
|
||||||
|
var b byte
|
||||||
|
p := unsafe.Pointer(&i)
|
||||||
|
l := uint32(4)
|
||||||
|
if opt.typ == ssoTypeByte {
|
||||||
|
b = byte(v)
|
||||||
|
p = unsafe.Pointer(&b)
|
||||||
|
l = 1
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, opt.name, p, l))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInterface(fd int, opt *sockOpt) (*net.Interface, error) {
|
||||||
|
if opt.name < 1 {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
switch opt.typ {
|
||||||
|
case ssoTypeInterface:
|
||||||
|
return getsockoptInterface(fd, opt.name)
|
||||||
|
case ssoTypeIPMreqn:
|
||||||
|
return getsockoptIPMreqn(fd, opt.name)
|
||||||
|
default:
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInterface(fd int, opt *sockOpt, ifi *net.Interface) error {
|
||||||
|
if opt.name < 1 {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
switch opt.typ {
|
||||||
|
case ssoTypeInterface:
|
||||||
|
return setsockoptInterface(fd, opt.name, ifi)
|
||||||
|
case ssoTypeIPMreqn:
|
||||||
|
return setsockoptIPMreqn(fd, opt.name, ifi, nil)
|
||||||
|
default:
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getICMPFilter(fd int, opt *sockOpt) (*ICMPFilter, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
var f ICMPFilter
|
||||||
|
l := uint32(sysSizeofICMPFilter)
|
||||||
|
if err := getsockopt(fd, iana.ProtocolReserved, opt.name, unsafe.Pointer(&f.sysICMPFilter), &l); err != nil {
|
||||||
|
return nil, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
return &f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setICMPFilter(fd int, opt *sockOpt, f *ICMPFilter) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeICMPFilter {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolReserved, opt.name, unsafe.Pointer(&f.sysICMPFilter), sysSizeofICMPFilter))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
if opt.name < 1 {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
switch opt.typ {
|
||||||
|
case ssoTypeIPMreq:
|
||||||
|
return setsockoptIPMreq(fd, opt.name, ifi, grp)
|
||||||
|
case ssoTypeIPMreqn:
|
||||||
|
return setsockoptIPMreqn(fd, opt.name, ifi, grp)
|
||||||
|
case ssoTypeGroupReq:
|
||||||
|
return setsockoptGroupReq(fd, opt.name, ifi, grp)
|
||||||
|
default:
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSourceGroup(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
return setsockoptGroupSourceReq(fd, opt.name, ifi, grp, src)
|
||||||
|
}
|
68
vendor/golang.org/x/net/ipv4/sockopt_windows.go
generated
vendored
Normal file
68
vendor/golang.org/x/net/ipv4/sockopt_windows.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getInt(fd syscall.Handle, opt *sockOpt) (int, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
|
return 0, errOpNoSupport
|
||||||
|
}
|
||||||
|
var i int32
|
||||||
|
l := int32(4)
|
||||||
|
if err := syscall.Getsockopt(fd, iana.ProtocolIP, int32(opt.name), (*byte)(unsafe.Pointer(&i)), &l); err != nil {
|
||||||
|
return 0, os.NewSyscallError("getsockopt", err)
|
||||||
|
}
|
||||||
|
return int(i), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInt(fd syscall.Handle, opt *sockOpt, v int) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInt {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
i := int32(v)
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, iana.ProtocolIP, int32(opt.name), (*byte)(unsafe.Pointer(&i)), 4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInterface(fd syscall.Handle, opt *sockOpt) (*net.Interface, error) {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
return getsockoptInterface(fd, opt.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setInterface(fd syscall.Handle, opt *sockOpt, ifi *net.Interface) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeInterface {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
return setsockoptInterface(fd, opt.name, ifi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getICMPFilter(fd syscall.Handle, opt *sockOpt) (*ICMPFilter, error) {
|
||||||
|
return nil, errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func setICMPFilter(fd syscall.Handle, opt *sockOpt, f *ICMPFilter) error {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
func setGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||||
|
if opt.name < 1 || opt.typ != ssoTypeIPMreq {
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
||||||
|
return setsockoptIPMreq(fd, opt.name, ifi, grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSourceGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||||
|
// TODO(mikio): implement this
|
||||||
|
return errOpNoSupport
|
||||||
|
}
|
34
vendor/golang.org/x/net/ipv4/sys_bsd.go
generated
vendored
Normal file
34
vendor/golang.org/x/net/ipv4/sys_bsd.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build dragonfly netbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
|
||||||
|
ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
|
||||||
|
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTOS: {sysIP_TOS, ssoTypeInt},
|
||||||
|
ssoTTL: {sysIP_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte},
|
||||||
|
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
|
||||||
|
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
|
||||||
|
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
|
||||||
|
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||||
|
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
96
vendor/golang.org/x/net/ipv4/sys_darwin.go
generated
vendored
Normal file
96
vendor/golang.org/x/net/ipv4/sys_darwin.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
|
||||||
|
ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
|
||||||
|
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTOS: {sysIP_TOS, ssoTypeInt},
|
||||||
|
ssoTTL: {sysIP_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte},
|
||||||
|
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
|
||||||
|
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
|
||||||
|
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
|
||||||
|
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||||
|
ssoStripHeader: {sysIP_STRIPHDR, ssoTypeInt},
|
||||||
|
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Seems like kern.osreldate is veiled on latest OS X. We use
|
||||||
|
// kern.osrelease instead.
|
||||||
|
osver, err := syscall.Sysctl("kern.osrelease")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
for i = range osver {
|
||||||
|
if osver[i] == '.' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The IP_PKTINFO and protocol-independent multicast API were
|
||||||
|
// introduced in OS X 10.7 (Darwin 11.0.0). But it looks like
|
||||||
|
// those features require OS X 10.8 (Darwin 12.0.0) and above.
|
||||||
|
// See http://support.apple.com/kb/HT1633.
|
||||||
|
if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '2' {
|
||||||
|
ctlOpts[ctlPacketInfo].name = sysIP_PKTINFO
|
||||||
|
ctlOpts[ctlPacketInfo].length = sysSizeofInetPktinfo
|
||||||
|
ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
|
||||||
|
ctlOpts[ctlPacketInfo].parse = parsePacketInfo
|
||||||
|
sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO
|
||||||
|
sockOpts[ssoPacketInfo].typ = ssoTypeInt
|
||||||
|
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn
|
||||||
|
sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
|
||||||
|
sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
|
||||||
|
sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
|
||||||
|
sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
|
||||||
|
sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
|
||||||
|
sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
|
||||||
|
sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
|
||||||
|
sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
|
||||||
|
sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *sysInetPktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = uint32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||||
|
sa := (*sysSockaddrInet)(unsafe.Pointer(&gr.Pad_cgo_0[0]))
|
||||||
|
sa.Len = sysSizeofSockaddrInet
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||||
|
sa := (*sysSockaddrInet)(unsafe.Pointer(&gsr.Pad_cgo_0[0]))
|
||||||
|
sa.Len = sysSizeofSockaddrInet
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
sa = (*sysSockaddrInet)(unsafe.Pointer(&gsr.Pad_cgo_1[0]))
|
||||||
|
sa.Len = sysSizeofSockaddrInet
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], src)
|
||||||
|
}
|
73
vendor/golang.org/x/net/ipv4/sys_freebsd.go
generated
vendored
Normal file
73
vendor/golang.org/x/net/ipv4/sys_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
|
||||||
|
ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
|
||||||
|
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTOS: {sysIP_TOS, ssoTypeInt},
|
||||||
|
ssoTTL: {sysIP_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte},
|
||||||
|
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
|
||||||
|
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
|
||||||
|
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
|
||||||
|
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||||
|
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
|
||||||
|
if freebsdVersion >= 1000000 {
|
||||||
|
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
|
||||||
|
archs, _ := syscall.Sysctl("kern.supported_archs")
|
||||||
|
for _, s := range strings.Fields(archs) {
|
||||||
|
if s == "amd64" {
|
||||||
|
freebsd32o64 = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||||
|
sa := (*sysSockaddrInet)(unsafe.Pointer(&gr.Group))
|
||||||
|
sa.Len = sysSizeofSockaddrInet
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||||
|
sa := (*sysSockaddrInet)(unsafe.Pointer(&gsr.Group))
|
||||||
|
sa.Len = sysSizeofSockaddrInet
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
sa = (*sysSockaddrInet)(unsafe.Pointer(&gsr.Source))
|
||||||
|
sa.Len = sysSizeofSockaddrInet
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], src)
|
||||||
|
}
|
55
vendor/golang.org/x/net/ipv4/sys_linux.go
generated
vendored
Normal file
55
vendor/golang.org/x/net/ipv4/sys_linux.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTTL: {sysIP_TTL, 1, marshalTTL, parseTTL},
|
||||||
|
ctlPacketInfo: {sysIP_PKTINFO, sysSizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTOS: {sysIP_TOS, ssoTypeInt},
|
||||||
|
ssoTTL: {sysIP_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeIPMreqn},
|
||||||
|
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
|
||||||
|
ssoPacketInfo: {sysIP_PKTINFO, ssoTypeInt},
|
||||||
|
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||||
|
ssoICMPFilter: {sysICMP_FILTER, ssoTypeICMPFilter},
|
||||||
|
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
|
||||||
|
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||||
|
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (pi *sysInetPktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = int32(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||||
|
sa := (*sysSockaddrInet)(unsafe.Pointer(&gr.Group))
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||||
|
sa := (*sysSockaddrInet)(unsafe.Pointer(&gsr.Group))
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], grp)
|
||||||
|
sa = (*sysSockaddrInet)(unsafe.Pointer(&gsr.Source))
|
||||||
|
sa.Family = syscall.AF_INET
|
||||||
|
copy(sa.Addr[:], src)
|
||||||
|
}
|
32
vendor/golang.org/x/net/ipv4/sys_openbsd.go
generated
vendored
Normal file
32
vendor/golang.org/x/net/ipv4/sys_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{
|
||||||
|
ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
|
||||||
|
ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
|
||||||
|
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
|
||||||
|
}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTOS: {sysIP_TOS, ssoTypeInt},
|
||||||
|
ssoTTL: {sysIP_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte},
|
||||||
|
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeByte},
|
||||||
|
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
|
||||||
|
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
|
||||||
|
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
|
||||||
|
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||||
|
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
13
vendor/golang.org/x/net/ipv4/sys_stub.go
generated
vendored
Normal file
13
vendor/golang.org/x/net/ipv4/sys_stub.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build nacl plan9 solaris
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{}
|
||||||
|
)
|
61
vendor/golang.org/x/net/ipv4/sys_windows.go
generated
vendored
Normal file
61
vendor/golang.org/x/net/ipv4/sys_windows.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
const (
|
||||||
|
// See ws2tcpip.h.
|
||||||
|
sysIP_OPTIONS = 0x1
|
||||||
|
sysIP_HDRINCL = 0x2
|
||||||
|
sysIP_TOS = 0x3
|
||||||
|
sysIP_TTL = 0x4
|
||||||
|
sysIP_MULTICAST_IF = 0x9
|
||||||
|
sysIP_MULTICAST_TTL = 0xa
|
||||||
|
sysIP_MULTICAST_LOOP = 0xb
|
||||||
|
sysIP_ADD_MEMBERSHIP = 0xc
|
||||||
|
sysIP_DROP_MEMBERSHIP = 0xd
|
||||||
|
sysIP_DONTFRAGMENT = 0xe
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = 0xf
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = 0x10
|
||||||
|
sysIP_PKTINFO = 0x13
|
||||||
|
|
||||||
|
sysSizeofInetPktinfo = 0x8
|
||||||
|
sysSizeofIPMreq = 0x8
|
||||||
|
sysSizeofIPMreqSource = 0xc
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysInetPktinfo struct {
|
||||||
|
Addr [4]byte
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreq struct {
|
||||||
|
Multiaddr [4]byte
|
||||||
|
Interface [4]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreqSource struct {
|
||||||
|
Multiaddr [4]byte
|
||||||
|
Sourceaddr [4]byte
|
||||||
|
Interface [4]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
|
||||||
|
var (
|
||||||
|
ctlOpts = [ctlMax]ctlOpt{}
|
||||||
|
|
||||||
|
sockOpts = [ssoMax]sockOpt{
|
||||||
|
ssoTOS: {sysIP_TOS, ssoTypeInt},
|
||||||
|
ssoTTL: {sysIP_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeInt},
|
||||||
|
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
|
||||||
|
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
|
||||||
|
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (pi *sysInetPktinfo) setIfindex(i int) {
|
||||||
|
pi.Ifindex = int32(i)
|
||||||
|
}
|
31
vendor/golang.org/x/net/ipv4/syscall_linux_386.go
generated
vendored
Normal file
31
vendor/golang.org/x/net/ipv4/syscall_linux_386.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysGETSOCKOPT = 0xf
|
||||||
|
sysSETSOCKOPT = 0xe
|
||||||
|
)
|
||||||
|
|
||||||
|
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
||||||
|
|
||||||
|
func getsockopt(fd, level, name int, v unsafe.Pointer, l *uint32) error {
|
||||||
|
if _, errno := socketcall(sysGETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockopt(fd, level, name int, v unsafe.Pointer, l uint32) error {
|
||||||
|
if _, errno := socketcall(sysSETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
26
vendor/golang.org/x/net/ipv4/syscall_unix.go
generated
vendored
Normal file
26
vendor/golang.org/x/net/ipv4/syscall_unix.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux,!386 netbsd openbsd
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getsockopt(fd, level, name int, v unsafe.Pointer, l *uint32) error {
|
||||||
|
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setsockopt(fd, level, name int, v unsafe.Pointer, l uint32) error {
|
||||||
|
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||||
|
return error(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
8
vendor/golang.org/x/net/ipv4/thunk_linux_386.s
generated
vendored
Normal file
8
vendor/golang.org/x/net/ipv4/thunk_linux_386.s
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.2
|
||||||
|
|
||||||
|
TEXT ·socketcall(SB),4,$0-36
|
||||||
|
JMP syscall·socketcall(SB)
|
246
vendor/golang.org/x/net/ipv4/unicast_test.go
generated
vendored
Normal file
246
vendor/golang.org/x/net/ipv4/unicast_test.go
generated
vendored
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("udp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
wb := []byte("HELLO-R-U-THERE")
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p.SetTTL(i + 1)
|
||||||
|
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, err := p.WriteTo(wb, nil, dst); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if !bytes.Equal(rb[:n], wb) {
|
||||||
|
t.Fatalf("got %v; want %v", rb[:n], wb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p := ipv4.NewPacketConn(c)
|
||||||
|
defer p.Close()
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
wb, err := (&icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p.SetTTL(i + 1)
|
||||||
|
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, err := p.WriteTo(wb, nil, dst); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if n != len(wb) {
|
||||||
|
t.Fatalf("got %v; want %v", n, len(wb))
|
||||||
|
}
|
||||||
|
rb := make([]byte, 128)
|
||||||
|
loop:
|
||||||
|
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if n, _, _, err := p.ReadFrom(rb); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
|
||||||
|
// On Linux we must handle own sent packets.
|
||||||
|
goto loop
|
||||||
|
}
|
||||||
|
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
|
||||||
|
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawConnReadWriteUnicastICMP(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris", "windows":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
|
||||||
|
|
||||||
|
for i, toggle := range []bool{true, false, true} {
|
||||||
|
wb, err := (&icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||||
|
Data: []byte("HELLO-R-U-THERE"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
wh := &ipv4.Header{
|
||||||
|
Version: ipv4.Version,
|
||||||
|
Len: ipv4.HeaderLen,
|
||||||
|
TOS: i + 1,
|
||||||
|
TotalLen: ipv4.HeaderLen + len(wb),
|
||||||
|
TTL: i + 1,
|
||||||
|
Protocol: 1,
|
||||||
|
Dst: dst.IP,
|
||||||
|
}
|
||||||
|
if err := r.SetControlMessage(cf, toggle); err != nil {
|
||||||
|
if nettest.ProtocolNotSupported(err) {
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := r.WriteTo(wh, wb, nil); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
rb := make([]byte, ipv4.HeaderLen+128)
|
||||||
|
loop:
|
||||||
|
if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, b, _, err := r.ReadFrom(rb); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket
|
||||||
|
t.Logf("not supported on %s", runtime.GOOS)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
|
||||||
|
// On Linux we must handle own sent packets.
|
||||||
|
goto loop
|
||||||
|
}
|
||||||
|
if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
|
||||||
|
t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
139
vendor/golang.org/x/net/ipv4/unicastsockopt_test.go
generated
vendored
Normal file
139
vendor/golang.org/x/net/ipv4/unicastsockopt_test.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ipv4_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/iana"
|
||||||
|
"golang.org/x/net/internal/nettest"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConnUnicastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp4", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
done := make(chan bool)
|
||||||
|
go acceptor(t, ln, done)
|
||||||
|
|
||||||
|
c, err := net.Dial("tcp4", ln.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
testUnicastSocketOptions(t, ipv4.NewConn(c))
|
||||||
|
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetConnUnicastSocketOptionTests = []struct {
|
||||||
|
net, proto, addr string
|
||||||
|
}{
|
||||||
|
{"udp4", "", "127.0.0.1:0"},
|
||||||
|
{"ip4", ":icmp", "127.0.0.1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPacketConnUnicastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
m, ok := nettest.SupportsRawIPSocket()
|
||||||
|
for _, tt := range packetConnUnicastSocketOptionTests {
|
||||||
|
if tt.net == "ip4" && !ok {
|
||||||
|
t.Log(m)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
testUnicastSocketOptions(t, ipv4.NewPacketConn(c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRawConnUnicastSocketOptions(t *testing.T) {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "nacl", "plan9", "solaris":
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||||
|
t.Skip(m)
|
||||||
|
}
|
||||||
|
ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
|
||||||
|
if ifi == nil {
|
||||||
|
t.Skipf("not available on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenPacket("ip4:icmp", "127.0.0.1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
r, err := ipv4.NewRawConn(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testUnicastSocketOptions(t, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
type testIPv4UnicastConn interface {
|
||||||
|
TOS() (int, error)
|
||||||
|
SetTOS(int) error
|
||||||
|
TTL() (int, error)
|
||||||
|
SetTTL(int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnicastSocketOptions(t *testing.T, c testIPv4UnicastConn) {
|
||||||
|
tos := iana.DiffServCS0 | iana.NotECNTransport
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
// IP_TOS option is supported on Windows 8 and beyond.
|
||||||
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.SetTOS(tos); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := c.TOS(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if v != tos {
|
||||||
|
t.Fatalf("got %v; want %v", v, tos)
|
||||||
|
}
|
||||||
|
const ttl = 255
|
||||||
|
if err := c.SetTTL(ttl); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := c.TTL(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if v != ttl {
|
||||||
|
t.Fatalf("got %v; want %v", v, ttl)
|
||||||
|
}
|
||||||
|
}
|
99
vendor/golang.org/x/net/ipv4/zsys_darwin.go
generated
vendored
Normal file
99
vendor/golang.org/x/net/ipv4/zsys_darwin.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_darwin.go
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = 0x1
|
||||||
|
sysIP_HDRINCL = 0x2
|
||||||
|
sysIP_TOS = 0x3
|
||||||
|
sysIP_TTL = 0x4
|
||||||
|
sysIP_RECVOPTS = 0x5
|
||||||
|
sysIP_RECVRETOPTS = 0x6
|
||||||
|
sysIP_RECVDSTADDR = 0x7
|
||||||
|
sysIP_RETOPTS = 0x8
|
||||||
|
sysIP_RECVIF = 0x14
|
||||||
|
sysIP_STRIPHDR = 0x17
|
||||||
|
sysIP_RECVTTL = 0x18
|
||||||
|
sysIP_BOUND_IF = 0x19
|
||||||
|
sysIP_PKTINFO = 0x1a
|
||||||
|
sysIP_RECVPKTINFO = 0x1a
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = 0x9
|
||||||
|
sysIP_MULTICAST_TTL = 0xa
|
||||||
|
sysIP_MULTICAST_LOOP = 0xb
|
||||||
|
sysIP_ADD_MEMBERSHIP = 0xc
|
||||||
|
sysIP_DROP_MEMBERSHIP = 0xd
|
||||||
|
sysIP_MULTICAST_VIF = 0xe
|
||||||
|
sysIP_MULTICAST_IFINDEX = 0x42
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
|
||||||
|
sysIP_BLOCK_SOURCE = 0x48
|
||||||
|
sysIP_UNBLOCK_SOURCE = 0x49
|
||||||
|
sysMCAST_JOIN_GROUP = 0x50
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x51
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x52
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x54
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x55
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet = 0x10
|
||||||
|
sysSizeofInetPktinfo = 0xc
|
||||||
|
|
||||||
|
sysSizeofIPMreq = 0x8
|
||||||
|
sysSizeofIPMreqn = 0xc
|
||||||
|
sysSizeofIPMreqSource = 0xc
|
||||||
|
sysSizeofGroupReq = 0x84
|
||||||
|
sysSizeofGroupSourceReq = 0x104
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
X__ss_pad1 [6]int8
|
||||||
|
X__ss_align int64
|
||||||
|
X__ss_pad2 [112]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
Zero [8]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysInetPktinfo struct {
|
||||||
|
Ifindex uint32
|
||||||
|
Spec_dst [4]byte /* in_addr */
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreq struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Interface [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreqn struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Address [4]byte /* in_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreqSource struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Sourceaddr [4]byte /* in_addr */
|
||||||
|
Interface [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [128]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Pad_cgo_0 [128]byte
|
||||||
|
Pad_cgo_1 [128]byte
|
||||||
|
}
|
33
vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
generated
vendored
Normal file
33
vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_dragonfly.go
|
||||||
|
|
||||||
|
// +build dragonfly
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = 0x1
|
||||||
|
sysIP_HDRINCL = 0x2
|
||||||
|
sysIP_TOS = 0x3
|
||||||
|
sysIP_TTL = 0x4
|
||||||
|
sysIP_RECVOPTS = 0x5
|
||||||
|
sysIP_RECVRETOPTS = 0x6
|
||||||
|
sysIP_RECVDSTADDR = 0x7
|
||||||
|
sysIP_RETOPTS = 0x8
|
||||||
|
sysIP_RECVIF = 0x14
|
||||||
|
sysIP_RECVTTL = 0x41
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = 0x9
|
||||||
|
sysIP_MULTICAST_TTL = 0xa
|
||||||
|
sysIP_MULTICAST_LOOP = 0xb
|
||||||
|
sysIP_MULTICAST_VIF = 0xe
|
||||||
|
sysIP_ADD_MEMBERSHIP = 0xc
|
||||||
|
sysIP_DROP_MEMBERSHIP = 0xd
|
||||||
|
|
||||||
|
sysSizeofIPMreq = 0x8
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysIPMreq struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Interface [4]byte /* in_addr */
|
||||||
|
}
|
93
vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
generated
vendored
Normal file
93
vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_freebsd.go
|
||||||
|
|
||||||
|
package ipv4
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysIP_OPTIONS = 0x1
|
||||||
|
sysIP_HDRINCL = 0x2
|
||||||
|
sysIP_TOS = 0x3
|
||||||
|
sysIP_TTL = 0x4
|
||||||
|
sysIP_RECVOPTS = 0x5
|
||||||
|
sysIP_RECVRETOPTS = 0x6
|
||||||
|
sysIP_RECVDSTADDR = 0x7
|
||||||
|
sysIP_SENDSRCADDR = 0x7
|
||||||
|
sysIP_RETOPTS = 0x8
|
||||||
|
sysIP_RECVIF = 0x14
|
||||||
|
sysIP_ONESBCAST = 0x17
|
||||||
|
sysIP_BINDANY = 0x18
|
||||||
|
sysIP_RECVTTL = 0x41
|
||||||
|
sysIP_MINTTL = 0x42
|
||||||
|
sysIP_DONTFRAG = 0x43
|
||||||
|
sysIP_RECVTOS = 0x44
|
||||||
|
|
||||||
|
sysIP_MULTICAST_IF = 0x9
|
||||||
|
sysIP_MULTICAST_TTL = 0xa
|
||||||
|
sysIP_MULTICAST_LOOP = 0xb
|
||||||
|
sysIP_ADD_MEMBERSHIP = 0xc
|
||||||
|
sysIP_DROP_MEMBERSHIP = 0xd
|
||||||
|
sysIP_MULTICAST_VIF = 0xe
|
||||||
|
sysIP_ADD_SOURCE_MEMBERSHIP = 0x46
|
||||||
|
sysIP_DROP_SOURCE_MEMBERSHIP = 0x47
|
||||||
|
sysIP_BLOCK_SOURCE = 0x48
|
||||||
|
sysIP_UNBLOCK_SOURCE = 0x49
|
||||||
|
sysMCAST_JOIN_GROUP = 0x50
|
||||||
|
sysMCAST_LEAVE_GROUP = 0x51
|
||||||
|
sysMCAST_JOIN_SOURCE_GROUP = 0x52
|
||||||
|
sysMCAST_LEAVE_SOURCE_GROUP = 0x53
|
||||||
|
sysMCAST_BLOCK_SOURCE = 0x54
|
||||||
|
sysMCAST_UNBLOCK_SOURCE = 0x55
|
||||||
|
|
||||||
|
sysSizeofSockaddrStorage = 0x80
|
||||||
|
sysSizeofSockaddrInet = 0x10
|
||||||
|
|
||||||
|
sysSizeofIPMreq = 0x8
|
||||||
|
sysSizeofIPMreqn = 0xc
|
||||||
|
sysSizeofIPMreqSource = 0xc
|
||||||
|
sysSizeofGroupReq = 0x84
|
||||||
|
sysSizeofGroupSourceReq = 0x104
|
||||||
|
)
|
||||||
|
|
||||||
|
type sysSockaddrStorage struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
X__ss_pad1 [6]int8
|
||||||
|
X__ss_align int64
|
||||||
|
X__ss_pad2 [112]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysSockaddrInet struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
Zero [8]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreq struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Interface [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreqn struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Address [4]byte /* in_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysIPMreqSource struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Sourceaddr [4]byte /* in_addr */
|
||||||
|
Interface [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
type sysGroupSourceReq struct {
|
||||||
|
Interface uint32
|
||||||
|
Group sysSockaddrStorage
|
||||||
|
Source sysSockaddrStorage
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user