mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 18:02:01 +00:00
Merge pull request #87926 from fedepaol/agnostsctp
Preliminary SCTP connectivity tests
This commit is contained in:
commit
2fd8debe9b
209
Godeps/LICENSES
generated
209
Godeps/LICENSES
generated
@ -12674,6 +12674,215 @@ limitations under the License.
|
|||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/github.com/ishidawataru/sctp licensed under: =
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
= vendor/github.com/ishidawataru/sctp/LICENSE e3fc50a88d0a364313df4b21ef20c29e
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/github.com/JeffAshton/win_pdh licensed under: =
|
= vendor/github.com/JeffAshton/win_pdh licensed under: =
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -68,6 +68,7 @@ require (
|
|||||||
github.com/hashicorp/golang-lru v0.5.1
|
github.com/hashicorp/golang-lru v0.5.1
|
||||||
github.com/heketi/heketi v9.0.1-0.20190917153846-c2e2a4ab7ab9+incompatible
|
github.com/heketi/heketi v9.0.1-0.20190917153846-c2e2a4ab7ab9+incompatible
|
||||||
github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6 // indirect
|
github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6 // indirect
|
||||||
|
github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5
|
||||||
github.com/json-iterator/go v1.1.8
|
github.com/json-iterator/go v1.1.8
|
||||||
github.com/libopenstorage/openstorage v1.0.0
|
github.com/libopenstorage/openstorage v1.0.0
|
||||||
github.com/lithammer/dedent v1.1.0
|
github.com/lithammer/dedent v1.1.0
|
||||||
@ -337,6 +338,7 @@ replace (
|
|||||||
github.com/hpcloud/tail => github.com/hpcloud/tail v1.0.0
|
github.com/hpcloud/tail => github.com/hpcloud/tail v1.0.0
|
||||||
github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
|
github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
|
||||||
github.com/inconshreveable/mousetrap => github.com/inconshreveable/mousetrap v1.0.0
|
github.com/inconshreveable/mousetrap => github.com/inconshreveable/mousetrap v1.0.0
|
||||||
|
github.com/ishidawataru/sctp => github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5
|
||||||
github.com/jellevandenhooff/dkim => github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1
|
github.com/jellevandenhooff/dkim => github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1
|
||||||
github.com/jimstudt/http-authentication => github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a
|
github.com/jimstudt/http-authentication => github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a
|
||||||
github.com/jmespath/go-jmespath => github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
|
github.com/jmespath/go-jmespath => github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
|
||||||
|
2
go.sum
2
go.sum
@ -299,6 +299,8 @@ github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
|
|||||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5 h1:qPmlgoeRS18y2dT+iAH5vEKZgIqgiPi2Y8UCu/b7Aq8=
|
||||||
|
github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
|
||||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||||
github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
|
github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
],
|
],
|
||||||
"ForbiddenPrefixes": [
|
"ForbiddenPrefixes": [
|
||||||
"k8s.io/kubernetes/cmd",
|
"k8s.io/kubernetes/cmd",
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml",
|
||||||
|
"github.com/ishidawataru/sctp"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -50,12 +50,16 @@ const (
|
|||||||
// EndpointHTTPPort is an endpoint HTTP port for testing.
|
// EndpointHTTPPort is an endpoint HTTP port for testing.
|
||||||
EndpointHTTPPort = 8080
|
EndpointHTTPPort = 8080
|
||||||
// EndpointUDPPort is an endpoint UDP port for testing.
|
// EndpointUDPPort is an endpoint UDP port for testing.
|
||||||
EndpointUDPPort = 8081
|
EndpointUDPPort = 8081
|
||||||
|
// EndpointSCTPPort is an endpoint SCTP port for testing.
|
||||||
|
EndpointSCTPPort = 8082
|
||||||
testContainerHTTPPort = 8080
|
testContainerHTTPPort = 8080
|
||||||
// ClusterHTTPPort is a cluster HTTP port for testing.
|
// ClusterHTTPPort is a cluster HTTP port for testing.
|
||||||
ClusterHTTPPort = 80
|
ClusterHTTPPort = 80
|
||||||
// ClusterUDPPort is a cluster UDP port for testing.
|
// ClusterUDPPort is a cluster UDP port for testing.
|
||||||
ClusterUDPPort = 90
|
ClusterUDPPort = 90
|
||||||
|
// ClusterSCTPPort is a cluster SCTP port for testing.
|
||||||
|
ClusterSCTPPort = 95
|
||||||
testPodName = "test-container-pod"
|
testPodName = "test-container-pod"
|
||||||
hostTestPodName = "host-test-container-pod"
|
hostTestPodName = "host-test-container-pod"
|
||||||
nodePortServiceName = "node-port-service"
|
nodePortServiceName = "node-port-service"
|
||||||
@ -85,8 +89,8 @@ const (
|
|||||||
var NetexecImageName = imageutils.GetE2EImage(imageutils.Agnhost)
|
var NetexecImageName = imageutils.GetE2EImage(imageutils.Agnhost)
|
||||||
|
|
||||||
// NewNetworkingTestConfig creates and sets up a new test config helper.
|
// NewNetworkingTestConfig creates and sets up a new test config helper.
|
||||||
func NewNetworkingTestConfig(f *framework.Framework, hostNetwork bool) *NetworkingTestConfig {
|
func NewNetworkingTestConfig(f *framework.Framework, hostNetwork, SCTPEnabled bool) *NetworkingTestConfig {
|
||||||
config := &NetworkingTestConfig{f: f, Namespace: f.Namespace.Name, HostNetwork: hostNetwork}
|
config := &NetworkingTestConfig{f: f, Namespace: f.Namespace.Name, HostNetwork: hostNetwork, SCTPEnabled: SCTPEnabled}
|
||||||
ginkgo.By(fmt.Sprintf("Performing setup for networking test in namespace %v", config.Namespace))
|
ginkgo.By(fmt.Sprintf("Performing setup for networking test in namespace %v", config.Namespace))
|
||||||
config.setup(getServiceSelector())
|
config.setup(getServiceSelector())
|
||||||
return config
|
return config
|
||||||
@ -119,6 +123,9 @@ type NetworkingTestConfig struct {
|
|||||||
HostTestContainerPod *v1.Pod
|
HostTestContainerPod *v1.Pod
|
||||||
// if the HostTestContainerPod is running with HostNetwork=true.
|
// if the HostTestContainerPod is running with HostNetwork=true.
|
||||||
HostNetwork bool
|
HostNetwork bool
|
||||||
|
// if the test pods are listening on sctp port. We need this as sctp tests
|
||||||
|
// are marked as disruptive as they may load the sctp module.
|
||||||
|
SCTPEnabled bool
|
||||||
// EndpointPods are the pods belonging to the Service created by this
|
// EndpointPods are the pods belonging to the Service created by this
|
||||||
// test config. Each invocation of `setup` creates a service with
|
// test config. Each invocation of `setup` creates a service with
|
||||||
// 1 pod per node running the netexecImage.
|
// 1 pod per node running the netexecImage.
|
||||||
@ -142,9 +149,10 @@ type NetworkingTestConfig struct {
|
|||||||
ClusterIP string
|
ClusterIP string
|
||||||
// External ip of first node for use in nodePort testing.
|
// External ip of first node for use in nodePort testing.
|
||||||
NodeIP string
|
NodeIP string
|
||||||
// The http/udp nodePorts of the Service.
|
// The http/udp/sctp nodePorts of the Service.
|
||||||
NodeHTTPPort int
|
NodeHTTPPort int
|
||||||
NodeUDPPort int
|
NodeUDPPort int
|
||||||
|
NodeSCTPPort int
|
||||||
// The kubernetes namespace within which all resources for this
|
// The kubernetes namespace within which all resources for this
|
||||||
// config are created
|
// config are created
|
||||||
Namespace string
|
Namespace string
|
||||||
@ -484,6 +492,15 @@ func (config *NetworkingTestConfig) createNetShellPodSpec(podName, hostname stri
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
// we want sctp to be optional as it will load the sctp kernel module
|
||||||
|
if config.SCTPEnabled {
|
||||||
|
pod.Spec.Containers[0].Args = append(pod.Spec.Containers[0].Args, fmt.Sprintf("--sctp-port=%d", EndpointSCTPPort))
|
||||||
|
pod.Spec.Containers[0].Ports = append(pod.Spec.Containers[0].Ports, v1.ContainerPort{
|
||||||
|
Name: "sctp",
|
||||||
|
ContainerPort: EndpointSCTPPort,
|
||||||
|
Protocol: v1.ProtocolSCTP,
|
||||||
|
})
|
||||||
|
}
|
||||||
return pod
|
return pod
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,6 +535,10 @@ func (config *NetworkingTestConfig) createTestPodSpec() *v1.Pod {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
// we want sctp to be optional as it will load the sctp kernel module
|
||||||
|
if config.SCTPEnabled {
|
||||||
|
pod.Spec.Containers[0].Args = append(pod.Spec.Containers[0].Args, fmt.Sprintf("--sctp-port=%d", EndpointSCTPPort))
|
||||||
|
}
|
||||||
return pod
|
return pod
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,7 +547,7 @@ func (config *NetworkingTestConfig) createNodePortServiceSpec(svcName string, se
|
|||||||
if enableSessionAffinity {
|
if enableSessionAffinity {
|
||||||
sessionAffinity = v1.ServiceAffinityClientIP
|
sessionAffinity = v1.ServiceAffinityClientIP
|
||||||
}
|
}
|
||||||
return &v1.Service{
|
res := &v1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: svcName,
|
Name: svcName,
|
||||||
},
|
},
|
||||||
@ -540,6 +561,11 @@ func (config *NetworkingTestConfig) createNodePortServiceSpec(svcName string, se
|
|||||||
SessionAffinity: sessionAffinity,
|
SessionAffinity: sessionAffinity,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.SCTPEnabled {
|
||||||
|
res.Spec.Ports = append(res.Spec.Ports, v1.ServicePort{Port: ClusterSCTPPort, Name: "sctp", Protocol: v1.ProtocolSCTP, TargetPort: intstr.FromInt(EndpointSCTPPort)})
|
||||||
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *NetworkingTestConfig) createNodePortService(selector map[string]string) {
|
func (config *NetworkingTestConfig) createNodePortService(selector map[string]string) {
|
||||||
@ -633,6 +659,8 @@ func (config *NetworkingTestConfig) setup(selector map[string]string) {
|
|||||||
config.NodeUDPPort = int(p.NodePort)
|
config.NodeUDPPort = int(p.NodePort)
|
||||||
case v1.ProtocolTCP:
|
case v1.ProtocolTCP:
|
||||||
config.NodeHTTPPort = int(p.NodePort)
|
config.NodeHTTPPort = int(p.NodePort)
|
||||||
|
case v1.ProtocolSCTP:
|
||||||
|
config.NodeSCTPPort = int(p.NodePort)
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
ginkgo.It("should check kube-proxy urls", func() {
|
ginkgo.It("should check kube-proxy urls", func() {
|
||||||
// TODO: this is overkill we just need the host networking pod
|
// TODO: this is overkill we just need the host networking pod
|
||||||
// to hit kube-proxy urls.
|
// to hit kube-proxy urls.
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, true)
|
config := e2enetwork.NewNetworkingTestConfig(f, true, false)
|
||||||
|
|
||||||
ginkgo.By("checking kube-proxy URLs")
|
ginkgo.By("checking kube-proxy URLs")
|
||||||
config.GetSelfURL(ports.ProxyHealthzPort, "/healthz", "200 OK")
|
config.GetSelfURL(ports.ProxyHealthzPort, "/healthz", "200 OK")
|
||||||
@ -162,7 +162,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
ginkgo.Describe("Granular Checks: Services", func() {
|
ginkgo.Describe("Granular Checks: Services", func() {
|
||||||
|
|
||||||
ginkgo.It("should function for pod-Service: http", func() {
|
ginkgo.It("should function for pod-Service: http", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||||
config.DialFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should function for pod-Service: udp", func() {
|
ginkgo.It("should function for pod-Service: udp", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
||||||
config.DialFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -179,8 +179,19 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
config.DialFromTestContainer("udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromTestContainer("udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Once basic tests checking for the sctp module not to be loaded are implemented, this
|
||||||
|
// needs to be marked as [Disruptive]
|
||||||
|
ginkgo.It("should function for pod-Service: sctp [Feature:SCTPConnectivity]", func() {
|
||||||
|
config := e2enetwork.NewNetworkingTestConfig(f, false, true)
|
||||||
|
ginkgo.By(fmt.Sprintf("dialing(sctp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterSCTPPort))
|
||||||
|
config.DialFromTestContainer("sctp", config.ClusterIP, e2enetwork.ClusterSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
|
ginkgo.By(fmt.Sprintf("dialing(sctp) %v --> %v:%v (nodeIP)", config.TestContainerPod.Name, config.NodeIP, config.NodeSCTPPort))
|
||||||
|
config.DialFromTestContainer("sctp", config.NodeIP, config.NodeSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
})
|
||||||
|
|
||||||
ginkgo.It("should function for node-Service: http", func() {
|
ginkgo.It("should function for node-Service: http", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, true)
|
config := e2enetwork.NewNetworkingTestConfig(f, true, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||||
config.DialFromNode("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromNode("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -189,7 +200,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should function for node-Service: udp", func() {
|
ginkgo.It("should function for node-Service: udp", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, true)
|
config := e2enetwork.NewNetworkingTestConfig(f, true, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
||||||
config.DialFromNode("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromNode("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -198,7 +209,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should function for endpoint-Service: http", func() {
|
ginkgo.It("should function for endpoint-Service: http", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||||
config.DialFromEndpointContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromEndpointContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -207,7 +218,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should function for endpoint-Service: udp", func() {
|
ginkgo.It("should function for endpoint-Service: udp", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
||||||
config.DialFromEndpointContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromEndpointContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -216,7 +227,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should update endpoints: http", func() {
|
ginkgo.It("should update endpoints: http", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||||
config.DialFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -227,7 +238,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should update endpoints: udp", func() {
|
ginkgo.It("should update endpoints: udp", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
||||||
config.DialFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -239,7 +250,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
|
|
||||||
// Slow because we confirm that the nodePort doesn't serve traffic, which requires a period of polling.
|
// Slow because we confirm that the nodePort doesn't serve traffic, which requires a period of polling.
|
||||||
ginkgo.It("should update nodePort: http [Slow]", func() {
|
ginkgo.It("should update nodePort: http [Slow]", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, true)
|
config := e2enetwork.NewNetworkingTestConfig(f, true, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeHTTPPort))
|
||||||
config.DialFromNode("http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromNode("http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -251,7 +262,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
|
|
||||||
// Slow because we confirm that the nodePort doesn't serve traffic, which requires a period of polling.
|
// Slow because we confirm that the nodePort doesn't serve traffic, which requires a period of polling.
|
||||||
ginkgo.It("should update nodePort: udp [Slow]", func() {
|
ginkgo.It("should update nodePort: udp [Slow]", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, true)
|
config := e2enetwork.NewNetworkingTestConfig(f, true, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeUDPPort))
|
||||||
config.DialFromNode("udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
config.DialFromNode("udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
|
||||||
|
|
||||||
@ -263,7 +274,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
|
|
||||||
// [LinuxOnly]: Windows does not support session affinity.
|
// [LinuxOnly]: Windows does not support session affinity.
|
||||||
ginkgo.It("should function for client IP based session affinity: http [LinuxOnly]", func() {
|
ginkgo.It("should function for client IP based session affinity: http [LinuxOnly]", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v", config.TestContainerPod.Name, config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v", config.TestContainerPod.Name, config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||||
|
|
||||||
// Check if number of endpoints returned are exactly one.
|
// Check if number of endpoints returned are exactly one.
|
||||||
@ -281,7 +292,7 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
|
|
||||||
// [LinuxOnly]: Windows does not support session affinity.
|
// [LinuxOnly]: Windows does not support session affinity.
|
||||||
ginkgo.It("should function for client IP based session affinity: udp [LinuxOnly]", func() {
|
ginkgo.It("should function for client IP based session affinity: udp [LinuxOnly]", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v", config.TestContainerPod.Name, config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v", config.TestContainerPod.Name, config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterUDPPort))
|
||||||
|
|
||||||
// Check if number of endpoints returned are exactly one.
|
// Check if number of endpoints returned are exactly one.
|
||||||
@ -298,20 +309,29 @@ var _ = SIGDescribe("Networking", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should be able to handle large requests: http", func() {
|
ginkgo.It("should be able to handle large requests: http", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
|
||||||
message := strings.Repeat("42", 1000)
|
message := strings.Repeat("42", 1000)
|
||||||
config.DialEchoFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, message)
|
config.DialEchoFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, message)
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should be able to handle large requests: udp", func() {
|
ginkgo.It("should be able to handle large requests: udp", func() {
|
||||||
config := e2enetwork.NewNetworkingTestConfig(f, false)
|
config := e2enetwork.NewNetworkingTestConfig(f, false, false)
|
||||||
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
|
||||||
message := "n" + strings.Repeat("o", 1999)
|
message := "n" + strings.Repeat("o", 1999)
|
||||||
config.DialEchoFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, message)
|
config.DialEchoFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, message)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Once basic tests checking for the sctp module not to be loaded are implemented, this
|
||||||
|
// needs to be marked as [Disruptive]
|
||||||
|
ginkgo.It("should function for pod-pod: sctp [Feature:SCTPConnectivity]", func() {
|
||||||
|
config := e2enetwork.NewNetworkingTestConfig(f, false, true)
|
||||||
|
ginkgo.By(fmt.Sprintf("dialing(sctp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterSCTPPort))
|
||||||
|
message := "hello"
|
||||||
|
config.DialEchoFromTestContainer("sctp", config.TestContainerPod.Status.PodIP, e2enetwork.EndpointSCTPPort, config.MaxTries, 0, message)
|
||||||
|
})
|
||||||
|
|
||||||
ginkgo.It("should recreate its iptables rules if they are deleted [Disruptive]", func() {
|
ginkgo.It("should recreate its iptables rules if they are deleted [Disruptive]", func() {
|
||||||
e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
|
e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
|
||||||
e2eskipper.SkipUnlessSSHKeyPresent()
|
e2eskipper.SkipUnlessSSHKeyPresent()
|
||||||
|
@ -375,7 +375,7 @@ HTTP server:
|
|||||||
|
|
||||||
### netexec
|
### netexec
|
||||||
|
|
||||||
Starts a HTTP server on given TCP / UDP ports with the following endpoints:
|
Starts a HTTP server on given port with the following endpoints:
|
||||||
|
|
||||||
- `/`: Returns the request's timestamp.
|
- `/`: Returns the request's timestamp.
|
||||||
- `/clientip`: Returns the request's IP address.
|
- `/clientip`: Returns the request's IP address.
|
||||||
@ -389,7 +389,7 @@ Starts a HTTP server on given TCP / UDP ports with the following endpoints:
|
|||||||
- `request`: The HTTP endpoint or data to be sent through UDP. If not specified, it will result
|
- `request`: The HTTP endpoint or data to be sent through UDP. If not specified, it will result
|
||||||
in a `400 Bad Request` status code being returned.
|
in a `400 Bad Request` status code being returned.
|
||||||
- `protocol`: The protocol which will be used when making the request. Default value: `http`.
|
- `protocol`: The protocol which will be used when making the request. Default value: `http`.
|
||||||
Acceptable values: `http`, `udp`.
|
Acceptable values: `http`, `udp`, `sctp`.
|
||||||
- `tries`: The number of times the request will be performed. Default value: `1`.
|
- `tries`: The number of times the request will be performed. Default value: `1`.
|
||||||
- `/echo`: Returns the given `msg` (`/echo?msg=echoed_msg`)
|
- `/echo`: Returns the given `msg` (`/echo?msg=echoed_msg`)
|
||||||
- `/exit`: Closes the server with the given code (`/exit?code=some-code`). The `code`
|
- `/exit`: Closes the server with the given code (`/exit?code=some-code`). The `code`
|
||||||
@ -407,10 +407,19 @@ Starts a HTTP server on given TCP / UDP ports with the following endpoints:
|
|||||||
Returns a JSON with the fields `output` (containing the file's name on the server) and
|
Returns a JSON with the fields `output` (containing the file's name on the server) and
|
||||||
`error` containing any potential server side errors.
|
`error` containing any potential server side errors.
|
||||||
|
|
||||||
|
It will also start a UDP server on the indicated UDP port that responds to the following commands:
|
||||||
|
|
||||||
|
- `hostname`: Returns the server's hostname
|
||||||
|
- `echo <msg>`: Returns the given `<msg>`
|
||||||
|
- `clientip`: Returns the request's IP address
|
||||||
|
|
||||||
|
Additionally, if (and only if) `--sctp-port` is passed, it will start an SCTP server on that port,
|
||||||
|
responding to the same commands as the UDP server.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
kubectl exec test-agnhost -- /agnhost netexec [--http-port <http-port>] [--udp-port <udp-port>]
|
kubectl exec test-agnhost -- /agnhost netexec [--http-port <http-port>] [--udp-port <udp-port>] [--sctp-port <sctp-port>]
|
||||||
```
|
```
|
||||||
|
|
||||||
### nettest
|
### nettest
|
||||||
|
@ -11,6 +11,7 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/test/images/agnhost/netexec",
|
importpath = "k8s.io/kubernetes/test/images/agnhost/netexec",
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||||
|
"//vendor/github.com/ishidawataru/sctp:go_default_library",
|
||||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ishidawataru/sctp"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
@ -40,6 +41,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
httpPort = 8080
|
httpPort = 8080
|
||||||
udpPort = 8081
|
udpPort = 8081
|
||||||
|
sctpPort = -1
|
||||||
shellPath = "/bin/sh"
|
shellPath = "/bin/sh"
|
||||||
serverReady = &atomicBool{0}
|
serverReady = &atomicBool{0}
|
||||||
)
|
)
|
||||||
@ -47,8 +49,8 @@ var (
|
|||||||
// CmdNetexec is used by agnhost Cobra.
|
// CmdNetexec is used by agnhost Cobra.
|
||||||
var CmdNetexec = &cobra.Command{
|
var CmdNetexec = &cobra.Command{
|
||||||
Use: "netexec",
|
Use: "netexec",
|
||||||
Short: "Creates a HTTP / UDP server with various endpoints",
|
Short: "Creates HTTP, UDP, and (optionally) SCTP servers with various endpoints",
|
||||||
Long: `Starts a HTTP server on given TCP / UDP ports with the following endpoints:
|
Long: `Starts a HTTP server on given port with the following endpoints:
|
||||||
|
|
||||||
- /: Returns the request's timestamp.
|
- /: Returns the request's timestamp.
|
||||||
- /clientip: Returns the request's IP address.
|
- /clientip: Returns the request's IP address.
|
||||||
@ -62,7 +64,7 @@ var CmdNetexec = &cobra.Command{
|
|||||||
- "request": The HTTP endpoint or data to be sent through UDP. If not specified, it will result
|
- "request": The HTTP endpoint or data to be sent through UDP. If not specified, it will result
|
||||||
in a "400 Bad Request" status code being returned.
|
in a "400 Bad Request" status code being returned.
|
||||||
- "protocol": The protocol which will be used when making the request. Default value: "http".
|
- "protocol": The protocol which will be used when making the request. Default value: "http".
|
||||||
Acceptable values: "http", "udp".
|
Acceptable values: "http", "udp", "sctp".
|
||||||
- "tries": The number of times the request will be performed. Default value: "1".
|
- "tries": The number of times the request will be performed. Default value: "1".
|
||||||
- "/echo": Returns the given "msg" ("/echo?msg=echoed_msg")
|
- "/echo": Returns the given "msg" ("/echo?msg=echoed_msg")
|
||||||
- "/exit": Closes the server with the given code ("/exit?code=some-code"). The "code"
|
- "/exit": Closes the server with the given code ("/exit?code=some-code"). The "code"
|
||||||
@ -78,7 +80,17 @@ var CmdNetexec = &cobra.Command{
|
|||||||
- "/shutdown": Closes the server with the exit code 0.
|
- "/shutdown": Closes the server with the exit code 0.
|
||||||
- "/upload": Accepts a file to be uploaded, writing it in the "/uploads" folder on the host.
|
- "/upload": Accepts a file to be uploaded, writing it in the "/uploads" folder on the host.
|
||||||
Returns a JSON with the fields "output" (containing the file's name on the server) and
|
Returns a JSON with the fields "output" (containing the file's name on the server) and
|
||||||
"error" containing any potential server side errors.`,
|
"error" containing any potential server side errors.
|
||||||
|
|
||||||
|
It will also start a UDP server on the indicated UDP port that responds to the following commands:
|
||||||
|
|
||||||
|
- "hostname": Returns the server's hostname
|
||||||
|
- "echo <msg>": Returns the given <msg>
|
||||||
|
- "clientip": Returns the request's IP address
|
||||||
|
|
||||||
|
Additionally, if (and only if) --sctp-port is passed, it will start an SCTP server on that port,
|
||||||
|
responding to the same commands as the UDP server.
|
||||||
|
`,
|
||||||
Args: cobra.MaximumNArgs(0),
|
Args: cobra.MaximumNArgs(0),
|
||||||
Run: main,
|
Run: main,
|
||||||
}
|
}
|
||||||
@ -86,6 +98,7 @@ var CmdNetexec = &cobra.Command{
|
|||||||
func init() {
|
func init() {
|
||||||
CmdNetexec.Flags().IntVar(&httpPort, "http-port", 8080, "HTTP Listen Port")
|
CmdNetexec.Flags().IntVar(&httpPort, "http-port", 8080, "HTTP Listen Port")
|
||||||
CmdNetexec.Flags().IntVar(&udpPort, "udp-port", 8081, "UDP Listen Port")
|
CmdNetexec.Flags().IntVar(&udpPort, "udp-port", 8081, "UDP Listen Port")
|
||||||
|
CmdNetexec.Flags().IntVar(&sctpPort, "sctp-port", -1, "SCTP Listen Port")
|
||||||
}
|
}
|
||||||
|
|
||||||
// atomicBool uses load/store operations on an int32 to simulate an atomic boolean.
|
// atomicBool uses load/store operations on an int32 to simulate an atomic boolean.
|
||||||
@ -109,6 +122,9 @@ func (a *atomicBool) get() bool {
|
|||||||
|
|
||||||
func main(cmd *cobra.Command, args []string) {
|
func main(cmd *cobra.Command, args []string) {
|
||||||
go startUDPServer(udpPort)
|
go startUDPServer(udpPort)
|
||||||
|
if sctpPort != -1 {
|
||||||
|
go startSCTPServer(sctpPort)
|
||||||
|
}
|
||||||
startHTTPServer(httpPort)
|
startHTTPServer(httpPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,40 +214,37 @@ func dialHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, fmt.Sprintf("request parameter not specified. %v", err), http.StatusBadRequest)
|
http.Error(w, fmt.Sprintf("request parameter not specified. %v", err), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(protocol) == 0 {
|
|
||||||
|
hostPort := net.JoinHostPort(host, port)
|
||||||
|
var addr net.Addr
|
||||||
|
var dialer func(string, net.Addr) (string, error)
|
||||||
|
switch strings.ToLower(protocol) {
|
||||||
|
case "", "http":
|
||||||
protocol = "http"
|
protocol = "http"
|
||||||
} else {
|
dialer = dialHTTP
|
||||||
protocol = strings.ToLower(protocol)
|
addr, err = net.ResolveTCPAddr("tcp", hostPort)
|
||||||
}
|
case "udp":
|
||||||
if protocol != "http" && protocol != "udp" {
|
protocol = "udp"
|
||||||
|
dialer = dialUDP
|
||||||
|
addr, err = net.ResolveUDPAddr("udp", hostPort)
|
||||||
|
case "sctp":
|
||||||
|
protocol = "sctp"
|
||||||
|
dialer = dialSCTP
|
||||||
|
addr, err = sctp.ResolveSCTPAddr("sctp", hostPort)
|
||||||
|
default:
|
||||||
http.Error(w, fmt.Sprintf("unsupported protocol. %s", protocol), http.StatusBadRequest)
|
http.Error(w, fmt.Sprintf("unsupported protocol. %s", protocol), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
hostPort := net.JoinHostPort(host, port)
|
http.Error(w, fmt.Sprintf("host and/or port param are invalid. %v", err), http.StatusBadRequest)
|
||||||
var udpAddress *net.UDPAddr
|
return
|
||||||
if protocol == "udp" {
|
|
||||||
udpAddress, err = net.ResolveUDPAddr("udp", hostPort)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("host and/or port param are invalid. %v", err), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err = net.ResolveTCPAddr("tcp", hostPort)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("host and/or port param are invalid. %v", err), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errors := make([]string, 0)
|
errors := make([]string, 0)
|
||||||
responses := make([]string, 0)
|
responses := make([]string, 0)
|
||||||
var response string
|
var response string
|
||||||
for i := 0; i < tries; i++ {
|
for i := 0; i < tries; i++ {
|
||||||
if protocol == "udp" {
|
response, err = dialer(request, addr)
|
||||||
response, err = dialUDP(request, udpAddress)
|
|
||||||
} else {
|
|
||||||
response, err = dialHTTP(request, hostPort)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, fmt.Sprintf("%v", err))
|
errors = append(errors, fmt.Sprintf("%v", err))
|
||||||
} else {
|
} else {
|
||||||
@ -253,10 +266,10 @@ func dialHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialHTTP(request, hostPort string) (string, error) {
|
func dialHTTP(request string, addr net.Addr) (string, error) {
|
||||||
transport := utilnet.SetTransportDefaults(&http.Transport{})
|
transport := utilnet.SetTransportDefaults(&http.Transport{})
|
||||||
httpClient := createHTTPClient(transport)
|
httpClient := createHTTPClient(transport)
|
||||||
resp, err := httpClient.Get(fmt.Sprintf("http://%s/%s", hostPort, request))
|
resp, err := httpClient.Get(fmt.Sprintf("http://%s/%s", addr.String(), request))
|
||||||
defer transport.CloseIdleConnections()
|
defer transport.CloseIdleConnections()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
@ -276,8 +289,8 @@ func createHTTPClient(transport *http.Transport) *http.Client {
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialUDP(request string, remoteAddress *net.UDPAddr) (string, error) {
|
func dialUDP(request string, addr net.Addr) (string, error) {
|
||||||
Conn, err := net.DialUDP("udp", nil, remoteAddress)
|
Conn, err := net.DialUDP("udp", nil, addr.(*net.UDPAddr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("udp dial failed. err:%v", err)
|
return "", fmt.Errorf("udp dial failed. err:%v", err)
|
||||||
}
|
}
|
||||||
@ -297,6 +310,27 @@ func dialUDP(request string, remoteAddress *net.UDPAddr) (string, error) {
|
|||||||
return string(udpResponse[0:count]), nil
|
return string(udpResponse[0:count]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dialSCTP(request string, addr net.Addr) (string, error) {
|
||||||
|
Conn, err := sctp.DialSCTP("sctp", nil, addr.(*sctp.SCTPAddr))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("sctp dial failed. err:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer Conn.Close()
|
||||||
|
buf := []byte(request)
|
||||||
|
_, err = Conn.Write(buf)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("sctp connection write failed. err:%v", err)
|
||||||
|
}
|
||||||
|
sctpResponse := make([]byte, 1024)
|
||||||
|
Conn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||||
|
count, err := Conn.Read(sctpResponse)
|
||||||
|
if err != nil || count == 0 {
|
||||||
|
return "", fmt.Errorf("reading from sctp connection failed. err:'%v'", err)
|
||||||
|
}
|
||||||
|
return string(sctpResponse[0:count]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func shellHandler(w http.ResponseWriter, r *http.Request) {
|
func shellHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
cmd := r.FormValue("shellCommand")
|
cmd := r.FormValue("shellCommand")
|
||||||
if cmd == "" {
|
if cmd == "" {
|
||||||
@ -433,6 +467,53 @@ func startUDPServer(udpPort int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sctp server supports the hostName, echo and clientIP commands.
|
||||||
|
func startSCTPServer(sctpPort int) {
|
||||||
|
serverAddress, err := sctp.ResolveSCTPAddr("sctp", fmt.Sprintf(":%d", sctpPort))
|
||||||
|
assertNoError(err)
|
||||||
|
listener, err := sctp.ListenSCTP("sctp", serverAddress)
|
||||||
|
assertNoError(err)
|
||||||
|
defer listener.Close()
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
|
||||||
|
log.Printf("Started SCTP server")
|
||||||
|
// Start responding to readiness probes.
|
||||||
|
serverReady.set(true)
|
||||||
|
defer func() {
|
||||||
|
log.Printf("SCTP server exited")
|
||||||
|
serverReady.set(false)
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
conn, err := listener.AcceptSCTP()
|
||||||
|
assertNoError(err)
|
||||||
|
n, err := conn.Read(buf)
|
||||||
|
assertNoError(err)
|
||||||
|
receivedText := strings.ToLower(strings.TrimSpace(string(buf[0:n])))
|
||||||
|
if receivedText == "hostname" {
|
||||||
|
log.Println("Sending sctp hostName response")
|
||||||
|
_, err = conn.Write([]byte(getHostName()))
|
||||||
|
assertNoError(err)
|
||||||
|
} else if strings.HasPrefix(receivedText, "echo ") {
|
||||||
|
parts := strings.SplitN(receivedText, " ", 2)
|
||||||
|
resp := ""
|
||||||
|
if len(parts) == 2 {
|
||||||
|
resp = parts[1]
|
||||||
|
}
|
||||||
|
log.Printf("Echoing %v\n", resp)
|
||||||
|
_, err = conn.Write([]byte(resp))
|
||||||
|
assertNoError(err)
|
||||||
|
} else if receivedText == "clientip" {
|
||||||
|
clientAddress := conn.RemoteAddr()
|
||||||
|
log.Printf("Sending back clientip to %s", clientAddress.String())
|
||||||
|
_, err = conn.Write([]byte(clientAddress.String()))
|
||||||
|
assertNoError(err)
|
||||||
|
} else if len(receivedText) > 0 {
|
||||||
|
log.Printf("Unknown sctp command received: %v\n", receivedText)
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getHostName() string {
|
func getHostName() string {
|
||||||
hostName, err := os.Hostname()
|
hostName, err := os.Hostname()
|
||||||
assertNoError(err)
|
assertNoError(err)
|
||||||
|
1
vendor/BUILD
vendored
1
vendor/BUILD
vendored
@ -222,6 +222,7 @@ filegroup(
|
|||||||
"//vendor/github.com/hpcloud/tail:all-srcs",
|
"//vendor/github.com/hpcloud/tail:all-srcs",
|
||||||
"//vendor/github.com/imdario/mergo:all-srcs",
|
"//vendor/github.com/imdario/mergo:all-srcs",
|
||||||
"//vendor/github.com/inconshreveable/mousetrap:all-srcs",
|
"//vendor/github.com/inconshreveable/mousetrap:all-srcs",
|
||||||
|
"//vendor/github.com/ishidawataru/sctp:all-srcs",
|
||||||
"//vendor/github.com/jmespath/go-jmespath:all-srcs",
|
"//vendor/github.com/jmespath/go-jmespath:all-srcs",
|
||||||
"//vendor/github.com/jonboulle/clockwork:all-srcs",
|
"//vendor/github.com/jonboulle/clockwork:all-srcs",
|
||||||
"//vendor/github.com/json-iterator/go:all-srcs",
|
"//vendor/github.com/json-iterator/go:all-srcs",
|
||||||
|
16
vendor/github.com/ishidawataru/sctp/.gitignore
generated
vendored
Normal file
16
vendor/github.com/ishidawataru/sctp/.gitignore
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||||
|
.glide/
|
||||||
|
|
||||||
|
example/example
|
20
vendor/github.com/ishidawataru/sctp/.travis.yml
generated
vendored
Normal file
20
vendor/github.com/ishidawataru/sctp/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.6
|
||||||
|
- 1.7
|
||||||
|
- 1.8
|
||||||
|
- 1.9
|
||||||
|
- "1.10"
|
||||||
|
- "1.11"
|
||||||
|
- "1.12"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v -race ./...
|
||||||
|
- GOOS=linux GOARCH=amd64 go build .
|
||||||
|
- GOOS=linux GOARCH=arm go build .
|
||||||
|
- GOOS=linux GOARCH=arm64 go build .
|
||||||
|
- GOOS=linux GOARCH=ppc64le go build .
|
||||||
|
- (go version | grep go1.6 > /dev/null) || GOOS=linux GOARCH=s390x go build .
|
||||||
|
# can be compiled but not functional:
|
||||||
|
- GOOS=linux GOARCH=386 go build .
|
||||||
|
- GOOS=windows GOARCH=amd64 go build .
|
28
vendor/github.com/ishidawataru/sctp/BUILD
generated
vendored
Normal file
28
vendor/github.com/ishidawataru/sctp/BUILD
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"ipsock_linux.go",
|
||||||
|
"sctp.go",
|
||||||
|
"sctp_linux.go",
|
||||||
|
"sctp_unsupported.go",
|
||||||
|
],
|
||||||
|
importmap = "k8s.io/kubernetes/vendor/github.com/ishidawataru/sctp",
|
||||||
|
importpath = "github.com/ishidawataru/sctp",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
27
vendor/github.com/ishidawataru/sctp/GO_LICENSE
generated
vendored
Normal file
27
vendor/github.com/ishidawataru/sctp/GO_LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
201
vendor/github.com/ishidawataru/sctp/LICENSE
generated
vendored
Normal file
201
vendor/github.com/ishidawataru/sctp/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
18
vendor/github.com/ishidawataru/sctp/README.md
generated
vendored
Normal file
18
vendor/github.com/ishidawataru/sctp/README.md
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Stream Control Transmission Protocol (SCTP)
|
||||||
|
----
|
||||||
|
|
||||||
|
[](https://travis-ci.org/ishidawataru/sctp/builds)
|
||||||
|
|
||||||
|
Examples
|
||||||
|
----
|
||||||
|
|
||||||
|
See `example/sctp.go`
|
||||||
|
|
||||||
|
```go
|
||||||
|
$ cd example
|
||||||
|
$ go build
|
||||||
|
$ # run example SCTP server
|
||||||
|
$ ./example -server -port 1000 -ip 10.10.0.1,10.20.0.1
|
||||||
|
$ # run example SCTP client
|
||||||
|
$ ./example -port 1000 -ip 10.10.0.1,10.20.0.1
|
||||||
|
```
|
218
vendor/github.com/ishidawataru/sctp/ipsock_linux.go
generated
vendored
Normal file
218
vendor/github.com/ishidawataru/sctp/ipsock_linux.go
generated
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
package sctp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
// Boolean to int.
|
||||||
|
func boolint(b bool) int {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
func ipToSockaddr(family int, ip net.IP, port int, zone string) (syscall.Sockaddr, error) {
|
||||||
|
switch family {
|
||||||
|
case syscall.AF_INET:
|
||||||
|
if len(ip) == 0 {
|
||||||
|
ip = net.IPv4zero
|
||||||
|
}
|
||||||
|
ip4 := ip.To4()
|
||||||
|
if ip4 == nil {
|
||||||
|
return nil, &net.AddrError{Err: "non-IPv4 address", Addr: ip.String()}
|
||||||
|
}
|
||||||
|
sa := &syscall.SockaddrInet4{Port: port}
|
||||||
|
copy(sa.Addr[:], ip4)
|
||||||
|
return sa, nil
|
||||||
|
case syscall.AF_INET6:
|
||||||
|
// In general, an IP wildcard address, which is either
|
||||||
|
// "0.0.0.0" or "::", means the entire IP addressing
|
||||||
|
// space. For some historical reason, it is used to
|
||||||
|
// specify "any available address" on some operations
|
||||||
|
// of IP node.
|
||||||
|
//
|
||||||
|
// When the IP node supports IPv4-mapped IPv6 address,
|
||||||
|
// we allow an listener to listen to the wildcard
|
||||||
|
// address of both IP addressing spaces by specifying
|
||||||
|
// IPv6 wildcard address.
|
||||||
|
if len(ip) == 0 || ip.Equal(net.IPv4zero) {
|
||||||
|
ip = net.IPv6zero
|
||||||
|
}
|
||||||
|
// We accept any IPv6 address including IPv4-mapped
|
||||||
|
// IPv6 address.
|
||||||
|
ip6 := ip.To16()
|
||||||
|
if ip6 == nil {
|
||||||
|
return nil, &net.AddrError{Err: "non-IPv6 address", Addr: ip.String()}
|
||||||
|
}
|
||||||
|
//we set ZoneId to 0, as currently we use this functon only to probe the IP capabilities of the host
|
||||||
|
//if real Zone handling is required, the zone cache implementation in golang/net should be pulled here
|
||||||
|
sa := &syscall.SockaddrInet6{Port: port, ZoneId: 0}
|
||||||
|
copy(sa.Addr[:], ip6)
|
||||||
|
return sa, nil
|
||||||
|
}
|
||||||
|
return nil, &net.AddrError{Err: "invalid address family", Addr: ip.String()}
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
func sockaddr(a *net.TCPAddr, family int) (syscall.Sockaddr, error) {
|
||||||
|
if a == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
type ipStackCapabilities struct {
|
||||||
|
sync.Once // guards following
|
||||||
|
ipv4Enabled bool
|
||||||
|
ipv6Enabled bool
|
||||||
|
ipv4MappedIPv6Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
var ipStackCaps ipStackCapabilities
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
// supportsIPv4 reports whether the platform supports IPv4 networking
|
||||||
|
// functionality.
|
||||||
|
func supportsIPv4() bool {
|
||||||
|
ipStackCaps.Once.Do(ipStackCaps.probe)
|
||||||
|
return ipStackCaps.ipv4Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
// supportsIPv6 reports whether the platform supports IPv6 networking
|
||||||
|
// functionality.
|
||||||
|
func supportsIPv6() bool {
|
||||||
|
ipStackCaps.Once.Do(ipStackCaps.probe)
|
||||||
|
return ipStackCaps.ipv6Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
// supportsIPv4map reports whether the platform supports mapping an
|
||||||
|
// IPv4 address inside an IPv6 address at transport layer
|
||||||
|
// protocols. See RFC 4291, RFC 4038 and RFC 3493.
|
||||||
|
func supportsIPv4map() bool {
|
||||||
|
ipStackCaps.Once.Do(ipStackCaps.probe)
|
||||||
|
return ipStackCaps.ipv4MappedIPv6Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
// Probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication
|
||||||
|
// capabilities which are controlled by the IPV6_V6ONLY socket option
|
||||||
|
// and kernel configuration.
|
||||||
|
//
|
||||||
|
// Should we try to use the IPv4 socket interface if we're only
|
||||||
|
// dealing with IPv4 sockets? As long as the host system understands
|
||||||
|
// IPv4-mapped IPv6, it's okay to pass IPv4-mapeed IPv6 addresses to
|
||||||
|
// the IPv6 interface. That simplifies our code and is most
|
||||||
|
// general. Unfortunately, we need to run on kernels built without
|
||||||
|
// IPv6 support too. So probe the kernel to figure it out.
|
||||||
|
func (p *ipStackCapabilities) probe() {
|
||||||
|
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
|
||||||
|
switch err {
|
||||||
|
case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
|
||||||
|
case nil:
|
||||||
|
syscall.Close(s)
|
||||||
|
p.ipv4Enabled = true
|
||||||
|
}
|
||||||
|
var probes = []struct {
|
||||||
|
laddr net.TCPAddr
|
||||||
|
value int
|
||||||
|
}{
|
||||||
|
// IPv6 communication capability
|
||||||
|
{laddr: net.TCPAddr{IP: net.IPv6loopback}, value: 1},
|
||||||
|
// IPv4-mapped IPv6 address communication capability
|
||||||
|
{laddr: net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)}, value: 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range probes {
|
||||||
|
s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer syscall.Close(s)
|
||||||
|
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, probes[i].value)
|
||||||
|
sa, err := sockaddr(&(probes[i].laddr), syscall.AF_INET6)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := syscall.Bind(s, sa); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
p.ipv6Enabled = true
|
||||||
|
} else {
|
||||||
|
p.ipv4MappedIPv6Enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
//Change: we check the first IP address in the list of candidate SCTP IP addresses
|
||||||
|
func (a *SCTPAddr) isWildcard() bool {
|
||||||
|
if a == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if 0 == len(a.IPAddrs) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.IPAddrs[0].IP.IsUnspecified()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SCTPAddr) family() int {
|
||||||
|
if a != nil {
|
||||||
|
for _, ip := range a.IPAddrs {
|
||||||
|
if ip.IP.To4() == nil {
|
||||||
|
return syscall.AF_INET6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syscall.AF_INET
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
func favoriteAddrFamily(network string, laddr *SCTPAddr, raddr *SCTPAddr, mode string) (family int, ipv6only bool) {
|
||||||
|
switch network[len(network)-1] {
|
||||||
|
case '4':
|
||||||
|
return syscall.AF_INET, false
|
||||||
|
case '6':
|
||||||
|
return syscall.AF_INET6, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
|
||||||
|
if supportsIPv4map() || !supportsIPv4() {
|
||||||
|
return syscall.AF_INET6, false
|
||||||
|
}
|
||||||
|
if laddr == nil {
|
||||||
|
return syscall.AF_INET, false
|
||||||
|
}
|
||||||
|
return laddr.family(), false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (laddr == nil || laddr.family() == syscall.AF_INET) &&
|
||||||
|
(raddr == nil || raddr.family() == syscall.AF_INET) {
|
||||||
|
return syscall.AF_INET, false
|
||||||
|
}
|
||||||
|
return syscall.AF_INET6, false
|
||||||
|
}
|
||||||
|
|
||||||
|
//from https://github.com/golang/go
|
||||||
|
//Changes: it is for SCTP only
|
||||||
|
func setDefaultSockopts(s int, family int, ipv6only bool) error {
|
||||||
|
if family == syscall.AF_INET6 {
|
||||||
|
// Allow both IP versions even if the OS default
|
||||||
|
// is otherwise. Note that some operating systems
|
||||||
|
// never admit this option.
|
||||||
|
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
|
||||||
|
}
|
||||||
|
// Allow broadcast.
|
||||||
|
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
|
||||||
|
}
|
696
vendor/github.com/ishidawataru/sctp/sctp.go
generated
vendored
Normal file
696
vendor/github.com/ishidawataru/sctp/sctp.go
generated
vendored
Normal file
@ -0,0 +1,696 @@
|
|||||||
|
package sctp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SOL_SCTP = 132
|
||||||
|
|
||||||
|
SCTP_BINDX_ADD_ADDR = 0x01
|
||||||
|
SCTP_BINDX_REM_ADDR = 0x02
|
||||||
|
|
||||||
|
MSG_NOTIFICATION = 0x8000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_RTOINFO = iota
|
||||||
|
SCTP_ASSOCINFO
|
||||||
|
SCTP_INITMSG
|
||||||
|
SCTP_NODELAY
|
||||||
|
SCTP_AUTOCLOSE
|
||||||
|
SCTP_SET_PEER_PRIMARY_ADDR
|
||||||
|
SCTP_PRIMARY_ADDR
|
||||||
|
SCTP_ADAPTATION_LAYER
|
||||||
|
SCTP_DISABLE_FRAGMENTS
|
||||||
|
SCTP_PEER_ADDR_PARAMS
|
||||||
|
SCTP_DEFAULT_SENT_PARAM
|
||||||
|
SCTP_EVENTS
|
||||||
|
SCTP_I_WANT_MAPPED_V4_ADDR
|
||||||
|
SCTP_MAXSEG
|
||||||
|
SCTP_STATUS
|
||||||
|
SCTP_GET_PEER_ADDR_INFO
|
||||||
|
SCTP_DELAYED_ACK_TIME
|
||||||
|
SCTP_DELAYED_ACK = SCTP_DELAYED_ACK_TIME
|
||||||
|
SCTP_DELAYED_SACK = SCTP_DELAYED_ACK_TIME
|
||||||
|
|
||||||
|
SCTP_SOCKOPT_BINDX_ADD = 100
|
||||||
|
SCTP_SOCKOPT_BINDX_REM = 101
|
||||||
|
SCTP_SOCKOPT_PEELOFF = 102
|
||||||
|
SCTP_GET_PEER_ADDRS = 108
|
||||||
|
SCTP_GET_LOCAL_ADDRS = 109
|
||||||
|
SCTP_SOCKOPT_CONNECTX = 110
|
||||||
|
SCTP_SOCKOPT_CONNECTX3 = 111
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_EVENT_DATA_IO = 1 << iota
|
||||||
|
SCTP_EVENT_ASSOCIATION
|
||||||
|
SCTP_EVENT_ADDRESS
|
||||||
|
SCTP_EVENT_SEND_FAILURE
|
||||||
|
SCTP_EVENT_PEER_ERROR
|
||||||
|
SCTP_EVENT_SHUTDOWN
|
||||||
|
SCTP_EVENT_PARTIAL_DELIVERY
|
||||||
|
SCTP_EVENT_ADAPTATION_LAYER
|
||||||
|
SCTP_EVENT_AUTHENTICATION
|
||||||
|
SCTP_EVENT_SENDER_DRY
|
||||||
|
|
||||||
|
SCTP_EVENT_ALL = SCTP_EVENT_DATA_IO | SCTP_EVENT_ASSOCIATION | SCTP_EVENT_ADDRESS | SCTP_EVENT_SEND_FAILURE | SCTP_EVENT_PEER_ERROR | SCTP_EVENT_SHUTDOWN | SCTP_EVENT_PARTIAL_DELIVERY | SCTP_EVENT_ADAPTATION_LAYER | SCTP_EVENT_AUTHENTICATION | SCTP_EVENT_SENDER_DRY
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCTPNotificationType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_SN_TYPE_BASE = SCTPNotificationType(iota + (1 << 15))
|
||||||
|
SCTP_ASSOC_CHANGE
|
||||||
|
SCTP_PEER_ADDR_CHANGE
|
||||||
|
SCTP_SEND_FAILED
|
||||||
|
SCTP_REMOTE_ERROR
|
||||||
|
SCTP_SHUTDOWN_EVENT
|
||||||
|
SCTP_PARTIAL_DELIVERY_EVENT
|
||||||
|
SCTP_ADAPTATION_INDICATION
|
||||||
|
SCTP_AUTHENTICATION_INDICATION
|
||||||
|
SCTP_SENDER_DRY_EVENT
|
||||||
|
)
|
||||||
|
|
||||||
|
type NotificationHandler func([]byte) error
|
||||||
|
|
||||||
|
type EventSubscribe struct {
|
||||||
|
DataIO uint8
|
||||||
|
Association uint8
|
||||||
|
Address uint8
|
||||||
|
SendFailure uint8
|
||||||
|
PeerError uint8
|
||||||
|
Shutdown uint8
|
||||||
|
PartialDelivery uint8
|
||||||
|
AdaptationLayer uint8
|
||||||
|
Authentication uint8
|
||||||
|
SenderDry uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_CMSG_INIT = iota
|
||||||
|
SCTP_CMSG_SNDRCV
|
||||||
|
SCTP_CMSG_SNDINFO
|
||||||
|
SCTP_CMSG_RCVINFO
|
||||||
|
SCTP_CMSG_NXTINFO
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_UNORDERED = 1 << iota
|
||||||
|
SCTP_ADDR_OVER
|
||||||
|
SCTP_ABORT
|
||||||
|
SCTP_SACK_IMMEDIATELY
|
||||||
|
SCTP_EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_MAX_STREAM = 0xffff
|
||||||
|
)
|
||||||
|
|
||||||
|
type InitMsg struct {
|
||||||
|
NumOstreams uint16
|
||||||
|
MaxInstreams uint16
|
||||||
|
MaxAttempts uint16
|
||||||
|
MaxInitTimeout uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type SndRcvInfo struct {
|
||||||
|
Stream uint16
|
||||||
|
SSN uint16
|
||||||
|
Flags uint16
|
||||||
|
_ uint16
|
||||||
|
PPID uint32
|
||||||
|
Context uint32
|
||||||
|
TTL uint32
|
||||||
|
TSN uint32
|
||||||
|
CumTSN uint32
|
||||||
|
AssocID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type SndInfo struct {
|
||||||
|
SID uint16
|
||||||
|
Flags uint16
|
||||||
|
PPID uint32
|
||||||
|
Context uint32
|
||||||
|
AssocID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAddrsOld struct {
|
||||||
|
AssocID int32
|
||||||
|
AddrNum int32
|
||||||
|
Addrs uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type NotificationHeader struct {
|
||||||
|
Type uint16
|
||||||
|
Flags uint16
|
||||||
|
Length uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCTPState uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCTP_COMM_UP = SCTPState(iota)
|
||||||
|
SCTP_COMM_LOST
|
||||||
|
SCTP_RESTART
|
||||||
|
SCTP_SHUTDOWN_COMP
|
||||||
|
SCTP_CANT_STR_ASSOC
|
||||||
|
)
|
||||||
|
|
||||||
|
var nativeEndian binary.ByteOrder
|
||||||
|
var sndRcvInfoSize uintptr
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
i := uint16(1)
|
||||||
|
if *(*byte)(unsafe.Pointer(&i)) == 0 {
|
||||||
|
nativeEndian = binary.BigEndian
|
||||||
|
} else {
|
||||||
|
nativeEndian = binary.LittleEndian
|
||||||
|
}
|
||||||
|
info := SndRcvInfo{}
|
||||||
|
sndRcvInfoSize = unsafe.Sizeof(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBuf(v interface{}) []byte {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
binary.Write(&buf, nativeEndian, v)
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func htons(h uint16) uint16 {
|
||||||
|
if nativeEndian == binary.LittleEndian {
|
||||||
|
return (h << 8 & 0xff00) | (h >> 8 & 0xff)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
var ntohs = htons
|
||||||
|
|
||||||
|
// setInitOpts sets options for an SCTP association initialization
|
||||||
|
// see https://tools.ietf.org/html/rfc4960#page-25
|
||||||
|
func setInitOpts(fd int, options InitMsg) error {
|
||||||
|
optlen := unsafe.Sizeof(options)
|
||||||
|
_, _, err := setsockopt(fd, SCTP_INITMSG, uintptr(unsafe.Pointer(&options)), uintptr(optlen))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNumOstreams(fd, num int) error {
|
||||||
|
return setInitOpts(fd, InitMsg{NumOstreams: uint16(num)})
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCTPAddr struct {
|
||||||
|
IPAddrs []net.IPAddr
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SCTPAddr) ToRawSockAddrBuf() []byte {
|
||||||
|
p := htons(uint16(a.Port))
|
||||||
|
if len(a.IPAddrs) == 0 { // if a.IPAddrs list is empty - fall back to IPv4 zero addr
|
||||||
|
s := syscall.RawSockaddrInet4{
|
||||||
|
Family: syscall.AF_INET,
|
||||||
|
Port: p,
|
||||||
|
}
|
||||||
|
copy(s.Addr[:], net.IPv4zero)
|
||||||
|
return toBuf(s)
|
||||||
|
}
|
||||||
|
buf := []byte{}
|
||||||
|
for _, ip := range a.IPAddrs {
|
||||||
|
ipBytes := ip.IP
|
||||||
|
if len(ipBytes) == 0 {
|
||||||
|
ipBytes = net.IPv4zero
|
||||||
|
}
|
||||||
|
if ip4 := ipBytes.To4(); ip4 != nil {
|
||||||
|
s := syscall.RawSockaddrInet4{
|
||||||
|
Family: syscall.AF_INET,
|
||||||
|
Port: p,
|
||||||
|
}
|
||||||
|
copy(s.Addr[:], ip4)
|
||||||
|
buf = append(buf, toBuf(s)...)
|
||||||
|
} else {
|
||||||
|
var scopeid uint32
|
||||||
|
ifi, err := net.InterfaceByName(ip.Zone)
|
||||||
|
if err == nil {
|
||||||
|
scopeid = uint32(ifi.Index)
|
||||||
|
}
|
||||||
|
s := syscall.RawSockaddrInet6{
|
||||||
|
Family: syscall.AF_INET6,
|
||||||
|
Port: p,
|
||||||
|
Scope_id: scopeid,
|
||||||
|
}
|
||||||
|
copy(s.Addr[:], ipBytes)
|
||||||
|
buf = append(buf, toBuf(s)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SCTPAddr) String() string {
|
||||||
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
for n, i := range a.IPAddrs {
|
||||||
|
if i.IP.To4() != nil {
|
||||||
|
b.WriteString(i.String())
|
||||||
|
} else if i.IP.To16() != nil {
|
||||||
|
b.WriteRune('[')
|
||||||
|
b.WriteString(i.String())
|
||||||
|
b.WriteRune(']')
|
||||||
|
}
|
||||||
|
if n < len(a.IPAddrs)-1 {
|
||||||
|
b.WriteRune('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.WriteRune(':')
|
||||||
|
b.WriteString(strconv.Itoa(a.Port))
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SCTPAddr) Network() string { return "sctp" }
|
||||||
|
|
||||||
|
func ResolveSCTPAddr(network, addrs string) (*SCTPAddr, error) {
|
||||||
|
tcpnet := ""
|
||||||
|
switch network {
|
||||||
|
case "", "sctp":
|
||||||
|
tcpnet = "tcp"
|
||||||
|
case "sctp4":
|
||||||
|
tcpnet = "tcp4"
|
||||||
|
case "sctp6":
|
||||||
|
tcpnet = "tcp6"
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid net: %s", network)
|
||||||
|
}
|
||||||
|
elems := strings.Split(addrs, "/")
|
||||||
|
if len(elems) == 0 {
|
||||||
|
return nil, fmt.Errorf("invalid input: %s", addrs)
|
||||||
|
}
|
||||||
|
ipaddrs := make([]net.IPAddr, 0, len(elems))
|
||||||
|
for _, e := range elems[:len(elems)-1] {
|
||||||
|
tcpa, err := net.ResolveTCPAddr(tcpnet, e+":")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ipaddrs = append(ipaddrs, net.IPAddr{IP: tcpa.IP, Zone: tcpa.Zone})
|
||||||
|
}
|
||||||
|
tcpa, err := net.ResolveTCPAddr(tcpnet, elems[len(elems)-1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if tcpa.IP != nil {
|
||||||
|
ipaddrs = append(ipaddrs, net.IPAddr{IP: tcpa.IP, Zone: tcpa.Zone})
|
||||||
|
} else {
|
||||||
|
ipaddrs = nil
|
||||||
|
}
|
||||||
|
return &SCTPAddr{
|
||||||
|
IPAddrs: ipaddrs,
|
||||||
|
Port: tcpa.Port,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SCTPConnect(fd int, addr *SCTPAddr) (int, error) {
|
||||||
|
buf := addr.ToRawSockAddrBuf()
|
||||||
|
param := GetAddrsOld{
|
||||||
|
AddrNum: int32(len(buf)),
|
||||||
|
Addrs: uintptr(uintptr(unsafe.Pointer(&buf[0]))),
|
||||||
|
}
|
||||||
|
optlen := unsafe.Sizeof(param)
|
||||||
|
_, _, err := getsockopt(fd, SCTP_SOCKOPT_CONNECTX3, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen)))
|
||||||
|
if err == nil {
|
||||||
|
return int(param.AssocID), nil
|
||||||
|
} else if err != syscall.ENOPROTOOPT {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
r0, _, err := setsockopt(fd, SCTP_SOCKOPT_CONNECTX, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
|
||||||
|
return int(r0), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SCTPBind(fd int, addr *SCTPAddr, flags int) error {
|
||||||
|
var option uintptr
|
||||||
|
switch flags {
|
||||||
|
case SCTP_BINDX_ADD_ADDR:
|
||||||
|
option = SCTP_SOCKOPT_BINDX_ADD
|
||||||
|
case SCTP_BINDX_REM_ADDR:
|
||||||
|
option = SCTP_SOCKOPT_BINDX_REM
|
||||||
|
default:
|
||||||
|
return syscall.EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := addr.ToRawSockAddrBuf()
|
||||||
|
_, _, err := setsockopt(fd, option, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCTPConn struct {
|
||||||
|
_fd int32
|
||||||
|
notificationHandler NotificationHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) fd() int {
|
||||||
|
return int(atomic.LoadInt32(&c._fd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSCTPConn(fd int, handler NotificationHandler) *SCTPConn {
|
||||||
|
conn := &SCTPConn{
|
||||||
|
_fd: int32(fd),
|
||||||
|
notificationHandler: handler,
|
||||||
|
}
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) Write(b []byte) (int, error) {
|
||||||
|
return c.SCTPWrite(b, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) Read(b []byte) (int, error) {
|
||||||
|
n, _, err := c.SCTPRead(b)
|
||||||
|
if n < 0 {
|
||||||
|
n = 0
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetInitMsg(numOstreams, maxInstreams, maxAttempts, maxInitTimeout int) error {
|
||||||
|
return setInitOpts(c.fd(), InitMsg{
|
||||||
|
NumOstreams: uint16(numOstreams),
|
||||||
|
MaxInstreams: uint16(maxInstreams),
|
||||||
|
MaxAttempts: uint16(maxAttempts),
|
||||||
|
MaxInitTimeout: uint16(maxInitTimeout),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SubscribeEvents(flags int) error {
|
||||||
|
var d, a, ad, sf, p, sh, pa, ada, au, se uint8
|
||||||
|
if flags&SCTP_EVENT_DATA_IO > 0 {
|
||||||
|
d = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_ASSOCIATION > 0 {
|
||||||
|
a = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_ADDRESS > 0 {
|
||||||
|
ad = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_SEND_FAILURE > 0 {
|
||||||
|
sf = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_PEER_ERROR > 0 {
|
||||||
|
p = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_SHUTDOWN > 0 {
|
||||||
|
sh = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_PARTIAL_DELIVERY > 0 {
|
||||||
|
pa = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_ADAPTATION_LAYER > 0 {
|
||||||
|
ada = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_AUTHENTICATION > 0 {
|
||||||
|
au = 1
|
||||||
|
}
|
||||||
|
if flags&SCTP_EVENT_SENDER_DRY > 0 {
|
||||||
|
se = 1
|
||||||
|
}
|
||||||
|
param := EventSubscribe{
|
||||||
|
DataIO: d,
|
||||||
|
Association: a,
|
||||||
|
Address: ad,
|
||||||
|
SendFailure: sf,
|
||||||
|
PeerError: p,
|
||||||
|
Shutdown: sh,
|
||||||
|
PartialDelivery: pa,
|
||||||
|
AdaptationLayer: ada,
|
||||||
|
Authentication: au,
|
||||||
|
SenderDry: se,
|
||||||
|
}
|
||||||
|
optlen := unsafe.Sizeof(param)
|
||||||
|
_, _, err := setsockopt(c.fd(), SCTP_EVENTS, uintptr(unsafe.Pointer(¶m)), uintptr(optlen))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SubscribedEvents() (int, error) {
|
||||||
|
param := EventSubscribe{}
|
||||||
|
optlen := unsafe.Sizeof(param)
|
||||||
|
_, _, err := getsockopt(c.fd(), SCTP_EVENTS, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen)))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var flags int
|
||||||
|
if param.DataIO > 0 {
|
||||||
|
flags |= SCTP_EVENT_DATA_IO
|
||||||
|
}
|
||||||
|
if param.Association > 0 {
|
||||||
|
flags |= SCTP_EVENT_ASSOCIATION
|
||||||
|
}
|
||||||
|
if param.Address > 0 {
|
||||||
|
flags |= SCTP_EVENT_ADDRESS
|
||||||
|
}
|
||||||
|
if param.SendFailure > 0 {
|
||||||
|
flags |= SCTP_EVENT_SEND_FAILURE
|
||||||
|
}
|
||||||
|
if param.PeerError > 0 {
|
||||||
|
flags |= SCTP_EVENT_PEER_ERROR
|
||||||
|
}
|
||||||
|
if param.Shutdown > 0 {
|
||||||
|
flags |= SCTP_EVENT_SHUTDOWN
|
||||||
|
}
|
||||||
|
if param.PartialDelivery > 0 {
|
||||||
|
flags |= SCTP_EVENT_PARTIAL_DELIVERY
|
||||||
|
}
|
||||||
|
if param.AdaptationLayer > 0 {
|
||||||
|
flags |= SCTP_EVENT_ADAPTATION_LAYER
|
||||||
|
}
|
||||||
|
if param.Authentication > 0 {
|
||||||
|
flags |= SCTP_EVENT_AUTHENTICATION
|
||||||
|
}
|
||||||
|
if param.SenderDry > 0 {
|
||||||
|
flags |= SCTP_EVENT_SENDER_DRY
|
||||||
|
}
|
||||||
|
return flags, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetDefaultSentParam(info *SndRcvInfo) error {
|
||||||
|
optlen := unsafe.Sizeof(*info)
|
||||||
|
_, _, err := setsockopt(c.fd(), SCTP_DEFAULT_SENT_PARAM, uintptr(unsafe.Pointer(info)), uintptr(optlen))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) GetDefaultSentParam() (*SndRcvInfo, error) {
|
||||||
|
info := &SndRcvInfo{}
|
||||||
|
optlen := unsafe.Sizeof(*info)
|
||||||
|
_, _, err := getsockopt(c.fd(), SCTP_DEFAULT_SENT_PARAM, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(&optlen)))
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveFromRawAddr(ptr unsafe.Pointer, n int) (*SCTPAddr, error) {
|
||||||
|
addr := &SCTPAddr{
|
||||||
|
IPAddrs: make([]net.IPAddr, n),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch family := (*(*syscall.RawSockaddrAny)(ptr)).Addr.Family; family {
|
||||||
|
case syscall.AF_INET:
|
||||||
|
addr.Port = int(ntohs(uint16((*(*syscall.RawSockaddrInet4)(ptr)).Port)))
|
||||||
|
tmp := syscall.RawSockaddrInet4{}
|
||||||
|
size := unsafe.Sizeof(tmp)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
a := *(*syscall.RawSockaddrInet4)(unsafe.Pointer(
|
||||||
|
uintptr(ptr) + size*uintptr(i)))
|
||||||
|
addr.IPAddrs[i] = net.IPAddr{IP: a.Addr[:]}
|
||||||
|
}
|
||||||
|
case syscall.AF_INET6:
|
||||||
|
addr.Port = int(ntohs(uint16((*(*syscall.RawSockaddrInet4)(ptr)).Port)))
|
||||||
|
tmp := syscall.RawSockaddrInet6{}
|
||||||
|
size := unsafe.Sizeof(tmp)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
a := *(*syscall.RawSockaddrInet6)(unsafe.Pointer(
|
||||||
|
uintptr(ptr) + size*uintptr(i)))
|
||||||
|
var zone string
|
||||||
|
ifi, err := net.InterfaceByIndex(int(a.Scope_id))
|
||||||
|
if err == nil {
|
||||||
|
zone = ifi.Name
|
||||||
|
}
|
||||||
|
addr.IPAddrs[i] = net.IPAddr{IP: a.Addr[:], Zone: zone}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown address family: %d", family)
|
||||||
|
}
|
||||||
|
return addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sctpGetAddrs(fd, id, optname int) (*SCTPAddr, error) {
|
||||||
|
|
||||||
|
type getaddrs struct {
|
||||||
|
assocId int32
|
||||||
|
addrNum uint32
|
||||||
|
addrs [4096]byte
|
||||||
|
}
|
||||||
|
param := getaddrs{
|
||||||
|
assocId: int32(id),
|
||||||
|
}
|
||||||
|
optlen := unsafe.Sizeof(param)
|
||||||
|
_, _, err := getsockopt(fd, uintptr(optname), uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resolveFromRawAddr(unsafe.Pointer(¶m.addrs), int(param.addrNum))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPGetPrimaryPeerAddr() (*SCTPAddr, error) {
|
||||||
|
|
||||||
|
type sctpGetSetPrim struct {
|
||||||
|
assocId int32
|
||||||
|
addrs [128]byte
|
||||||
|
}
|
||||||
|
param := sctpGetSetPrim{
|
||||||
|
assocId: int32(0),
|
||||||
|
}
|
||||||
|
optlen := unsafe.Sizeof(param)
|
||||||
|
_, _, err := getsockopt(c.fd(), SCTP_PRIMARY_ADDR, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resolveFromRawAddr(unsafe.Pointer(¶m.addrs), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPLocalAddr(id int) (*SCTPAddr, error) {
|
||||||
|
return sctpGetAddrs(c.fd(), id, SCTP_GET_LOCAL_ADDRS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPRemoteAddr(id int) (*SCTPAddr, error) {
|
||||||
|
return sctpGetAddrs(c.fd(), id, SCTP_GET_PEER_ADDRS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) LocalAddr() net.Addr {
|
||||||
|
addr, err := sctpGetAddrs(c.fd(), 0, SCTP_GET_LOCAL_ADDRS)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) RemoteAddr() net.Addr {
|
||||||
|
addr, err := sctpGetAddrs(c.fd(), 0, SCTP_GET_PEER_ADDRS)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) PeelOff(id int) (*SCTPConn, error) {
|
||||||
|
type peeloffArg struct {
|
||||||
|
assocId int32
|
||||||
|
sd int
|
||||||
|
}
|
||||||
|
param := peeloffArg{
|
||||||
|
assocId: int32(id),
|
||||||
|
}
|
||||||
|
optlen := unsafe.Sizeof(param)
|
||||||
|
_, _, err := getsockopt(c.fd(), SCTP_SOCKOPT_PEELOFF, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SCTPConn{_fd: int32(param.sd)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetDeadline(t time.Time) error {
|
||||||
|
return syscall.EOPNOTSUPP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetReadDeadline(t time.Time) error {
|
||||||
|
return syscall.EOPNOTSUPP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return syscall.EOPNOTSUPP
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCTPListener struct {
|
||||||
|
fd int
|
||||||
|
m sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *SCTPListener) Addr() net.Addr {
|
||||||
|
laddr, err := sctpGetAddrs(ln.fd, 0, SCTP_GET_LOCAL_ADDRS)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return laddr
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCTPSndRcvInfoWrappedConn struct {
|
||||||
|
conn *SCTPConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSCTPSndRcvInfoWrappedConn(conn *SCTPConn) *SCTPSndRcvInfoWrappedConn {
|
||||||
|
conn.SubscribeEvents(SCTP_EVENT_DATA_IO)
|
||||||
|
return &SCTPSndRcvInfoWrappedConn{conn}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) Write(b []byte) (int, error) {
|
||||||
|
if len(b) < int(sndRcvInfoSize) {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
info := (*SndRcvInfo)(unsafe.Pointer(&b[0]))
|
||||||
|
n, err := c.conn.SCTPWrite(b[sndRcvInfoSize:], info)
|
||||||
|
return n + int(sndRcvInfoSize), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) Read(b []byte) (int, error) {
|
||||||
|
if len(b) < int(sndRcvInfoSize) {
|
||||||
|
return 0, syscall.EINVAL
|
||||||
|
}
|
||||||
|
n, info, err := c.conn.SCTPRead(b[sndRcvInfoSize:])
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
copy(b, toBuf(info))
|
||||||
|
return n + int(sndRcvInfoSize), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) Close() error {
|
||||||
|
return c.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) LocalAddr() net.Addr {
|
||||||
|
return c.conn.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) RemoteAddr() net.Addr {
|
||||||
|
return c.conn.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) SetDeadline(t time.Time) error {
|
||||||
|
return c.conn.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) SetReadDeadline(t time.Time) error {
|
||||||
|
return c.conn.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return c.conn.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) SetWriteBuffer(bytes int) error {
|
||||||
|
return c.conn.SetWriteBuffer(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) GetWriteBuffer() (int, error) {
|
||||||
|
return c.conn.GetWriteBuffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) SetReadBuffer(bytes int) error {
|
||||||
|
return c.conn.SetReadBuffer(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPSndRcvInfoWrappedConn) GetReadBuffer() (int, error) {
|
||||||
|
return c.conn.GetReadBuffer()
|
||||||
|
}
|
252
vendor/github.com/ishidawataru/sctp/sctp_linux.go
generated
vendored
Normal file
252
vendor/github.com/ishidawataru/sctp/sctp_linux.go
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
// +build linux,!386
|
||||||
|
|
||||||
|
package sctp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
||||||
|
// FIXME: syscall.SYS_SETSOCKOPT is undefined on 386
|
||||||
|
r0, r1, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT,
|
||||||
|
uintptr(fd),
|
||||||
|
SOL_SCTP,
|
||||||
|
optname,
|
||||||
|
optval,
|
||||||
|
optlen,
|
||||||
|
0)
|
||||||
|
if errno != 0 {
|
||||||
|
return r0, r1, errno
|
||||||
|
}
|
||||||
|
return r0, r1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
||||||
|
// FIXME: syscall.SYS_GETSOCKOPT is undefined on 386
|
||||||
|
r0, r1, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT,
|
||||||
|
uintptr(fd),
|
||||||
|
SOL_SCTP,
|
||||||
|
optname,
|
||||||
|
optval,
|
||||||
|
optlen,
|
||||||
|
0)
|
||||||
|
if errno != 0 {
|
||||||
|
return r0, r1, errno
|
||||||
|
}
|
||||||
|
return r0, r1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPWrite(b []byte, info *SndRcvInfo) (int, error) {
|
||||||
|
var cbuf []byte
|
||||||
|
if info != nil {
|
||||||
|
cmsgBuf := toBuf(info)
|
||||||
|
hdr := &syscall.Cmsghdr{
|
||||||
|
Level: syscall.IPPROTO_SCTP,
|
||||||
|
Type: SCTP_CMSG_SNDRCV,
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitwidth of hdr.Len is platform-specific,
|
||||||
|
// so we use hdr.SetLen() rather than directly setting hdr.Len
|
||||||
|
hdr.SetLen(syscall.CmsgSpace(len(cmsgBuf)))
|
||||||
|
cbuf = append(toBuf(hdr), cmsgBuf...)
|
||||||
|
}
|
||||||
|
return syscall.SendmsgN(c.fd(), b, cbuf, nil, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSndRcvInfo(b []byte) (*SndRcvInfo, error) {
|
||||||
|
msgs, err := syscall.ParseSocketControlMessage(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, m := range msgs {
|
||||||
|
if m.Header.Level == syscall.IPPROTO_SCTP {
|
||||||
|
switch m.Header.Type {
|
||||||
|
case SCTP_CMSG_SNDRCV:
|
||||||
|
return (*SndRcvInfo)(unsafe.Pointer(&m.Data[0])), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPRead(b []byte) (int, *SndRcvInfo, error) {
|
||||||
|
oob := make([]byte, 254)
|
||||||
|
for {
|
||||||
|
n, oobn, recvflags, _, err := syscall.Recvmsg(c.fd(), b, oob, 0)
|
||||||
|
if err != nil {
|
||||||
|
return n, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 && oobn == 0 {
|
||||||
|
return 0, nil, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if recvflags&MSG_NOTIFICATION > 0 && c.notificationHandler != nil {
|
||||||
|
if err := c.notificationHandler(b[:n]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var info *SndRcvInfo
|
||||||
|
if oobn > 0 {
|
||||||
|
info, err = parseSndRcvInfo(oob[:oobn])
|
||||||
|
}
|
||||||
|
return n, info, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) Close() error {
|
||||||
|
if c != nil {
|
||||||
|
fd := atomic.SwapInt32(&c._fd, -1)
|
||||||
|
if fd > 0 {
|
||||||
|
info := &SndRcvInfo{
|
||||||
|
Flags: SCTP_EOF,
|
||||||
|
}
|
||||||
|
c.SCTPWrite(nil, info)
|
||||||
|
syscall.Shutdown(int(fd), syscall.SHUT_RDWR)
|
||||||
|
return syscall.Close(int(fd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syscall.EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetWriteBuffer(bytes int) error {
|
||||||
|
return syscall.SetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) GetWriteBuffer() (int, error) {
|
||||||
|
return syscall.GetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_SNDBUF)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetReadBuffer(bytes int) error {
|
||||||
|
return syscall.SetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) GetReadBuffer() (int, error) {
|
||||||
|
return syscall.GetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_RCVBUF)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenSCTP - start listener on specified address/port
|
||||||
|
func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
||||||
|
return ListenSCTPExt(net, laddr, InitMsg{NumOstreams: SCTP_MAX_STREAM})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenSCTPExt - start listener on specified address/port with given SCTP options
|
||||||
|
func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListener, error) {
|
||||||
|
af, ipv6only := favoriteAddrFamily(network, laddr, nil, "listen")
|
||||||
|
sock, err := syscall.Socket(
|
||||||
|
af,
|
||||||
|
syscall.SOCK_STREAM,
|
||||||
|
syscall.IPPROTO_SCTP,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// close socket on error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
syscall.Close(sock)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = setInitOpts(sock, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if laddr != nil {
|
||||||
|
// If IP address and/or port was not provided so far, let's use the unspecified IPv4 or IPv6 address
|
||||||
|
if len(laddr.IPAddrs) == 0 {
|
||||||
|
if af == syscall.AF_INET {
|
||||||
|
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv4zero})
|
||||||
|
} else if af == syscall.AF_INET6 {
|
||||||
|
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv6zero})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = syscall.Listen(sock, syscall.SOMAXCONN)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SCTPListener{
|
||||||
|
fd: sock,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcceptSCTP waits for and returns the next SCTP connection to the listener.
|
||||||
|
func (ln *SCTPListener) AcceptSCTP() (*SCTPConn, error) {
|
||||||
|
fd, _, err := syscall.Accept4(ln.fd, 0)
|
||||||
|
return NewSCTPConn(fd, nil), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept waits for and returns the next connection connection to the listener.
|
||||||
|
func (ln *SCTPListener) Accept() (net.Conn, error) {
|
||||||
|
return ln.AcceptSCTP()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *SCTPListener) Close() error {
|
||||||
|
syscall.Shutdown(ln.fd, syscall.SHUT_RDWR)
|
||||||
|
return syscall.Close(ln.fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialSCTP - bind socket to laddr (if given) and connect to raddr
|
||||||
|
func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
||||||
|
return DialSCTPExt(net, laddr, raddr, InitMsg{NumOstreams: SCTP_MAX_STREAM})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialSCTPExt - same as DialSCTP but with given SCTP options
|
||||||
|
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
|
||||||
|
af, ipv6only := favoriteAddrFamily(network, laddr, raddr, "dial")
|
||||||
|
sock, err := syscall.Socket(
|
||||||
|
af,
|
||||||
|
syscall.SOCK_STREAM,
|
||||||
|
syscall.IPPROTO_SCTP,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// close socket on error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
syscall.Close(sock)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = setInitOpts(sock, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if laddr != nil {
|
||||||
|
// If IP address and/or port was not provided so far, let's use the unspecified IPv4 or IPv6 address
|
||||||
|
if len(laddr.IPAddrs) == 0 {
|
||||||
|
if af == syscall.AF_INET {
|
||||||
|
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv4zero})
|
||||||
|
} else if af == syscall.AF_INET6 {
|
||||||
|
laddr.IPAddrs = append(laddr.IPAddrs, net.IPAddr{IP: net.IPv6zero})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = SCTPConnect(sock, raddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewSCTPConn(sock, nil), nil
|
||||||
|
}
|
75
vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
generated
vendored
Normal file
75
vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// +build !linux linux,386
|
||||||
|
|
||||||
|
package sctp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrUnsupported = errors.New("SCTP is unsupported on " + runtime.GOOS + "/" + runtime.GOARCH)
|
||||||
|
|
||||||
|
func setsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
||||||
|
return 0, 0, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func getsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
||||||
|
return 0, 0, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPWrite(b []byte, info *SndRcvInfo) (int, error) {
|
||||||
|
return 0, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SCTPRead(b []byte) (int, *SndRcvInfo, error) {
|
||||||
|
return 0, nil, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) Close() error {
|
||||||
|
return ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetWriteBuffer(bytes int) error {
|
||||||
|
return ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) GetWriteBuffer() (int, error) {
|
||||||
|
return 0, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) SetReadBuffer(bytes int) error {
|
||||||
|
return ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SCTPConn) GetReadBuffer() (int, error) {
|
||||||
|
return 0, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
||||||
|
return nil, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListenSCTPExt(net string, laddr *SCTPAddr, options InitMsg) (*SCTPListener, error) {
|
||||||
|
return nil, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *SCTPListener) Accept() (net.Conn, error) {
|
||||||
|
return nil, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *SCTPListener) AcceptSCTP() (*SCTPConn, error) {
|
||||||
|
return nil, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *SCTPListener) Close() error {
|
||||||
|
return ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
||||||
|
return nil, ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
|
||||||
|
return nil, ErrUnsupported
|
||||||
|
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -478,6 +478,8 @@ github.com/hpcloud/tail/winfile
|
|||||||
github.com/imdario/mergo
|
github.com/imdario/mergo
|
||||||
# github.com/inconshreveable/mousetrap v1.0.0 => github.com/inconshreveable/mousetrap v1.0.0
|
# github.com/inconshreveable/mousetrap v1.0.0 => github.com/inconshreveable/mousetrap v1.0.0
|
||||||
github.com/inconshreveable/mousetrap
|
github.com/inconshreveable/mousetrap
|
||||||
|
# github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5 => github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5
|
||||||
|
github.com/ishidawataru/sctp
|
||||||
# github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af => github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
|
# github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af => github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
|
||||||
github.com/jmespath/go-jmespath
|
github.com/jmespath/go-jmespath
|
||||||
# github.com/jonboulle/clockwork v0.1.0 => github.com/jonboulle/clockwork v0.1.0
|
# github.com/jonboulle/clockwork v0.1.0 => github.com/jonboulle/clockwork v0.1.0
|
||||||
|
Loading…
Reference in New Issue
Block a user