mirror of
https://github.com/k8snetworkplumbingwg/multus-cni.git
synced 2025-09-02 01:19:31 +00:00
Compare commits
170 Commits
v4.2.2
...
release-3.
Author | SHA1 | Date | |
---|---|---|---|
|
812441ce17 | ||
|
d00e22aaca | ||
|
c6dca41433 | ||
|
3430f77b81 | ||
|
a30bc622b0 | ||
|
916690bae4 | ||
|
384bc19c84 | ||
|
55ec6a5c1c | ||
|
e52c28c945 | ||
|
e8726d7120 | ||
|
a4bcbc043c | ||
|
be46ee25b6 | ||
|
4ca7e30bf5 | ||
|
1cb7d0f9c0 | ||
|
cae7b7887a | ||
|
6d83c7f552 | ||
|
ae42a3a107 | ||
|
aaa7a07909 | ||
|
3f7aa2cf2f | ||
|
dc0b5c2a93 | ||
|
d1213c2dec | ||
|
c884bb77af | ||
|
0f1e336b62 | ||
|
a7cfc2d781 | ||
|
83987a0d73 | ||
|
3ad0d98bce | ||
|
ca50f32648 | ||
|
d3a1815632 | ||
|
c758877033 | ||
|
04311d3594 | ||
|
30f0ae914f | ||
|
10692b4538 | ||
|
abb8cd406f | ||
|
25c25916b5 | ||
|
707017a5cd | ||
|
81636bc0c6 | ||
|
2f70e96401 | ||
|
89b82c1264 | ||
|
b615316342 | ||
|
c42108e40a | ||
|
4b88a0293a | ||
|
89a3ffb08e | ||
|
1a2f8ccc9b | ||
|
d7b233d0f4 | ||
|
240ec14e3c | ||
|
f89e7e47bb | ||
|
e6a9fe8b11 | ||
|
b20f528de1 | ||
|
52ccadc1d4 | ||
|
13932b1cdd | ||
|
124ff4ee70 | ||
|
c8dc6316c9 | ||
|
9bf83c28d3 | ||
|
09fde13d79 | ||
|
7e0637f6a9 | ||
|
a4dbe7b102 | ||
|
bb69ac5058 | ||
|
0b153cd941 | ||
|
41160c62d6 | ||
|
381db908a2 | ||
|
f5bb00a5b1 | ||
|
f242f38a60 | ||
|
e13c535019 | ||
|
5b6d4320a0 | ||
|
31d87f615d | ||
|
dd8e7c3abd | ||
|
0390c1720c | ||
|
e691b1fa46 | ||
|
a805f63a04 | ||
|
b6c8dfbffb | ||
|
05ba224c08 | ||
|
93fe981913 | ||
|
d2a02a6e5d | ||
|
877f00be30 | ||
|
942ad4749e | ||
|
310c8e914c | ||
|
02913fb96f | ||
|
aff54bb1f7 | ||
|
57f1d7afc7 | ||
|
363b7fbc06 | ||
|
7094c9675f | ||
|
4aecbd2133 | ||
|
1e4fe4f837 | ||
|
11fe266139 | ||
|
68c5d0dd70 | ||
|
f47677d637 | ||
|
8b806df35c | ||
|
faae208bd7 | ||
|
61f9e08863 | ||
|
3a489263ea | ||
|
3a9cf4a9a2 | ||
|
b622593956 | ||
|
2ecb1a01a5 | ||
|
73e10fb999 | ||
|
972a7d18c6 | ||
|
f276c023f8 | ||
|
7174b9ac47 | ||
|
a51309c532 | ||
|
8d2445bb4c | ||
|
0a59253609 | ||
|
570a81d641 | ||
|
4ad64094b3 | ||
|
3e2c4b1528 | ||
|
2e070bd4a5 | ||
|
dd8492c44c | ||
|
09503c3dd3 | ||
|
1ee63551fa | ||
|
0e6cc2292a | ||
|
8c021bd46f | ||
|
50dfdb7036 | ||
|
5b5e5e5386 | ||
|
510c803d2c | ||
|
99dbdd9f57 | ||
|
61801e07d4 | ||
|
52f6892ba1 | ||
|
62b9dc51c1 | ||
|
80009b398c | ||
|
67380dbf9e | ||
|
7d551d100d | ||
|
9d20b37904 | ||
|
c4feebc6c9 | ||
|
787586aca8 | ||
|
8c2798a32a | ||
|
d87b7beeca | ||
|
ecb3260866 | ||
|
20ae7c25e5 | ||
|
e748969163 | ||
|
63ff3f1992 | ||
|
862eb5e8e2 | ||
|
abcee9ecda | ||
|
8b18175fc9 | ||
|
5892b36b7a | ||
|
fd5ac6801c | ||
|
d773dcfaad | ||
|
bcc6e21587 | ||
|
818c8d7c99 | ||
|
dd9fedee2a | ||
|
87b7dbc378 | ||
|
481c21b1e1 | ||
|
91a0e74a0d | ||
|
ac3731380c | ||
|
0a0c8d042a | ||
|
dae85d7781 | ||
|
6b573e8c4b | ||
|
606efe443f | ||
|
3458934e12 | ||
|
6b0266148b | ||
|
55792b94d5 | ||
|
061f4f913e | ||
|
bb89e538eb | ||
|
7f389e7e7c | ||
|
da20d1d875 | ||
|
fa2e35c4d4 | ||
|
35e4ee50a4 | ||
|
ae626b4aa5 | ||
|
25fd3ca8bc | ||
|
5380edbe6e | ||
|
980edbdf6c | ||
|
ae9a1a5c10 | ||
|
959ffaac3b | ||
|
346bed2d9d | ||
|
66361bfbb2 | ||
|
1ba90bad00 | ||
|
484385456b | ||
|
5988b7a82b | ||
|
2cfaa19dda | ||
|
539e92b8b0 | ||
|
93237e6161 | ||
|
bae3adf158 | ||
|
e9aa18319d |
@@ -1,15 +1,36 @@
|
||||
# This dockerfile is specific to building Multus for OpenShift
|
||||
FROM openshift/origin-release:golang-1.10 as builder
|
||||
|
||||
FROM openshift/origin-release:rhel-8-golang-1.12 as rhel8
|
||||
ADD . /usr/src/multus-cni
|
||||
WORKDIR /usr/src/multus-cni
|
||||
ENV CGO_ENABLED=1
|
||||
ENV GO111MODULE=off
|
||||
ENV VERSION=rhel8 COMMIT=unset
|
||||
RUN ./build && \
|
||||
cd /usr/src/multus-cni/bin
|
||||
WORKDIR /
|
||||
|
||||
FROM openshift/origin-release:rhel-7-golang-1.12 as rhel7
|
||||
ADD . /usr/src/multus-cni
|
||||
WORKDIR /usr/src/multus-cni
|
||||
ENV CGO_ENABLED=1
|
||||
ENV GO111MODULE=off
|
||||
RUN ./build && \
|
||||
cd /usr/src/multus-cni/bin
|
||||
|
||||
WORKDIR /usr/src/multus-cni
|
||||
ENV GO111MODULE=off
|
||||
RUN ./build
|
||||
RUN ./build && \
|
||||
cd /usr/src/multus-cni/bin
|
||||
WORKDIR /
|
||||
|
||||
FROM openshift/origin-base
|
||||
RUN mkdir -p /usr/src/multus-cni/images && mkdir -p /usr/src/multus-cni/bin
|
||||
COPY --from=builder /usr/src/multus-cni/bin/multus /usr/src/multus-cni/bin
|
||||
RUN mkdir -p /usr/src/multus-cni/images && \
|
||||
mkdir -p /usr/src/multus-cni/bin && \
|
||||
mkdir -p /usr/src/multus-cni/rhel7/bin && \
|
||||
mkdir -p /usr/src/multus-cni/rhel8/bin
|
||||
COPY --from=rhel7 /usr/src/multus-cni/bin/multus /usr/src/multus-cni/rhel7/bin
|
||||
COPY --from=rhel7 /usr/src/multus-cni/bin/multus /usr/src/multus-cni/bin
|
||||
COPY --from=rhel8 /usr/src/multus-cni/bin/multus /usr/src/multus-cni/rhel8/bin
|
||||
ADD ./images/entrypoint.sh /
|
||||
|
||||
LABEL io.k8s.display-name="Multus CNI" \
|
||||
|
15
OWNERS
Normal file
15
OWNERS
Normal file
@@ -0,0 +1,15 @@
|
||||
reviewers:
|
||||
- dougbtv
|
||||
- dcbw
|
||||
- squeed
|
||||
- zshi
|
||||
- fepan
|
||||
- s1061123
|
||||
approvers:
|
||||
- dougbtv
|
||||
- dcbw
|
||||
- squeed
|
||||
- zshi
|
||||
- fepan
|
||||
- s1061123
|
||||
|
6
build
6
build
@@ -22,7 +22,7 @@ fi
|
||||
DATE=$(date --iso-8601=seconds)
|
||||
COMMIT=${COMMIT:-$(git rev-parse --verify HEAD)}
|
||||
LDFLAGS="-X main.version=${VERSION:-master} -X main.commit=${COMMIT} -X main.date=${DATE}"
|
||||
export CGO_ENABLED=0
|
||||
export CGO_ENABLED=1
|
||||
|
||||
# this if... will be removed when gomodules goes default
|
||||
if [ "$GO111MODULE" == "off" ]; then
|
||||
@@ -40,11 +40,11 @@ if [ "$GO111MODULE" == "off" ]; then
|
||||
export GO15VENDOREXPERIMENT=1
|
||||
export GOBIN=${PWD}/bin
|
||||
export GOPATH=${PWD}/gopath
|
||||
go install -tags no_openssl -ldflags "${LDFLAGS}" "$@" ${REPO_PATH}/multus
|
||||
go install -ldflags "${LDFLAGS}" "$@" ${REPO_PATH}/multus
|
||||
else
|
||||
# build with go modules
|
||||
export GO111MODULE=on
|
||||
|
||||
echo "Building plugins"
|
||||
go build -o ${DEST_DIR}/multus -tags no_openssl -ldflags "${LDFLAGS}" "$@" ./multus
|
||||
go build -o ${DEST_DIR}/multus -ldflags "${LDFLAGS}" "$@" ./multus
|
||||
fi
|
||||
|
95
deployment/webhook/certs.sh
Executable file
95
deployment/webhook/certs.sh
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# 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.
|
||||
|
||||
# create temp dir to store intermediate files
|
||||
tmp=$(mktemp -d)
|
||||
|
||||
# generate private key
|
||||
echo "Generating private RSA key..."
|
||||
openssl genrsa -out ${tmp}/webhook-key.pem 2048 >/dev/null 2>&1
|
||||
|
||||
# generate CSR
|
||||
echo "Generating CSR configuration file..."
|
||||
cat <<EOF >> ${tmp}/webhook.conf
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
DNS.1 = multus-webhook-service
|
||||
DNS.2 = multus-webhook-service.default
|
||||
DNS.3 = multus-webhook-service.default.svc
|
||||
EOF
|
||||
openssl req -new -key ${tmp}/webhook-key.pem -subj "/CN=multus-webhook-service.default.svc" -out ${tmp}/server.csr -config ${tmp}/webhook.conf
|
||||
|
||||
# push CSR to Kubernetes API server
|
||||
echo "Sending CSR to Kubernetes..."
|
||||
csr_name="multus-webhook-service.default"
|
||||
kubectl delete csr ${csr_name} >/dev/null 2>&1
|
||||
cat <<EOF | kubectl create -f -
|
||||
apiVersion: certificates.k8s.io/v1beta1
|
||||
kind: CertificateSigningRequest
|
||||
metadata:
|
||||
name: ${csr_name}
|
||||
spec:
|
||||
request: $(cat ${tmp}/server.csr | base64 -w0)
|
||||
groups:
|
||||
- system:authenticated
|
||||
usages:
|
||||
- digital signature
|
||||
- key encipherment
|
||||
- server auth
|
||||
EOF
|
||||
|
||||
# approve certificate
|
||||
echo "Approving CSR..."
|
||||
kubectl certificate approve ${csr_name}
|
||||
|
||||
# wait for the cert to be issued
|
||||
echo -n "Waiting for the certificate to be issued..."
|
||||
cert=""
|
||||
for sec in $(seq 15); do
|
||||
cert=$(kubectl get csr ${csr_name} -o jsonpath='{.status.certificate}')
|
||||
if [[ $cert != "" ]]; then
|
||||
echo -e "\nCertificate issued succesfully."
|
||||
echo $cert | base64 --decode > ${tmp}/webhook-cert.pem
|
||||
break
|
||||
fi
|
||||
echo -n "."; sleep 1
|
||||
done
|
||||
if [[ $cert == "" ]]; then
|
||||
echo -e "\nError: certificate not issued. Verify that the API for signing certificates is enabled."
|
||||
exit
|
||||
fi
|
||||
|
||||
# create secret
|
||||
echo "Creating secret..."
|
||||
kubectl delete secret "multus-webhook-secret"
|
||||
kubectl create secret generic --from-file=key.pem=${tmp}/webhook-key.pem --from-file=cert.pem=${tmp}/webhook-cert.pem "multus-webhook-secret"
|
||||
|
||||
# set cert in webhook configuration
|
||||
echo "Patching configuration file with certificate..."
|
||||
if [[ -f configuration-template.yaml ]]; then
|
||||
sed "s/__CERT__/${cert}/" configuration-template.yaml > configuration.yaml
|
||||
echo "File configuration.yaml patched."
|
||||
else
|
||||
echo -e "Error: validating configuration template file 'configuration-template.yaml' is missing. Please update it with cert.pem value from the secret manually."
|
||||
fi
|
38
deployment/webhook/configuration-template.yaml
Normal file
38
deployment/webhook/configuration-template.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# 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.
|
||||
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
labels:
|
||||
app: multus-webhook
|
||||
name: multus-webhook-config
|
||||
webhooks:
|
||||
- clientConfig:
|
||||
caBundle: __CERT__
|
||||
service:
|
||||
name: multus-webhook-service
|
||||
namespace: default
|
||||
path: /validate
|
||||
failurePolicy: Fail
|
||||
name: multus-webhook.k8s.cni.cncf.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- k8s.cni.cncf.io
|
||||
apiVersions:
|
||||
- v1
|
||||
resources:
|
||||
- network-attachment-definitions
|
||||
operations:
|
||||
- CREATE
|
50
deployment/webhook/deployment.yaml
Normal file
50
deployment/webhook/deployment.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# 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.
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: multus-webhook
|
||||
name: multus-webhook-deployment
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: multus-webhook
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: multus-webhook
|
||||
spec:
|
||||
containers:
|
||||
- name: multus-webhook
|
||||
image: multus-webhook
|
||||
command:
|
||||
- /webhook/webhook
|
||||
args:
|
||||
- --bind-address=0.0.0.0
|
||||
- --port=443
|
||||
- --tls-private-key-file=/webhook/tls/key.pem
|
||||
- --tls-cert-file=/webhook/tls/cert.pem
|
||||
volumeMounts:
|
||||
- mountPath: /webhook/tls
|
||||
name: multus-webhook-secret
|
||||
readOnly: True
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumes:
|
||||
- name: multus-webhook-secret
|
||||
secret:
|
||||
secretName: multus-webhook-secret
|
27
deployment/webhook/service.yaml
Normal file
27
deployment/webhook/service.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# 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.
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: multus-webhook-service
|
||||
labels:
|
||||
app: multus-webhook
|
||||
namespace: default
|
||||
spec:
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 443
|
||||
selector:
|
||||
app: multus-webhook
|
@@ -117,6 +117,8 @@ You may configure the logging level by using the `LogLevel` option in your CNI c
|
||||
|
||||
The functionality provided by the `namespaceIsolation` configuration option enables a mode where Multus only allows pods to access custom resources (the `NetworkAttachmentDefinitions`) within the namespace where that pod resides. In other words, the `NetworkAttachmentDefinitions` are isolated to usage within the namespace in which they're created.
|
||||
|
||||
**NOTE**: The default namespace is special in this scenario. Even with namespace isolation enabled, any pod, in any namespace is allowed to refer to `NetworkAttachmentDefinitions` in the default namespace. This allows you to create commonly used unprivileged `NetworkAttachmentDefinitions` without having to put them in all namespaces. For example, if you had a `NetworkAttachmentDefinition` named `foo` the default namespace, you may reference it in an annotation with: `default/foo`.
|
||||
|
||||
For example, if a pod is created in the namespace called `development`, Multus will not allow networks to be attached when defined by custom resources created in a different namespace, say in the `default` network.
|
||||
|
||||
Consider the situation where you have a system that has users of different privilege levels -- as an example, a platform which has two administrators: a Senior Administrator and a Junior Administrator. The Senior Administrator may have access to all namespaces, and some network configurations as used by Multus are considered to be privileged in that they allow access to some protected resources available on the network. However, the Junior Administrator has access to only a subset of namespaces, and therefore it should be assumed that the Junior Administrator cannot create pods in their limited subset of namespaces. The `namespaceIsolation` feature provides for this isolation, allowing pods created in given namespaces to only access custom resources in the same namespace as the pod.
|
||||
|
@@ -615,3 +615,11 @@ Additionally when using CRIO, you may wish to have the CNI config file that's us
|
||||
When using `--multus-conf-file=auto` you may also care to specify a `binDir` in the configuration, this can be accomplished using the `--additional-bin-dir` option.
|
||||
|
||||
--additional-bin-dir=/opt/multus/bin
|
||||
|
||||
Sometimes, you may wish to not have the entrypoint copy the binary file onto the host. Potentially, you have another way to copy in a specific version of Multus, for example. By default, it's always copied, but you may disable the copy with:
|
||||
|
||||
--skip-multus-binary-copy=true
|
||||
|
||||
If you wish to have auto configuration use the `readinessindicatorfile` in the configuration, you can use the `--readiness-indicator-file` to express which file should be used as the readiness indicator.
|
||||
|
||||
--readiness-indicator-file=/path/to/file
|
||||
|
112
doc/webhook/webhook.md
Normal file
112
doc/webhook/webhook.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Validating admission webhook
|
||||
|
||||
## Building Docker image
|
||||
|
||||
From the root directory of Multus execute:
|
||||
```
|
||||
cd webhook
|
||||
./build
|
||||
```
|
||||
|
||||
## Deploying webhook application
|
||||
|
||||
Change working directory. From the root directory of Multus execute:
|
||||
```
|
||||
cd deployment/webhook
|
||||
```
|
||||
|
||||
Create key and certificate pair and patch configuration-template.yaml file with base64-encoded certificate file. Run:
|
||||
```
|
||||
./certs.sh
|
||||
```
|
||||
*Note: Verify that Kubernetes controller manager has --cluster-signing-cert-file and --cluster-signing-key-file parameters set to paths to your CA keypair,
|
||||
to make sure that Certificates API is enabled in order to generate certificate signed by cluster CA.
|
||||
Script generates private key and certificate signing request, which is then pushed to the Kubernetes API server.
|
||||
Then script approves that CSR and API server issues the certificate. Certificate is obtained from the API server and used to create a secret.
|
||||
Script also patches `configuration-template.yaml` file with base64-encoded certificate and creates `configuration.yaml` file containing
|
||||
Validating Webhook Configuration specification, which is deployed in one of the next steps.
|
||||
More details about TLS certificates management in a cluster available [here](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/).*
|
||||
|
||||
Create service:
|
||||
```
|
||||
kubectl create -f service.yaml
|
||||
```
|
||||
|
||||
Run deployment:
|
||||
```
|
||||
kubectl create -f deployment.yaml
|
||||
```
|
||||
|
||||
Create Validating Webhook Configuration:
|
||||
```
|
||||
kubectl create -f configuration.yaml
|
||||
```
|
||||
|
||||
## Verifying installation
|
||||
|
||||
Try to create invalid Network Attachment Definition resource:
|
||||
```
|
||||
cat <<EOF | kubectl create -f -
|
||||
apiVersion: "k8s.cni.cncf.io/v1"
|
||||
kind: NetworkAttachmentDefinition
|
||||
metadata:
|
||||
name: invalid-net-attach-def
|
||||
spec:
|
||||
config: '{
|
||||
"invalid": "config"
|
||||
}'
|
||||
EOF
|
||||
```
|
||||
Webhook should deny the request:
|
||||
```
|
||||
Error from server: error when creating "STDIN": admission webhook "multus-webhook.k8s.cni.cncf.io" denied the request: Invalid network config spec
|
||||
```
|
||||
|
||||
Now, try to create correctly defined one:
|
||||
```
|
||||
cat <<EOF | kubectl create -f -
|
||||
apiVersion: "k8s.cni.cncf.io/v1"
|
||||
kind: NetworkAttachmentDefinition
|
||||
metadata:
|
||||
name: correct-net-attach-def
|
||||
spec:
|
||||
config: '{
|
||||
"cniVersion": "0.3.0",
|
||||
"name": "a-bridge-network",
|
||||
"type": "bridge",
|
||||
"bridge": "br0",
|
||||
"isGateway": true,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "192.168.5.0/24",
|
||||
"dataDir": "/mnt/cluster-ipam"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
```
|
||||
Resource should be allowed and created:
|
||||
```
|
||||
networkattachmentdefinition.k8s.cni.cncf.io/correct-net-attach-def created
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
Webhook server prints a lot of debug messages that could help to find the root cause of an issue.
|
||||
To display logs run:
|
||||
```
|
||||
kubectl logs -l app=multus-webhook
|
||||
```
|
||||
Example output showing logs for handling requests generated in the "Verifying installation section":
|
||||
```
|
||||
# kubectl logs multus-webhook-pod
|
||||
2018-08-22T13:33:09Z [debug] Starting Multus webhook server
|
||||
2018-08-22T13:33:32Z [debug] Validating network config spec: { "invalid": "config" }
|
||||
2018-08-22T13:33:32Z [debug] Spec is not a valid network config: error parsing configuration list: no name. Trying to parse into config list
|
||||
2018-08-22T13:33:32Z [debug] Spec is not a valid network config list: error parsing configuration: missing 'type'
|
||||
2018-08-22T13:33:32Z [error] Invalid config: error parsing configuration: missing 'type'
|
||||
2018-08-22T13:33:32Z [debug] Sending response to the API server
|
||||
2018-08-22T13:35:29Z [debug] Validating network config spec: { "cniVersion": "0.3.0", "name": "a-bridge-network", "type": "bridge", "bridge": "br0", "isGateway": true, "ipam": { "type": "host-local", "subnet": "192.168.5.0/24", "dataDir": "/mnt/cluster-ipam" } }
|
||||
2018-08-22T13:35:29Z [debug] Spec is not a valid network config: error parsing configuration list: no 'plugins' key. Trying to parse into config list
|
||||
2018-08-22T13:35:29Z [debug] Network Attachment Defintion is valid. Admission Review request allowed
|
||||
2018-08-22T13:35:29Z [debug] Sending response to the API server
|
||||
```
|
||||
|
@@ -3,20 +3,6 @@
|
||||
# Always exit on errors.
|
||||
set -e
|
||||
|
||||
# Run a clean up when we exit if configured to do so.
|
||||
trap cleanup TERM
|
||||
function cleanup {
|
||||
if [ "$MULTUS_CLEANUP_CONFIG_ON_EXIT" == "true" ]; then
|
||||
CONF=$(cat <<-EOF
|
||||
{Multus configuration intentionally invalidated to prevent pods from being scheduled.}
|
||||
EOF
|
||||
)
|
||||
echo $CONF > $CNI_CONF_DIR/00-multus.conf
|
||||
log "Multus configuration intentionally invalidated to prevent pods from being scheduled."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Set our known directories.
|
||||
CNI_CONF_DIR="/host/etc/cni/net.d"
|
||||
CNI_BIN_DIR="/host/opt/cni/bin"
|
||||
@@ -28,11 +14,13 @@ MULTUS_KUBECONFIG_FILE_HOST="/etc/cni/net.d/multus.d/multus.kubeconfig"
|
||||
MULTUS_NAMESPACE_ISOLATION=false
|
||||
MULTUS_LOG_LEVEL=""
|
||||
MULTUS_LOG_FILE=""
|
||||
MULTUS_READINESS_INDICATOR_FILE=""
|
||||
OVERRIDE_NETWORK_NAME=false
|
||||
MULTUS_CLEANUP_CONFIG_ON_EXIT=false
|
||||
RESTART_CRIO=false
|
||||
CRIO_RESTARTED_ONCE=false
|
||||
RENAME_SOURCE_CONFIG_FILE=false
|
||||
SKIP_BINARY_COPY=false
|
||||
|
||||
# Give help text for parameters.
|
||||
function usage()
|
||||
@@ -51,6 +39,7 @@ function usage()
|
||||
echo -e "\t--cni-version=<cniVersion (e.g. 0.3.1)>"
|
||||
echo -e "\t--multus-conf-file=$MULTUS_CONF_FILE"
|
||||
echo -e "\t--multus-bin-file=$MULTUS_BIN_FILE"
|
||||
echo -e "\t--skip-multus-binary-copy=$SKIP_BINARY_COPY"
|
||||
echo -e "\t--multus-kubeconfig-file-host=$MULTUS_KUBECONFIG_FILE_HOST"
|
||||
echo -e "\t--namespace-isolation=$MULTUS_NAMESPACE_ISOLATION"
|
||||
echo -e "\t--multus-autoconfig-dir=$MULTUS_AUTOCONF_DIR (used only with --multus-conf-file=auto)"
|
||||
@@ -59,6 +48,7 @@ function usage()
|
||||
echo -e "\t--override-network-name=false (used only with --multus-conf-file=auto)"
|
||||
echo -e "\t--cleanup-config-on-exit=false (used only with --multus-conf-file=auto)"
|
||||
echo -e "\t--rename-conf-file=false (used only with --multus-conf-file=auto)"
|
||||
echo -e "\t--readiness-indicator-file=$MULTUS_READINESS_INDICATOR_FILE (used only with --multus-conf-file=auto)"
|
||||
echo -e "\t--additional-bin-dir=$ADDITIONAL_BIN_DIR (adds binDir option to configuration, used only with --multus-conf-file=auto)"
|
||||
echo -e "\t--restart-crio=false (restarts CRIO after config file is generated)"
|
||||
}
|
||||
@@ -132,6 +122,12 @@ while [ "$1" != "" ]; do
|
||||
--additional-bin-dir)
|
||||
ADDITIONAL_BIN_DIR=$VALUE
|
||||
;;
|
||||
--skip-multus-binary-copy)
|
||||
SKIP_BINARY_COPY=$VALUE
|
||||
;;
|
||||
--readiness-indicator-file)
|
||||
MULTUS_READINESS_INDICATOR_FILE=$VALUE
|
||||
;;
|
||||
*)
|
||||
warn "unknown parameter \"$PARAM\""
|
||||
;;
|
||||
@@ -157,8 +153,13 @@ do
|
||||
done
|
||||
|
||||
# Copy files into place and atomically move into final binary name
|
||||
cp -f $MULTUS_BIN_FILE $CNI_BIN_DIR/_multus
|
||||
mv -f $CNI_BIN_DIR/_multus $CNI_BIN_DIR/multus
|
||||
if [ "$SKIP_BINARY_COPY" = false ]; then
|
||||
cp -f $MULTUS_BIN_FILE $CNI_BIN_DIR/_multus
|
||||
mv -f $CNI_BIN_DIR/_multus $CNI_BIN_DIR/multus
|
||||
else
|
||||
log "Entrypoint skipped copying Multus binary."
|
||||
fi
|
||||
|
||||
if [ "$MULTUS_CONF_FILE" != "auto" ]; then
|
||||
cp -f $MULTUS_CONF_FILE $CNI_CONF_DIR
|
||||
fi
|
||||
@@ -240,13 +241,6 @@ if [ "$MULTUS_CONF_FILE" == "auto" ]; then
|
||||
log "Attemping to find master plugin configuration, attempt $tries"
|
||||
fi
|
||||
let "tries+=1"
|
||||
# See if the Multus configuration file exists, if it does then clean it up.
|
||||
if [ "$MULTUS_CLEANUP_CONFIG_ON_EXIT" == true ] && [ -f "$CNI_CONF_DIR/00-multus.conf" ]; then
|
||||
# But first, check if it has the invalidated configuration in it (otherwise we keep doing this over and over.)
|
||||
if ! grep -q "invalidated" $CNI_CONF_DIR/00-multus.conf; then
|
||||
cleanup
|
||||
fi
|
||||
fi
|
||||
sleep 1;
|
||||
else
|
||||
error "Multus could not be configured: no master plugin was found."
|
||||
@@ -295,6 +289,12 @@ if [ "$MULTUS_CONF_FILE" == "auto" ]; then
|
||||
ADDITIONAL_BIN_DIR_STRING="\"binDir\": \"$ADDITIONAL_BIN_DIR\","
|
||||
fi
|
||||
|
||||
|
||||
READINESS_INDICATOR_FILE_STRING=""
|
||||
if [ ! -z "${MULTUS_READINESS_INDICATOR_FILE// }" ]; then
|
||||
READINESS_INDICATOR_FILE_STRING="\"readinessindicatorfile\": \"$MULTUS_READINESS_INDICATOR_FILE\","
|
||||
fi
|
||||
|
||||
if [ "$OVERRIDE_NETWORK_NAME" == "true" ]; then
|
||||
MASTER_PLUGIN_NET_NAME="$(cat $MULTUS_AUTOCONF_DIR/$MASTER_PLUGIN | \
|
||||
python -c 'import json,sys;print json.load(sys.stdin)["name"]')"
|
||||
@@ -314,6 +314,7 @@ if [ "$MULTUS_CONF_FILE" == "auto" ]; then
|
||||
$LOG_LEVEL_STRING
|
||||
$LOG_FILE_STRING
|
||||
$ADDITIONAL_BIN_DIR_STRING
|
||||
$READINESS_INDICATOR_FILE_STRING
|
||||
"kubeconfig": "$MULTUS_KUBECONFIG_FILE_HOST",
|
||||
"delegates": [
|
||||
$MASTER_PLUGIN_JSON
|
||||
@@ -353,8 +354,17 @@ if [ "$MULTUS_CLEANUP_CONFIG_ON_EXIT" == true ]; then
|
||||
while true; do
|
||||
# Check and see if the original master plugin configuration exists...
|
||||
if [ ! -f "$MASTER_PLUGIN_LOCATION" ]; then
|
||||
log "Master plugin @ $MASTER_PLUGIN_LOCATION has been deleted. Performing cleanup..."
|
||||
cleanup
|
||||
log "Master plugin @ $MASTER_PLUGIN_LOCATION has been deleted. Allowing 45 seconds for its restoration..."
|
||||
sleep 10
|
||||
for i in {1..35}
|
||||
do
|
||||
if [ -f "$MASTER_PLUGIN_LOCATION" ]; then
|
||||
log "Master plugin @ $MASTER_PLUGIN_LOCATION was restored. Regenerating given configuration."
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
generateMultusConf
|
||||
log "Continuing watch loop after configuration regeneration..."
|
||||
fi
|
||||
|
@@ -454,22 +454,22 @@ func GetK8sArgs(args *skel.CmdArgs) (*types.K8sArgs, error) {
|
||||
|
||||
// TryLoadPodDelegates attempts to load Kubernetes-defined delegates and add them to the Multus config.
|
||||
// Returns the number of Kubernetes-defined delegates added or an error.
|
||||
func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient KubeClient) (int, *ClientInfo, error) {
|
||||
func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient KubeClient) (int, *v1.Pod, *ClientInfo, error) {
|
||||
var err error
|
||||
clientInfo := &ClientInfo{}
|
||||
|
||||
logging.Debugf("TryLoadPodDelegates: %v, %v, %v", k8sArgs, conf, kubeClient)
|
||||
kubeClient, err = GetK8sClient(conf.Kubeconfig, kubeClient)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
|
||||
if kubeClient == nil {
|
||||
if len(conf.Delegates) == 0 {
|
||||
// No available kube client and no delegates, we can't do anything
|
||||
return 0, nil, logging.Errorf("TryLoadPodDelegates: must have either Kubernetes config or delegates")
|
||||
return 0, nil, nil, logging.Errorf("TryLoadPodDelegates: must have either Kubernetes config or delegates")
|
||||
}
|
||||
return 0, nil, nil
|
||||
return 0, nil, nil, nil
|
||||
}
|
||||
|
||||
setKubeClientInfo(clientInfo, kubeClient, k8sArgs)
|
||||
@@ -477,12 +477,12 @@ func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
|
||||
pod, err := kubeClient.GetPod(string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
|
||||
if err != nil {
|
||||
logging.Debugf("TryLoadPodDelegates: Err in loading K8s cluster default network from pod annotation: %v, use cached delegates", err)
|
||||
return 0, nil, nil
|
||||
return 0, nil, nil, nil
|
||||
}
|
||||
|
||||
delegate, err := tryLoadK8sPodDefaultNetwork(kubeClient, pod, conf)
|
||||
if err != nil {
|
||||
return 0, nil, logging.Errorf("TryLoadPodDelegates: error in loading K8s cluster default network from pod annotation: %v", err)
|
||||
return 0, nil, nil, logging.Errorf("TryLoadPodDelegates: error in loading K8s cluster default network from pod annotation: %v", err)
|
||||
}
|
||||
if delegate != nil {
|
||||
logging.Debugf("TryLoadPodDelegates: Overwrite the cluster default network with %v from pod annotations", delegate)
|
||||
@@ -496,13 +496,13 @@ func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
|
||||
|
||||
if err != nil {
|
||||
if _, ok := err.(*NoK8sNetworkError); ok {
|
||||
return 0, clientInfo, nil
|
||||
return 0, nil, clientInfo, nil
|
||||
}
|
||||
return 0, nil, logging.Errorf("TryLoadPodDelegates: error in getting k8s network from pod: %v", err)
|
||||
return 0, nil, nil, logging.Errorf("TryLoadPodDelegates: error in getting k8s network from pod: %v", err)
|
||||
}
|
||||
|
||||
if err = conf.AddDelegates(delegates); err != nil {
|
||||
return 0, nil, err
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
|
||||
// Check gatewayRequest is configured in delegates
|
||||
@@ -519,10 +519,10 @@ func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
|
||||
types.CheckGatewayConfig(conf.Delegates)
|
||||
}
|
||||
|
||||
return len(delegates), clientInfo, nil
|
||||
return len(delegates), pod, clientInfo, nil
|
||||
}
|
||||
|
||||
return 0, clientInfo, nil
|
||||
return 0, pod, clientInfo, nil
|
||||
}
|
||||
|
||||
// GetK8sClient gets client info from kubeconfig
|
||||
@@ -603,7 +603,10 @@ func GetNetworkDelegates(k8sclient KubeClient, pod *v1.Pod, networks []*types.Ne
|
||||
// In the case that this is a mismatch when namespaceisolation is enabled, this should be an error.
|
||||
if confnamespaceIsolation {
|
||||
if defaultNamespace != net.Namespace {
|
||||
return nil, logging.Errorf("GetNetworkDelegates: namespace isolation enabled, annotation violates permission, pod is in namespace %v but refers to target namespace %v", defaultNamespace, net.Namespace)
|
||||
// There is an exception however, we always allow a reference to the default namespace.
|
||||
if net.Namespace != "default" {
|
||||
return nil, logging.Errorf("GetNetworkDelegates: namespace isolation enabled, annotation violates permission, pod is in namespace %v but refers to target namespace %v", defaultNamespace, net.Namespace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -580,7 +580,7 @@ var _ = Describe("k8sclient operations", func() {
|
||||
Expect(netConf.Delegates[0].Conf.Name).To(Equal("net2"))
|
||||
Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2"))
|
||||
|
||||
numK8sDelegates, _, err := TryLoadPodDelegates(k8sArgs, netConf, kubeClient)
|
||||
numK8sDelegates, _, _, err := TryLoadPodDelegates(k8sArgs, netConf, kubeClient)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(numK8sDelegates).To(Equal(0))
|
||||
Expect(netConf.Delegates[0].Conf.Name).To(Equal("net1"))
|
||||
@@ -617,7 +617,7 @@ var _ = Describe("k8sclient operations", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
netConf.ConfDir = "badfilepath"
|
||||
_, _, err = TryLoadPodDelegates(k8sArgs, netConf, kubeClient)
|
||||
_, _, _, err = TryLoadPodDelegates(k8sArgs, netConf, kubeClient)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -650,7 +650,7 @@ var _ = Describe("k8sclient operations", func() {
|
||||
k8sArgs, err := GetK8sArgs(args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
numK8sDelegates, _, err := TryLoadPodDelegates(k8sArgs, netConf, kubeClient)
|
||||
numK8sDelegates, _, _, err := TryLoadPodDelegates(k8sArgs, netConf, kubeClient)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(numK8sDelegates).To(Equal(0))
|
||||
Expect(netConf.Delegates[0].Conf.Name).To(Equal("net1"))
|
||||
@@ -685,7 +685,7 @@ var _ = Describe("k8sclient operations", func() {
|
||||
k8sArgs, err := GetK8sArgs(args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
_, _, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -717,12 +717,12 @@ var _ = Describe("k8sclient operations", func() {
|
||||
k8sArgs, err := GetK8sArgs(args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
_, _, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// additionally, we expect the test to fail with no delegates, as at least one is always required.
|
||||
netConf.Delegates = nil
|
||||
_, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
_, _, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -780,7 +780,7 @@ users:
|
||||
k8sArgs, err := GetK8sArgs(args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
_, _, _, err = TryLoadPodDelegates(k8sArgs, netConf, nil)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
|
123
multus/multus.go
123
multus/multus.go
@@ -41,6 +41,7 @@ import (
|
||||
"github.com/intel/multus-cni/netutils"
|
||||
"github.com/intel/multus-cni/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
@@ -48,12 +49,8 @@ var version = "master@git"
|
||||
var commit = "unknown commit"
|
||||
var date = "unknown date"
|
||||
|
||||
var defaultReadinessBackoff = wait.Backoff{
|
||||
Steps: 4,
|
||||
Duration: 250 * time.Millisecond,
|
||||
Factor: 4.0,
|
||||
Jitter: 0.1,
|
||||
}
|
||||
var pollDuration = 1000 * time.Millisecond
|
||||
var pollTimeout = 45 * time.Second
|
||||
|
||||
func printVersionString() string {
|
||||
return fmt.Sprintf("multus-cni version:%s, commit:%s, date:%s",
|
||||
@@ -225,7 +222,7 @@ func conflistDel(rt *libcni.RuntimeConf, rawnetconflist []byte, binDir string, e
|
||||
return err
|
||||
}
|
||||
|
||||
func delegateAdd(exec invoke.Exec, ifName string, delegate *types.DelegateNetConf, rt *libcni.RuntimeConf, binDir string, cniArgs string) (cnitypes.Result, error) {
|
||||
func delegateAdd(exec invoke.Exec, pod *v1.Pod, ifName string, delegate *types.DelegateNetConf, rt *libcni.RuntimeConf, binDir string, cniArgs string) (cnitypes.Result, error) {
|
||||
logging.Debugf("delegateAdd: %v, %s, %v, %v, %s", exec, ifName, delegate, rt, binDir)
|
||||
if os.Setenv("CNI_IFNAME", ifName) != nil {
|
||||
return nil, logging.Errorf("delegateAdd: error setting envionment variable CNI_IFNAME")
|
||||
@@ -290,21 +287,25 @@ func delegateAdd(exec invoke.Exec, ifName string, delegate *types.DelegateNetCon
|
||||
|
||||
if logging.GetLoggingLevel() >= logging.VerboseLevel {
|
||||
data, _ := json.Marshal(result)
|
||||
var confName string
|
||||
var cniConfName string
|
||||
if delegate.ConfListPlugin {
|
||||
confName = delegate.ConfList.Name
|
||||
cniConfName = delegate.ConfList.Name
|
||||
} else {
|
||||
confName = delegate.Conf.Name
|
||||
cniConfName = delegate.Conf.Name
|
||||
}
|
||||
|
||||
logging.Verbosef("Add: %s:%s:%s:%s %s", rt.Args[1][1], rt.Args[2][1], confName, rt.IfName, string(data))
|
||||
podUID := "unknownUID"
|
||||
if pod != nil {
|
||||
podUID = string(pod.ObjectMeta.UID)
|
||||
}
|
||||
logging.Verbosef("Add: %s:%s:%s:%s(%s):%s %s", rt.Args[1][1], rt.Args[2][1], podUID, delegate.Name, cniConfName, rt.IfName, string(data))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func delegateDel(exec invoke.Exec, ifName string, delegateConf *types.DelegateNetConf, rt *libcni.RuntimeConf, binDir string) error {
|
||||
logging.Debugf("delegateDel: %v, %s, %v, %v, %s", exec, ifName, delegateConf, rt, binDir)
|
||||
func delegateDel(exec invoke.Exec, pod *v1.Pod, ifName string, delegateConf *types.DelegateNetConf, rt *libcni.RuntimeConf, binDir string) error {
|
||||
logging.Debugf("delegateDel: %v, %v, %s, %v, %v, %s", exec, pod, ifName, delegateConf, rt, binDir)
|
||||
if os.Setenv("CNI_IFNAME", ifName) != nil {
|
||||
return logging.Errorf("delegateDel: error setting envionment variable CNI_IFNAME")
|
||||
}
|
||||
@@ -316,7 +317,11 @@ func delegateDel(exec invoke.Exec, ifName string, delegateConf *types.DelegateNe
|
||||
} else {
|
||||
confName = delegateConf.Conf.Name
|
||||
}
|
||||
logging.Verbosef("Del: %s:%s:%s:%s %s", rt.Args[1][1], rt.Args[2][1], confName, rt.IfName, string(delegateConf.Bytes))
|
||||
podUID := "unknownUID"
|
||||
if pod != nil {
|
||||
podUID = string(pod.ObjectMeta.UID)
|
||||
}
|
||||
logging.Verbosef("Del: %s:%s:%s:%s:%s %s", rt.Args[1][1], rt.Args[2][1], podUID, confName, rt.IfName, string(delegateConf.Bytes))
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -335,8 +340,8 @@ func delegateDel(exec invoke.Exec, ifName string, delegateConf *types.DelegateNe
|
||||
return err
|
||||
}
|
||||
|
||||
func delPlugins(exec invoke.Exec, argIfname string, delegates []*types.DelegateNetConf, lastIdx int, rt *libcni.RuntimeConf, binDir string) error {
|
||||
logging.Debugf("delPlugins: %v, %s, %v, %d, %v, %s", exec, argIfname, delegates, lastIdx, rt, binDir)
|
||||
func delPlugins(exec invoke.Exec, pod *v1.Pod, argIfname string, delegates []*types.DelegateNetConf, lastIdx int, rt *libcni.RuntimeConf, binDir string) error {
|
||||
logging.Debugf("delPlugins: %v, %v, %s, %v, %d, %v, %s", exec, pod, argIfname, delegates, lastIdx, rt, binDir)
|
||||
if os.Setenv("CNI_COMMAND", "DEL") != nil {
|
||||
return logging.Errorf("delPlugins: error setting envionment variable CNI_COMMAND to a value of DEL")
|
||||
}
|
||||
@@ -346,7 +351,7 @@ func delPlugins(exec invoke.Exec, argIfname string, delegates []*types.DelegateN
|
||||
ifName := getIfname(delegates[idx], argIfname, idx)
|
||||
rt.IfName = ifName
|
||||
// Attempt to delete all but do not error out, instead, collect all errors.
|
||||
if err := delegateDel(exec, ifName, delegates[idx], rt, binDir); err != nil {
|
||||
if err := delegateDel(exec, pod, ifName, delegates[idx], rt, binDir); err != nil {
|
||||
errorstrings = append(errorstrings, err.Error())
|
||||
}
|
||||
}
|
||||
@@ -359,45 +364,53 @@ func delPlugins(exec invoke.Exec, argIfname string, delegates []*types.DelegateN
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdErr(k8sArgs *types.K8sArgs, format string, args ...interface{}) error {
|
||||
prefix := "Multus: "
|
||||
if k8sArgs != nil {
|
||||
prefix += fmt.Sprintf("[%s/%s]: ", k8sArgs.K8S_POD_NAMESPACE, k8sArgs.K8S_POD_NAME)
|
||||
}
|
||||
return logging.Errorf(prefix+format, args...)
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cnitypes.Result, error) {
|
||||
n, err := types.LoadNetConf(args.StdinData)
|
||||
logging.Debugf("cmdAdd: %v, %v, %v", args, exec, kubeClient)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: error loading netconf: %v", err)
|
||||
return nil, cmdErr(nil, "error loading netconf: %v", err)
|
||||
}
|
||||
|
||||
k8sArgs, err := k8s.GetK8sArgs(args)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: error getting k8s args: %v", err)
|
||||
return nil, cmdErr(nil, "error getting k8s args: %v", err)
|
||||
}
|
||||
|
||||
wait.ExponentialBackoff(defaultReadinessBackoff, func() (bool, error) {
|
||||
_, err := os.Stat(n.ReadinessIndicatorFile)
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
if n.ReadinessIndicatorFile != "" {
|
||||
err := wait.PollImmediate(pollDuration, pollTimeout, func() (bool, error) {
|
||||
_, err := os.Stat(n.ReadinessIndicatorFile)
|
||||
return err == nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, cmdErr(k8sArgs, "PollImmediate error waiting for ReadinessIndicatorFile: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if n.ClusterNetwork != "" {
|
||||
err = k8s.GetDefaultNetworks(k8sArgs, n, kubeClient)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: failed to get clusterNetwork/defaultNetworks: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "failed to get clusterNetwork/defaultNetworks: %v", err)
|
||||
}
|
||||
// First delegate is always the master plugin
|
||||
n.Delegates[0].MasterPlugin = true
|
||||
}
|
||||
|
||||
_, kc, err := k8s.TryLoadPodDelegates(k8sArgs, n, kubeClient)
|
||||
_, pod, kc, err := k8s.TryLoadPodDelegates(k8sArgs, n, kubeClient)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: error loading k8s delegates k8s args: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "error loading k8s delegates k8s args: %v", err)
|
||||
}
|
||||
|
||||
// cache the multus config
|
||||
if err := saveDelegates(args.ContainerID, n.CNIDir, n.Delegates); err != nil {
|
||||
return nil, logging.Errorf("Multus: error saving the delegates: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "error saving the delegates: %v", err)
|
||||
}
|
||||
|
||||
var result, tmpResult cnitypes.Result
|
||||
@@ -408,7 +421,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cn
|
||||
|
||||
runtimeConfig := types.MergeCNIRuntimeConfig(n.RuntimeConfig, delegate)
|
||||
rt := types.CreateCNIRuntimeConf(args, k8sArgs, ifName, runtimeConfig)
|
||||
tmpResult, err = delegateAdd(exec, ifName, delegate, rt, n.BinDir, cniArgs)
|
||||
tmpResult, err = delegateAdd(exec, pod, ifName, delegate, rt, n.BinDir, cniArgs)
|
||||
if err != nil {
|
||||
// If the add failed, tear down all networks we already added
|
||||
netName := delegate.Conf.Name
|
||||
@@ -416,8 +429,8 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cn
|
||||
netName = delegate.ConfList.Name
|
||||
}
|
||||
// Ignore errors; DEL must be idempotent anyway
|
||||
_ = delPlugins(exec, args.IfName, n.Delegates, idx, rt, n.BinDir)
|
||||
return nil, logging.Errorf("Multus: error adding pod to network %q: %v", netName, err)
|
||||
_ = delPlugins(exec, nil, args.IfName, n.Delegates, idx, rt, n.BinDir)
|
||||
return nil, cmdErr(k8sArgs, "error adding container to network %q: %v", netName, err)
|
||||
}
|
||||
|
||||
// Remove gateway from routing table if the gateway is not used
|
||||
@@ -438,7 +451,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cn
|
||||
if deletegateway {
|
||||
tmpResult, err = netutils.DeleteDefaultGW(args, ifName, &tmpResult)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: Err in deleting gateway: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "error deleting default gateway: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +459,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cn
|
||||
if adddefaultgateway {
|
||||
tmpResult, err = netutils.SetDefaultGW(args, ifName, delegate.GatewayRequest, &tmpResult)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: Err in setting default gateway: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "error setting default gateway: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +473,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cn
|
||||
if !types.CheckSystemNamespaces(kc.Podnamespace, n.SystemNamespaces) {
|
||||
delegateNetStatus, err := types.LoadNetworkStatus(tmpResult, delegate.Conf.Name, delegate.MasterPlugin)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: error setting network status: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "error setting network status: %v", err)
|
||||
}
|
||||
|
||||
netStatus = append(netStatus, delegateNetStatus)
|
||||
@@ -473,7 +486,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) (cn
|
||||
if !types.CheckSystemNamespaces(kc.Podnamespace, n.SystemNamespaces) {
|
||||
err = k8s.SetNetworkStatus(kubeClient, k8sArgs, netStatus, n)
|
||||
if err != nil {
|
||||
return nil, logging.Errorf("Multus: error setting the networks status: %v", err)
|
||||
return nil, cmdErr(k8sArgs, "error setting the networks status: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -511,7 +524,7 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) err
|
||||
netnsfound = false
|
||||
logging.Debugf("cmdDel: WARNING netns may not exist, netns: %s, err: %s", args.Netns, err)
|
||||
} else {
|
||||
return logging.Errorf("Multus: failed to open netns %q: %v", netns, err)
|
||||
return cmdErr(nil, "failed to open netns %q: %v", netns, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,7 +534,17 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) err
|
||||
|
||||
k8sArgs, err := k8s.GetK8sArgs(args)
|
||||
if err != nil {
|
||||
return logging.Errorf("Multus: error getting k8s args: %v", err)
|
||||
return cmdErr(nil, "error getting k8s args: %v", err)
|
||||
}
|
||||
|
||||
if in.ReadinessIndicatorFile != "" {
|
||||
err := wait.PollImmediate(pollDuration, pollTimeout, func() (bool, error) {
|
||||
_, err := os.Stat(in.ReadinessIndicatorFile)
|
||||
return err == nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
return cmdErr(k8sArgs, "PollImmediate error waiting for ReadinessIndicatorFile (on del): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Read the cache to get delegates json for the pod
|
||||
@@ -532,29 +555,29 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) err
|
||||
if in.ClusterNetwork != "" {
|
||||
err = k8s.GetDefaultNetworks(k8sArgs, in, kubeClient)
|
||||
if err != nil {
|
||||
return logging.Errorf("Multus: failed to get clusterNetwork/defaultNetworks: %v", err)
|
||||
return cmdErr(k8sArgs, "failed to get clusterNetwork/defaultNetworks: %v", err)
|
||||
}
|
||||
// First delegate is always the master plugin
|
||||
in.Delegates[0].MasterPlugin = true
|
||||
}
|
||||
|
||||
// Get pod annotation and so on
|
||||
_, _, err := k8s.TryLoadPodDelegates(k8sArgs, in, kubeClient)
|
||||
_, _, _, err := k8s.TryLoadPodDelegates(k8sArgs, in, kubeClient)
|
||||
if err != nil {
|
||||
if len(in.Delegates) == 0 {
|
||||
// No delegate available so send error
|
||||
return logging.Errorf("Multus: failed to get delegates: %v", err)
|
||||
return cmdErr(k8sArgs, "failed to get delegates: %v", err)
|
||||
}
|
||||
// Get clusterNetwork before, so continue to delete
|
||||
logging.Errorf("Multus: failed to get delegates: %v, but continue to delete clusterNetwork", err)
|
||||
}
|
||||
} else {
|
||||
return logging.Errorf("Multus: error reading the delegates: %v", err)
|
||||
return cmdErr(k8sArgs, "error reading the delegates: %v", err)
|
||||
}
|
||||
} else {
|
||||
defer os.Remove(path)
|
||||
if err := json.Unmarshal(netconfBytes, &in.Delegates); err != nil {
|
||||
return logging.Errorf("Multus: failed to load netconf: %v", err)
|
||||
return cmdErr(k8sArgs, "failed to load netconf: %v", err)
|
||||
}
|
||||
// check plugins field and enable ConfListPlugin if there is
|
||||
for _, v := range in.Delegates {
|
||||
@@ -589,8 +612,16 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient k8s.KubeClient) err
|
||||
}
|
||||
}
|
||||
|
||||
kubeClient, err = k8s.GetK8sClient(in.Kubeconfig, kubeClient)
|
||||
var pod *v1.Pod
|
||||
if kubeClient != nil {
|
||||
podName := string(k8sArgs.K8S_POD_NAME)
|
||||
podNamespace := string(k8sArgs.K8S_POD_NAMESPACE)
|
||||
pod, _ = kubeClient.GetPod(podNamespace, podName)
|
||||
}
|
||||
|
||||
rt := types.CreateCNIRuntimeConf(args, k8sArgs, "", in.RuntimeConfig)
|
||||
return delPlugins(exec, args.IfName, in.Delegates, len(in.Delegates)-1, rt, in.BinDir)
|
||||
return delPlugins(exec, pod, args.IfName, in.Delegates, len(in.Delegates)-1, rt, in.BinDir)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@@ -1169,7 +1169,7 @@ var _ = Describe("multus operations", func() {
|
||||
_, err = cmdAdd(args, fExec, nil)
|
||||
Expect(fExec.addIndex).To(Equal(2))
|
||||
Expect(fExec.delIndex).To(Equal(2))
|
||||
Expect(err).To(MatchError("Multus: error adding pod to network \"other1\": delegateAdd: error invoking DelegateAdd - \"other-plugin\": error in getting result from AddNetwork: expected plugin failure"))
|
||||
Expect(err).To(MatchError("Multus: [/]: error adding container to network \"other1\": delegateAdd: error invoking DelegateAdd - \"other-plugin\": error in getting result from AddNetwork: expected plugin failure"))
|
||||
|
||||
// Cleanup default network file.
|
||||
if _, errStat := os.Stat(configPath); errStat == nil {
|
||||
@@ -1805,7 +1805,7 @@ var _ = Describe("multus operations", func() {
|
||||
err = cmdDel(args, fExec, fKubeClient)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
||||
Expect(fKubeClient.PodCount).To(Equal(3))
|
||||
Expect(fKubeClient.PodCount).To(Equal(4))
|
||||
Expect(fKubeClient.NetCount).To(Equal(1))
|
||||
})
|
||||
|
||||
@@ -1886,7 +1886,7 @@ var _ = Describe("multus operations", func() {
|
||||
err = cmdDel(args, fExec, fKubeClient)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
||||
Expect(fKubeClient.PodCount).To(Equal(4))
|
||||
Expect(fKubeClient.PodCount).To(Equal(5))
|
||||
Expect(fKubeClient.NetCount).To(Equal(2))
|
||||
})
|
||||
|
||||
|
@@ -149,6 +149,7 @@ func NewFakePod(name string, netAnnotation string, defaultNetAnnotation string)
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: "test",
|
||||
UID: "testUID",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
|
@@ -97,6 +97,9 @@ func LoadDelegateNetConf(bytes []byte, net *NetworkSelectionElement, deviceID st
|
||||
}
|
||||
|
||||
if net != nil {
|
||||
if net.Name != "" {
|
||||
delegateConf.Name = net.Name
|
||||
}
|
||||
if net.InterfaceRequest != "" {
|
||||
delegateConf.IfnameRequest = net.InterfaceRequest
|
||||
}
|
||||
@@ -160,6 +163,7 @@ func CreateCNIRuntimeConf(args *skel.CmdArgs, k8sArgs *K8sArgs, ifName string, r
|
||||
ContainerID: args.ContainerID,
|
||||
NetNS: args.Netns,
|
||||
IfName: ifName,
|
||||
// NOTE: Verbose logging depends on this order, so please keep Args order.
|
||||
Args: [][2]string{
|
||||
{"IgnoreUnknown", string("true")},
|
||||
{"K8S_POD_NAMESPACE", string(k8sArgs.K8S_POD_NAMESPACE)},
|
||||
|
@@ -368,17 +368,17 @@ var _ = Describe("config operations", func() {
|
||||
"args1": "val1"
|
||||
}`
|
||||
type bridgeNetConf struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Args struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Args struct {
|
||||
CNI map[string]string `json:"cni"`
|
||||
} `json:"args"`
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(cniArgs), &args)
|
||||
err := json.Unmarshal([]byte(cniArgs), &args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
net := &NetworkSelectionElement{
|
||||
Name: "test-elem",
|
||||
net := &NetworkSelectionElement{
|
||||
Name: "test-elem",
|
||||
CNIArgs: &args,
|
||||
}
|
||||
delegateNetConf, err := LoadDelegateNetConf([]byte(conf), net, "")
|
||||
@@ -404,17 +404,17 @@ var _ = Describe("config operations", func() {
|
||||
"args1": "val1a"
|
||||
}`
|
||||
type bridgeNetConf struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Args struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Args struct {
|
||||
CNI map[string]string `json:"cni"`
|
||||
} `json:"args"`
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(cniArgs), &args)
|
||||
err := json.Unmarshal([]byte(cniArgs), &args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
net := &NetworkSelectionElement{
|
||||
Name: "test-elem",
|
||||
net := &NetworkSelectionElement{
|
||||
Name: "test-elem",
|
||||
CNIArgs: &args,
|
||||
}
|
||||
delegateNetConf, err := LoadDelegateNetConf([]byte(conf), net, "")
|
||||
@@ -439,20 +439,20 @@ var _ = Describe("config operations", func() {
|
||||
"args1": "val1"
|
||||
}`
|
||||
type bridgeNetConf struct {
|
||||
Type string `json:"type"`
|
||||
Args struct {
|
||||
Type string `json:"type"`
|
||||
Args struct {
|
||||
CNI map[string]string `json:"cni"`
|
||||
} `json:"args"`
|
||||
}
|
||||
type bridgeNetConfList struct {
|
||||
Name string `json:"name"`
|
||||
Name string `json:"name"`
|
||||
Plugins []*bridgeNetConf `json:"plugins"`
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(cniArgs), &args)
|
||||
err := json.Unmarshal([]byte(cniArgs), &args)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
net := &NetworkSelectionElement{
|
||||
Name: "test-elem",
|
||||
net := &NetworkSelectionElement{
|
||||
Name: "test-elem",
|
||||
CNIArgs: &args,
|
||||
}
|
||||
delegateNetConf, err := LoadDelegateNetConf([]byte(conf), net, "")
|
||||
|
@@ -94,6 +94,7 @@ type NetworkStatus struct {
|
||||
type DelegateNetConf struct {
|
||||
Conf types.NetConf
|
||||
ConfList types.NetConfList
|
||||
Name string
|
||||
IfnameRequest string `json:"ifnameRequest,omitempty"`
|
||||
MacRequest string `json:"macRequest,omitempty"`
|
||||
IPRequest []string `json:"ipRequest,omitempty"`
|
||||
|
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
Normal file
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
||||
//This program must be run after mksyscall.go.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
in1, err := ioutil.ReadFile("syscall_darwin.go")
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
||||
}
|
||||
arch := os.Args[1]
|
||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in := string(in1) + string(in2) + string(in3)
|
||||
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
var out bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "// +build go1.12\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
||||
for _, line := range strings.Split(in, "\n") {
|
||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
|
||||
continue
|
||||
}
|
||||
fn := line[5 : len(line)-13]
|
||||
if !trampolines[fn] {
|
||||
trampolines[fn] = true
|
||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
|
||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
||||
}
|
||||
}
|
||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
||||
}
|
||||
}
|
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
Normal file
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_darwin.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named errno.
|
||||
|
||||
A line beginning with //sysnb is like //sys, except that the
|
||||
goroutine will not be suspended during the execution of the system
|
||||
call. This must only be used for system calls which can never
|
||||
block, as otherwise the system call could cause all goroutines to
|
||||
hang.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
plan9 = flag.Bool("plan9", false, "plan9")
|
||||
openbsd = flag.Bool("openbsd", false, "openbsd")
|
||||
netbsd = flag.Bool("netbsd", false, "netbsd")
|
||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly")
|
||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
if goos == "" {
|
||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment")
|
||||
os.Exit(1)
|
||||
}
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
|
||||
// Check that we are using the Docker-based build system if we should
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n")
|
||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
libc := false
|
||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
|
||||
libc = true
|
||||
}
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
text := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5]
|
||||
|
||||
// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
|
||||
if goos == "darwin" && !libc && funct == "ClockGettime" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Go function header.
|
||||
outDecl := ""
|
||||
if len(out) > 0 {
|
||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", "))
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass dummy pointer in that case.
|
||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n)
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name)
|
||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && (*openbsd || *netbsd) {
|
||||
args = append(args, "0")
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int64" && *dragonfly {
|
||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil {
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" {
|
||||
if len(args)%2 == 1 && *arm {
|
||||
// arm abi specifies 64-bit argument uses
|
||||
// (even, odd) pair
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "Syscall"
|
||||
if nonblock != nil {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "RawSyscallNoError"
|
||||
} else {
|
||||
asm = "RawSyscall"
|
||||
}
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "SyscallNoError"
|
||||
}
|
||||
}
|
||||
if len(args) <= 3 {
|
||||
for len(args) < 3 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 6 {
|
||||
asm += "6"
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 9 {
|
||||
asm += "9"
|
||||
for len(args) < 9 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct)
|
||||
}
|
||||
|
||||
// System call number.
|
||||
if sysname == "" {
|
||||
sysname = "SYS_" + funct
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToUpper(sysname)
|
||||
}
|
||||
|
||||
var libcFn string
|
||||
if libc {
|
||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
||||
sysname = strings.ToLower(sysname) // lowercase
|
||||
if sysname == "getdirentries64" {
|
||||
// Special case - libSystem name and
|
||||
// raw syscall name don't match.
|
||||
sysname = "__getdirentries64"
|
||||
}
|
||||
libcFn = sysname
|
||||
sysname = "funcPC(libc_" + sysname + "_trampoline)"
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" && !*plan9 {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else if p.Name == "err" && *plan9 {
|
||||
ret[0] = "r0"
|
||||
ret[2] = "e1"
|
||||
break
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" || *plan9 {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
}
|
||||
text += body
|
||||
|
||||
if *plan9 && ret[2] == "e1" {
|
||||
text += "\tif int32(r0) == -1 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
} else if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = errnoErr(e1)\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n\n"
|
||||
|
||||
if libc && !trampolines[libcFn] {
|
||||
// some system calls share a trampoline, like read and readlen.
|
||||
trampolines[libcFn] = true
|
||||
// Declare assembly trampoline.
|
||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
|
||||
// Assembly trampoline calls the libc_* function, which this magic
|
||||
// redirects to use the function from libSystem.
|
||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn)
|
||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)
|
||||
text += "\n"
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var _ syscall.Errno
|
||||
|
||||
%s
|
||||
`
|
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
Normal file
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
retvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
retvar = p.Name
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// Change p.Types to c
|
||||
var cIn []string
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
cExtern += "#define c_select select\n"
|
||||
}
|
||||
// Imports of system calls from libc
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
|
||||
// So file name.
|
||||
if *aix {
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
strconvfunc := "C.CString"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
|
||||
n++
|
||||
text += fmt.Sprintf("\tvar _p%d int\n", n)
|
||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
n++
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("_p%d", n))
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
|
||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
|
||||
} else if argN == 0 && funct == "fcntl" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := ""
|
||||
if sysname == "exit" {
|
||||
if errvar != "" {
|
||||
call += "er :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
} else if errvar != "" {
|
||||
call += "r0,er :="
|
||||
} else if retvar != "" {
|
||||
call += "r0,_ :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
|
||||
} else {
|
||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
||||
}
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
} else {
|
||||
reg = "r0"
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
|
||||
// verify return
|
||||
if sysname != "exit" && errvar != "" {
|
||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
|
||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
} else {
|
||||
body += "\tif (r0 ==-1 && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
} else if errvar != "" {
|
||||
body += "\tif (er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
text += body
|
||||
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
Normal file
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
Normal file
@@ -0,0 +1,614 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
||||
|
||||
This program will generate three files and handle both gc and gccgo implementation:
|
||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
||||
|
||||
The generated code looks like this
|
||||
|
||||
zsyscall_aix_ppc64.go
|
||||
func asyscall(...) (n int, err error) {
|
||||
// Pointer Creation
|
||||
r1, e1 := callasyscall(...)
|
||||
// Type Conversion
|
||||
// Error Handler
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_gc.go
|
||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
||||
//go:linkname libc_asyscall libc_asyscall
|
||||
var asyscall syscallFunc
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_ggcgo.go
|
||||
|
||||
// int asyscall(...)
|
||||
|
||||
import "C"
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.asyscall(...))
|
||||
e1 = syscall.GetErrno()
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
// GCCGO
|
||||
textgccgo := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n"
|
||||
// GC
|
||||
textgc := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
// COMMON
|
||||
textcommon := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
onlyCommon := false
|
||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
|
||||
// This function call another syscall which is already implemented.
|
||||
// Therefore, the gc and gccgo part must not be generated.
|
||||
onlyCommon = true
|
||||
}
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
|
||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
if !onlyCommon {
|
||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
}
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// GCCGO Prototype return type
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// GCCGO Prototype arguments type
|
||||
var cIn []string
|
||||
for i, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
if (i == 0 || i == 2) && funct == "fcntl" {
|
||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if !onlyCommon {
|
||||
// GCCGO Prototype Generation
|
||||
// Imports of system calls from libc
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
cExtern += "#define c_select select\n"
|
||||
}
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
// GC Library name
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
sysvarname := fmt.Sprintf("libc_%s", sysname)
|
||||
|
||||
if !onlyCommon {
|
||||
// GC Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
|
||||
// GC Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
|
||||
// GC Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
}
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if textcommon != "" {
|
||||
textcommon += "\n"
|
||||
}
|
||||
|
||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments tocall.
|
||||
var argscommon []string // Arguments in the common part
|
||||
var argscall []string // Arguments for call prototype
|
||||
var argsgc []string // Arguments for gc call (with syscall6)
|
||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
|
||||
} else if p.Type == "bool" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
|
||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
|
||||
} else {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
nargs := len(argsgc)
|
||||
|
||||
// COMMON function generation
|
||||
argscommonlist := strings.Join(argscommon, ", ")
|
||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
|
||||
ret := []string{"_", "_"}
|
||||
body := ""
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[1] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = "r0"
|
||||
ret[0] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" {
|
||||
textcommon += fmt.Sprintf("\t%s\n", callcommon)
|
||||
} else {
|
||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
|
||||
}
|
||||
textcommon += body
|
||||
|
||||
if doErrno {
|
||||
textcommon += "\tif e1 != 0 {\n"
|
||||
textcommon += "\t\terr = errnoErr(e1)\n"
|
||||
textcommon += "\t}\n"
|
||||
}
|
||||
textcommon += "\treturn\n"
|
||||
textcommon += "}\n"
|
||||
|
||||
if onlyCommon {
|
||||
continue
|
||||
}
|
||||
|
||||
// CALL Prototype
|
||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
|
||||
|
||||
// GC function generation
|
||||
asm := "syscall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSyscall6"
|
||||
}
|
||||
|
||||
if len(argsgc) <= 6 {
|
||||
for len(argsgc) < 6 {
|
||||
argsgc = append(argsgc, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
argsgclist := strings.Join(argsgc, ", ")
|
||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
|
||||
|
||||
textgc += callProto
|
||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
|
||||
textgc += "\treturn\n}\n"
|
||||
|
||||
// GCCGO function generation
|
||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
||||
var callgccgo string
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
|
||||
} else {
|
||||
callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
||||
}
|
||||
textgccgo += callProto
|
||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
||||
textgccgo += "\treturn\n}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64.go
|
||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gc.go
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gccgo.go
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const srcTemplate1 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate2 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build !gccgo
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
type syscallFunc uintptr
|
||||
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
// Implemented in runtime/syscall_aix.go.
|
||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate3 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build gccgo
|
||||
|
||||
package %s
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
Normal file
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_solaris.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// So file name.
|
||||
if modname == "" {
|
||||
modname = "libc"
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
// System call pointer variable name.
|
||||
sysvarname := fmt.Sprintf("proc%s", sysname)
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname)
|
||||
// Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname)
|
||||
// Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
|
||||
// Go function header.
|
||||
outlist := strings.Join(out, ", ")
|
||||
if outlist != "" {
|
||||
outlist = fmt.Sprintf(" (%s)", outlist)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n))
|
||||
n++
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
nargs := len(args)
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "sysvicall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSysvicall6"
|
||||
}
|
||||
if len(args) <= 6 {
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%d != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
text += body
|
||||
|
||||
if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
%s
|
||||
`
|
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
Normal file
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
Normal file
@@ -0,0 +1,355 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
||||
//
|
||||
// Build a MIB with each entry being an array containing the level, type and
|
||||
// a hash that will contain additional entries if the current entry is a node.
|
||||
// We then walk this MIB and create a flattened sysctl name to OID hash.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments.
|
||||
func cmdLine() string {
|
||||
return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags.
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
// reMatch performs regular expression match and stores the substring slice to value pointed by m.
|
||||
func reMatch(re *regexp.Regexp, str string, m *[]string) bool {
|
||||
*m = re.FindStringSubmatch(str)
|
||||
if *m != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type nodeElement struct {
|
||||
n int
|
||||
t string
|
||||
pE *map[string]nodeElement
|
||||
}
|
||||
|
||||
var (
|
||||
debugEnabled bool
|
||||
mib map[string]nodeElement
|
||||
node *map[string]nodeElement
|
||||
nodeMap map[string]string
|
||||
sysCtl []string
|
||||
)
|
||||
|
||||
var (
|
||||
ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`)
|
||||
ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`)
|
||||
ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`)
|
||||
netInetRE = regexp.MustCompile(`^netinet/`)
|
||||
netInet6RE = regexp.MustCompile(`^netinet6/`)
|
||||
netRE = regexp.MustCompile(`^net/`)
|
||||
bracesRE = regexp.MustCompile(`{.*}`)
|
||||
ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`)
|
||||
fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`)
|
||||
)
|
||||
|
||||
func debug(s string) {
|
||||
if debugEnabled {
|
||||
fmt.Fprintln(os.Stderr, s)
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the MIB and build a sysctl name to OID mapping.
|
||||
func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) {
|
||||
lNode := pNode // local copy of pointer to node
|
||||
var keys []string
|
||||
for k := range *lNode {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
nodename := name
|
||||
if name != "" {
|
||||
nodename += "."
|
||||
}
|
||||
nodename += key
|
||||
|
||||
nodeoid := append(oid, (*pNode)[key].n)
|
||||
|
||||
if (*pNode)[key].t == `CTLTYPE_NODE` {
|
||||
if _, ok := nodeMap[nodename]; ok {
|
||||
lNode = &mib
|
||||
ctlName := nodeMap[nodename]
|
||||
for _, part := range strings.Split(ctlName, ".") {
|
||||
lNode = ((*lNode)[part]).pE
|
||||
}
|
||||
} else {
|
||||
lNode = (*pNode)[key].pE
|
||||
}
|
||||
buildSysctl(lNode, nodename, nodeoid)
|
||||
} else if (*pNode)[key].t != "" {
|
||||
oidStr := []string{}
|
||||
for j := range nodeoid {
|
||||
oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j]))
|
||||
}
|
||||
text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n"
|
||||
sysCtl = append(sysCtl, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
mib = make(map[string]nodeElement)
|
||||
headers := [...]string{
|
||||
`sys/sysctl.h`,
|
||||
`sys/socket.h`,
|
||||
`sys/tty.h`,
|
||||
`sys/malloc.h`,
|
||||
`sys/mount.h`,
|
||||
`sys/namei.h`,
|
||||
`sys/sem.h`,
|
||||
`sys/shm.h`,
|
||||
`sys/vmmeter.h`,
|
||||
`uvm/uvmexp.h`,
|
||||
`uvm/uvm_param.h`,
|
||||
`uvm/uvm_swap_encrypt.h`,
|
||||
`ddb/db_var.h`,
|
||||
`net/if.h`,
|
||||
`net/if_pfsync.h`,
|
||||
`net/pipex.h`,
|
||||
`netinet/in.h`,
|
||||
`netinet/icmp_var.h`,
|
||||
`netinet/igmp_var.h`,
|
||||
`netinet/ip_ah.h`,
|
||||
`netinet/ip_carp.h`,
|
||||
`netinet/ip_divert.h`,
|
||||
`netinet/ip_esp.h`,
|
||||
`netinet/ip_ether.h`,
|
||||
`netinet/ip_gre.h`,
|
||||
`netinet/ip_ipcomp.h`,
|
||||
`netinet/ip_ipip.h`,
|
||||
`netinet/pim_var.h`,
|
||||
`netinet/tcp_var.h`,
|
||||
`netinet/udp_var.h`,
|
||||
`netinet6/in6.h`,
|
||||
`netinet6/ip6_divert.h`,
|
||||
`netinet6/pim6_var.h`,
|
||||
`netinet/icmp6.h`,
|
||||
`netmpls/mpls.h`,
|
||||
}
|
||||
|
||||
ctls := [...]string{
|
||||
`kern`,
|
||||
`vm`,
|
||||
`fs`,
|
||||
`net`,
|
||||
//debug /* Special handling required */
|
||||
`hw`,
|
||||
//machdep /* Arch specific */
|
||||
`user`,
|
||||
`ddb`,
|
||||
//vfs /* Special handling required */
|
||||
`fs.posix`,
|
||||
`kern.forkstat`,
|
||||
`kern.intrcnt`,
|
||||
`kern.malloc`,
|
||||
`kern.nchstats`,
|
||||
`kern.seminfo`,
|
||||
`kern.shminfo`,
|
||||
`kern.timecounter`,
|
||||
`kern.tty`,
|
||||
`kern.watchdog`,
|
||||
`net.bpf`,
|
||||
`net.ifq`,
|
||||
`net.inet`,
|
||||
`net.inet.ah`,
|
||||
`net.inet.carp`,
|
||||
`net.inet.divert`,
|
||||
`net.inet.esp`,
|
||||
`net.inet.etherip`,
|
||||
`net.inet.gre`,
|
||||
`net.inet.icmp`,
|
||||
`net.inet.igmp`,
|
||||
`net.inet.ip`,
|
||||
`net.inet.ip.ifq`,
|
||||
`net.inet.ipcomp`,
|
||||
`net.inet.ipip`,
|
||||
`net.inet.mobileip`,
|
||||
`net.inet.pfsync`,
|
||||
`net.inet.pim`,
|
||||
`net.inet.tcp`,
|
||||
`net.inet.udp`,
|
||||
`net.inet6`,
|
||||
`net.inet6.divert`,
|
||||
`net.inet6.ip6`,
|
||||
`net.inet6.icmp6`,
|
||||
`net.inet6.pim6`,
|
||||
`net.inet6.tcp6`,
|
||||
`net.inet6.udp6`,
|
||||
`net.mpls`,
|
||||
`net.mpls.ifq`,
|
||||
`net.key`,
|
||||
`net.pflow`,
|
||||
`net.pfsync`,
|
||||
`net.pipex`,
|
||||
`net.rt`,
|
||||
`vm.swapencrypt`,
|
||||
//vfsgenctl /* Special handling required */
|
||||
}
|
||||
|
||||
// Node name "fixups"
|
||||
ctlMap := map[string]string{
|
||||
"ipproto": "net.inet",
|
||||
"net.inet.ipproto": "net.inet",
|
||||
"net.inet6.ipv6proto": "net.inet6",
|
||||
"net.inet6.ipv6": "net.inet6.ip6",
|
||||
"net.inet.icmpv6": "net.inet6.icmp6",
|
||||
"net.inet6.divert6": "net.inet6.divert",
|
||||
"net.inet6.tcp6": "net.inet.tcp",
|
||||
"net.inet6.udp6": "net.inet.udp",
|
||||
"mpls": "net.mpls",
|
||||
"swpenc": "vm.swapencrypt",
|
||||
}
|
||||
|
||||
// Node mappings
|
||||
nodeMap = map[string]string{
|
||||
"net.inet.ip.ifq": "net.ifq",
|
||||
"net.inet.pfsync": "net.pfsync",
|
||||
"net.mpls.ifq": "net.ifq",
|
||||
}
|
||||
|
||||
mCtls := make(map[string]bool)
|
||||
for _, ctl := range ctls {
|
||||
mCtls[ctl] = true
|
||||
}
|
||||
|
||||
for _, header := range headers {
|
||||
debug("Processing " + header)
|
||||
file, err := os.Open(filepath.Join("/usr/include", header))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
var sub []string
|
||||
if reMatch(ctlNames1RE, s.Text(), &sub) ||
|
||||
reMatch(ctlNames2RE, s.Text(), &sub) ||
|
||||
reMatch(ctlNames3RE, s.Text(), &sub) {
|
||||
if sub[1] == `CTL_NAMES` {
|
||||
// Top level.
|
||||
node = &mib
|
||||
} else {
|
||||
// Node.
|
||||
nodename := strings.ToLower(sub[2])
|
||||
ctlName := ""
|
||||
if reMatch(netInetRE, header, &sub) {
|
||||
ctlName = "net.inet." + nodename
|
||||
} else if reMatch(netInet6RE, header, &sub) {
|
||||
ctlName = "net.inet6." + nodename
|
||||
} else if reMatch(netRE, header, &sub) {
|
||||
ctlName = "net." + nodename
|
||||
} else {
|
||||
ctlName = nodename
|
||||
ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`)
|
||||
}
|
||||
|
||||
if val, ok := ctlMap[ctlName]; ok {
|
||||
ctlName = val
|
||||
}
|
||||
if _, ok := mCtls[ctlName]; !ok {
|
||||
debug("Ignoring " + ctlName + "...")
|
||||
continue
|
||||
}
|
||||
|
||||
// Walk down from the top of the MIB.
|
||||
node = &mib
|
||||
for _, part := range strings.Split(ctlName, ".") {
|
||||
if _, ok := (*node)[part]; !ok {
|
||||
debug("Missing node " + part)
|
||||
(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}}
|
||||
}
|
||||
node = (*node)[part].pE
|
||||
}
|
||||
}
|
||||
|
||||
// Populate current node with entries.
|
||||
i := -1
|
||||
for !strings.HasPrefix(s.Text(), "}") {
|
||||
s.Scan()
|
||||
if reMatch(bracesRE, s.Text(), &sub) {
|
||||
i++
|
||||
}
|
||||
if !reMatch(ctlTypeRE, s.Text(), &sub) {
|
||||
continue
|
||||
}
|
||||
(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = s.Err()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
buildSysctl(&mib, "", []int{})
|
||||
|
||||
sort.Strings(sysCtl)
|
||||
text := strings.Join(sysCtl, "")
|
||||
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
type mibentry struct {
|
||||
ctlname string
|
||||
ctloid []_C_int
|
||||
}
|
||||
|
||||
var sysctlMib = []mibentry {
|
||||
%s
|
||||
}
|
||||
`
|
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
Normal file
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate system call table for DragonFly, NetBSD,
|
||||
// FreeBSD, OpenBSD or Darwin from master list
|
||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
||||
// sys/syscall.h).
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// source string and substring slice for regexp
|
||||
type re struct {
|
||||
str string // source string
|
||||
sub []string // matched sub-string
|
||||
}
|
||||
|
||||
// Match performs regular expression match
|
||||
func (r *re) Match(exp string) bool {
|
||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
||||
if r.sub != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fetchFile fetches a text file from URL
|
||||
func fetchFile(URL string) io.Reader {
|
||||
resp, err := http.Get(URL)
|
||||
checkErr(err)
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
checkErr(err)
|
||||
return strings.NewReader(string(body))
|
||||
}
|
||||
|
||||
// readFile reads a text file from path
|
||||
func readFile(path string) io.Reader {
|
||||
file, err := os.Open(os.Args[1])
|
||||
checkErr(err)
|
||||
return file
|
||||
}
|
||||
|
||||
func format(name, num, proto string) string {
|
||||
name = strings.ToUpper(name)
|
||||
// There are multiple entries for enosys and nosys, so comment them out.
|
||||
nm := re{str: name}
|
||||
if nm.Match(`^SYS_E?NOSYS$`) {
|
||||
name = fmt.Sprintf("// %s", name)
|
||||
}
|
||||
if name == `SYS_SYS_EXIT` {
|
||||
name = `SYS_EXIT`
|
||||
}
|
||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file := strings.TrimSpace(os.Args[1])
|
||||
var syscalls io.Reader
|
||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
|
||||
// Download syscalls.master file
|
||||
syscalls = fetchFile(file)
|
||||
} else {
|
||||
syscalls = readFile(file)
|
||||
}
|
||||
|
||||
var text, line string
|
||||
s := bufio.NewScanner(syscalls)
|
||||
for s.Scan() {
|
||||
t := re{str: line}
|
||||
if t.Match(`^(.*)\\$`) {
|
||||
// Handle continuation
|
||||
line = t.sub[1]
|
||||
line += strings.TrimLeft(s.Text(), " \t")
|
||||
} else {
|
||||
// New line
|
||||
line = s.Text()
|
||||
}
|
||||
t = re{str: line}
|
||||
if t.Match(`\\$`) {
|
||||
continue
|
||||
}
|
||||
t = re{str: line}
|
||||
|
||||
switch goos {
|
||||
case "dragonfly":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "freebsd":
|
||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "openbsd":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
|
||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4]
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "netbsd":
|
||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
|
||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
|
||||
name := t.sub[7] + "_" + t.sub[9]
|
||||
if t.sub[11] != "" {
|
||||
name = t.sub[7] + "_" + t.sub[11]
|
||||
}
|
||||
name = strings.ToUpper(name)
|
||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" {
|
||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
}
|
||||
case "darwin":
|
||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) {
|
||||
name, num := t.sub[1], t.sub[2]
|
||||
name = strings.ToUpper(name)
|
||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
|
||||
os.Exit(1)
|
||||
|
||||
}
|
||||
}
|
||||
err := s.Err()
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const template = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
const(
|
||||
%s)`
|
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
Normal file
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
// +build aix
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See also mkerrors.sh and mkall.sh
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/un.h>
|
||||
#include <utime.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/termio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type off64 C.off64_t
|
||||
type off C.off_t
|
||||
type Mode_t C.mode_t
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Timex C.struct_timex
|
||||
|
||||
type Time_t C.time_t
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
type Timezone C.struct_timezone
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit64
|
||||
|
||||
type Pid_t C.pid_t
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
type dev_t C.dev_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type StatxTimestamp C.struct_statx_timestamp
|
||||
|
||||
type Statx_t C.struct_statx
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
)
|
||||
|
||||
type IfMsgHdr C.struct_if_msghdr
|
||||
|
||||
// Misc
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
//poll
|
||||
|
||||
type PollFd struct {
|
||||
Fd int32
|
||||
Events uint16
|
||||
Revents uint16
|
||||
}
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
//flock_t
|
||||
|
||||
type Flock_t C.struct_flock64
|
||||
|
||||
// Statfs
|
||||
|
||||
type Fsid_t C.struct_fsid_t
|
||||
type Fsid64_t C.struct_fsid64_t
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
const RNDGETENTCNT = 0x80045200
|
64
vendor/golang.org/x/text/internal/language/compact/gen.go
generated
vendored
Normal file
64
vendor/golang.org/x/text/internal/language/compact/gen.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Language tag table generator.
|
||||
// Data read from the web.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/unicode/cldr"
|
||||
)
|
||||
|
||||
var (
|
||||
test = flag.Bool("test",
|
||||
false,
|
||||
"test existing tables; can be used to compare web data with package data.")
|
||||
outputFile = flag.String("output",
|
||||
"tables.go",
|
||||
"output file for generated tables")
|
||||
)
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteGoFile("tables.go", "compact")
|
||||
|
||||
fmt.Fprintln(w, `import "golang.org/x/text/internal/language"`)
|
||||
|
||||
b := newBuilder(w)
|
||||
gen.WriteCLDRVersion(w)
|
||||
|
||||
b.writeCompactIndex()
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
w *gen.CodeWriter
|
||||
data *cldr.CLDR
|
||||
supp *cldr.SupplementalData
|
||||
}
|
||||
|
||||
func newBuilder(w *gen.CodeWriter) *builder {
|
||||
r := gen.OpenCLDRCoreZip()
|
||||
defer r.Close()
|
||||
d := &cldr.Decoder{}
|
||||
data, err := d.DecodeZip(r)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
b := builder{
|
||||
w: w,
|
||||
data: data,
|
||||
supp: data.Supplemental(),
|
||||
}
|
||||
return &b
|
||||
}
|
113
vendor/golang.org/x/text/internal/language/compact/gen_index.go
generated
vendored
Normal file
113
vendor/golang.org/x/text/internal/language/compact/gen_index.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file generates derivative tables based on the language package itself.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/language"
|
||||
)
|
||||
|
||||
// Compact indices:
|
||||
// Note -va-X variants only apply to localization variants.
|
||||
// BCP variants only ever apply to language.
|
||||
// The only ambiguity between tags is with regions.
|
||||
|
||||
func (b *builder) writeCompactIndex() {
|
||||
// Collect all language tags for which we have any data in CLDR.
|
||||
m := map[language.Tag]bool{}
|
||||
for _, lang := range b.data.Locales() {
|
||||
// We include all locales unconditionally to be consistent with en_US.
|
||||
// We want en_US, even though it has no data associated with it.
|
||||
|
||||
// TODO: put any of the languages for which no data exists at the end
|
||||
// of the index. This allows all components based on ICU to use that
|
||||
// as the cutoff point.
|
||||
// if x := data.RawLDML(lang); false ||
|
||||
// x.LocaleDisplayNames != nil ||
|
||||
// x.Characters != nil ||
|
||||
// x.Delimiters != nil ||
|
||||
// x.Measurement != nil ||
|
||||
// x.Dates != nil ||
|
||||
// x.Numbers != nil ||
|
||||
// x.Units != nil ||
|
||||
// x.ListPatterns != nil ||
|
||||
// x.Collations != nil ||
|
||||
// x.Segmentations != nil ||
|
||||
// x.Rbnf != nil ||
|
||||
// x.Annotations != nil ||
|
||||
// x.Metadata != nil {
|
||||
|
||||
// TODO: support POSIX natively, albeit non-standard.
|
||||
tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1))
|
||||
m[tag] = true
|
||||
// }
|
||||
}
|
||||
|
||||
// TODO: plural rules are also defined for the deprecated tags:
|
||||
// iw mo sh tl
|
||||
// Consider removing these as compact tags.
|
||||
|
||||
// Include locales for plural rules, which uses a different structure.
|
||||
for _, plurals := range b.supp.Plurals {
|
||||
for _, rules := range plurals.PluralRules {
|
||||
for _, lang := range strings.Split(rules.Locales, " ") {
|
||||
m[language.Make(lang)] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var coreTags []language.CompactCoreInfo
|
||||
var special []string
|
||||
|
||||
for t := range m {
|
||||
if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" {
|
||||
log.Fatalf("Unexpected extension %v in %v", x, t)
|
||||
}
|
||||
if len(t.Variants()) == 0 && len(t.Extensions()) == 0 {
|
||||
cci, ok := language.GetCompactCore(t)
|
||||
if !ok {
|
||||
log.Fatalf("Locale for non-basic language %q", t)
|
||||
}
|
||||
coreTags = append(coreTags, cci)
|
||||
} else {
|
||||
special = append(special, t.String())
|
||||
}
|
||||
}
|
||||
|
||||
w := b.w
|
||||
|
||||
sort.Slice(coreTags, func(i, j int) bool { return coreTags[i] < coreTags[j] })
|
||||
sort.Strings(special)
|
||||
|
||||
w.WriteComment(`
|
||||
NumCompactTags is the number of common tags. The maximum tag is
|
||||
NumCompactTags-1.`)
|
||||
w.WriteConst("NumCompactTags", len(m))
|
||||
|
||||
fmt.Fprintln(w, "const (")
|
||||
for i, t := range coreTags {
|
||||
fmt.Fprintf(w, "%s ID = %d\n", ident(t.Tag().String()), i)
|
||||
}
|
||||
for i, t := range special {
|
||||
fmt.Fprintf(w, "%s ID = %d\n", ident(t), i+len(coreTags))
|
||||
}
|
||||
fmt.Fprintln(w, ")")
|
||||
|
||||
w.WriteVar("coreTags", coreTags)
|
||||
|
||||
w.WriteConst("specialTagsStr", strings.Join(special, " "))
|
||||
}
|
||||
|
||||
func ident(s string) string {
|
||||
return strings.Replace(s, "-", "", -1) + "Index"
|
||||
}
|
54
vendor/golang.org/x/text/internal/language/compact/gen_parents.go
generated
vendored
Normal file
54
vendor/golang.org/x/text/internal/language/compact/gen_parents.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/language"
|
||||
"golang.org/x/text/internal/language/compact"
|
||||
"golang.org/x/text/unicode/cldr"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gen.OpenCLDRCoreZip()
|
||||
defer r.Close()
|
||||
|
||||
d := &cldr.Decoder{}
|
||||
data, err := d.DecodeZip(r)
|
||||
if err != nil {
|
||||
log.Fatalf("DecodeZip: %v", err)
|
||||
}
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteGoFile("parents.go", "compact")
|
||||
|
||||
// Create parents table.
|
||||
type ID uint16
|
||||
parents := make([]ID, compact.NumCompactTags)
|
||||
for _, loc := range data.Locales() {
|
||||
tag := language.MustParse(loc)
|
||||
index, ok := compact.FromTag(tag)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
parentIndex := compact.ID(0) // und
|
||||
for p := tag.Parent(); p != language.Und; p = p.Parent() {
|
||||
if x, ok := compact.FromTag(p); ok {
|
||||
parentIndex = x
|
||||
break
|
||||
}
|
||||
}
|
||||
parents[index] = ID(parentIndex)
|
||||
}
|
||||
|
||||
w.WriteComment(`
|
||||
parents maps a compact index of a tag to the compact index of the parent of
|
||||
this tag.`)
|
||||
w.WriteVar("parents", parents)
|
||||
}
|
1520
vendor/golang.org/x/text/internal/language/gen.go
generated
vendored
Normal file
1520
vendor/golang.org/x/text/internal/language/gen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
20
vendor/golang.org/x/text/internal/language/gen_common.go
generated
vendored
Normal file
20
vendor/golang.org/x/text/internal/language/gen_common.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file contains code common to the maketables.go and the package code.
|
||||
|
||||
// AliasType is the type of an alias in AliasMap.
|
||||
type AliasType int8
|
||||
|
||||
const (
|
||||
Deprecated AliasType = iota
|
||||
Macro
|
||||
Legacy
|
||||
|
||||
AliasTypeUnknown AliasType = -1
|
||||
)
|
19
webhook/Dockerfile
Normal file
19
webhook/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
FROM golang:1.10 as builder
|
||||
|
||||
RUN go get github.com/Masterminds/glide
|
||||
|
||||
ENV PKG_NAME=github.com/intel/multus-cni/webhook
|
||||
ENV PKG_PATH=$GOPATH/src/$PKG_NAME
|
||||
WORKDIR $PKG_PATH
|
||||
|
||||
COPY *.go glide.yaml $PKG_PATH/
|
||||
RUN glide install -v
|
||||
RUN go build -v -o webhook
|
||||
|
||||
FROM golang:1.10
|
||||
ENV PKG_NAME=github.com/intel/multus-cni/webhook
|
||||
ENV PKG_PATH=$GOPATH/src/$PKG_NAME
|
||||
RUN mkdir /webhook
|
||||
COPY --from=builder $PKG_PATH/webhook /webhook/
|
||||
WORKDIR /webhook
|
||||
CMD ["./webhook"]
|
10
webhook/build
Executable file
10
webhook/build
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
docker build --build-arg http_proxy=${http_proxy} \
|
||||
--build-arg HTTP_PROXY=${HTTP_PROXY} \
|
||||
--build-arg https_proxy=${https_proxy} \
|
||||
--build-arg HTTPS_PROXY=${HTTPS_PROXY} \
|
||||
--build-arg no_proxy=${no_proxy} \
|
||||
--build-arg NO_PROXY=${NO_PROXY} \
|
||||
-t multus-webhook .
|
26
webhook/glide.yaml
Normal file
26
webhook/glide.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
package: github.com/intel/multus-cni/webhook
|
||||
import:
|
||||
- package: github.com/containernetworking/cni
|
||||
version: ~0.7.0-alpha1
|
||||
subpackages:
|
||||
- libcni
|
||||
- package: github.com/intel/multus-cni
|
||||
version: ~3.1.0
|
||||
subpackages:
|
||||
- logging
|
||||
- types
|
||||
- package: k8s.io/api
|
||||
subpackages:
|
||||
- admission/v1beta1
|
||||
- package: k8s.io/apimachinery
|
||||
subpackages:
|
||||
- pkg/apis/meta/v1
|
||||
- pkg/runtime
|
||||
- pkg/runtime/serializer
|
||||
testImport:
|
||||
- package: github.com/onsi/ginkgo
|
||||
version: ~1.6.0
|
||||
subpackages:
|
||||
- extensions/table
|
||||
- package: github.com/onsi/gomega
|
||||
version: ~1.4.1
|
203
webhook/webhook.go
Normal file
203
webhook/webhook.go
Normal file
@@ -0,0 +1,203 @@
|
||||
// Copyright (c) 2018 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/intel/multus-cni/logging"
|
||||
"github.com/intel/multus-cni/types"
|
||||
|
||||
"github.com/containernetworking/cni/libcni"
|
||||
"k8s.io/api/admission/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
func validateNetworkAttachmentDefinition(netAttachDef types.NetworkAttachmentDefinition) (bool, error) {
|
||||
nameRegex := `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
|
||||
isNameCorrect, err := regexp.MatchString(nameRegex, netAttachDef.Metadata.Name)
|
||||
if !isNameCorrect {
|
||||
logging.Errorf("Invalid name.")
|
||||
return false, fmt.Errorf("Invalid name")
|
||||
}
|
||||
if err != nil {
|
||||
logging.Errorf("Error validating name: %s.", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if netAttachDef.Spec.Config == "" {
|
||||
logging.Errorf("Network Config is empty.")
|
||||
return false, fmt.Errorf("Network Config is empty")
|
||||
}
|
||||
|
||||
logging.Printf(logging.DebugLevel, "Validating network config spec: %s", netAttachDef.Spec.Config)
|
||||
|
||||
/* try to unmarshal config into NetworkConfig or NetworkConfigList
|
||||
using actual code from libcni - if succesful, it means that the config
|
||||
will be accepted by CNI itseld as well */
|
||||
confBytes := []byte(netAttachDef.Spec.Config)
|
||||
_, err = libcni.ConfListFromBytes(confBytes)
|
||||
if err != nil {
|
||||
logging.Printf(logging.DebugLevel, "Spec is not a valid network config: %s. Trying to parse into config list", err)
|
||||
_, err = libcni.ConfFromBytes(confBytes)
|
||||
if err != nil {
|
||||
logging.Printf(logging.DebugLevel, "Spec is not a valid network config list: %s", err)
|
||||
logging.Errorf("Invalid config: %s", err)
|
||||
return false, fmt.Errorf("Invalid network config spec")
|
||||
}
|
||||
}
|
||||
|
||||
logging.Printf(logging.DebugLevel, "Network Attachment Defintion is valid. Admission Review request allowed")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func prepareAdmissionReviewResponse(allowed bool, message string, ar *v1beta1.AdmissionReview) error {
|
||||
if ar.Request != nil {
|
||||
ar.Response = &v1beta1.AdmissionResponse{
|
||||
UID: ar.Request.UID,
|
||||
Allowed: allowed,
|
||||
}
|
||||
if message != "" {
|
||||
ar.Response.Result = &metav1.Status{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("AdmissionReview request empty")
|
||||
}
|
||||
}
|
||||
|
||||
func deserializeAdmissionReview(body []byte) (v1beta1.AdmissionReview, error) {
|
||||
ar := v1beta1.AdmissionReview{}
|
||||
runtimeScheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(runtimeScheme)
|
||||
deserializer := codecs.UniversalDeserializer()
|
||||
_, _, err := deserializer.Decode(body, nil, &ar)
|
||||
|
||||
/* Decode() won't return an error if the data wasn't actual AdmissionReview */
|
||||
if err == nil && ar.TypeMeta.Kind != "AdmissionReview" {
|
||||
err = fmt.Errorf("Object is not an AdmissionReview")
|
||||
}
|
||||
|
||||
return ar, err
|
||||
}
|
||||
|
||||
func deserializeNetworkAttachmentDefinition(ar v1beta1.AdmissionReview) (types.NetworkAttachmentDefinition, error) {
|
||||
/* unmarshal NetworkAttachmentDefinition from AdmissionReview request */
|
||||
netAttachDef := types.NetworkAttachmentDefinition{}
|
||||
err := json.Unmarshal(ar.Request.Object.Raw, &netAttachDef)
|
||||
return netAttachDef, err
|
||||
}
|
||||
|
||||
func handleValidationError(w http.ResponseWriter, ar v1beta1.AdmissionReview, orgErr error) {
|
||||
err := prepareAdmissionReviewResponse(false, orgErr.Error(), &ar)
|
||||
if err != nil {
|
||||
logging.Errorf("Error preparing AdmissionResponse: %s", err.Error())
|
||||
http.Error(w, fmt.Sprintf("Error preparing AdmissionResponse: %s", err.Error()), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
writeResponse(w, ar)
|
||||
}
|
||||
|
||||
func writeResponse(w http.ResponseWriter, ar v1beta1.AdmissionReview) {
|
||||
logging.Printf(logging.DebugLevel, "Sending response to the API server")
|
||||
resp, _ := json.Marshal(ar)
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
func validateHandler(w http.ResponseWriter, req *http.Request) {
|
||||
var body []byte
|
||||
|
||||
if req.Body != nil {
|
||||
if data, err := ioutil.ReadAll(req.Body); err == nil {
|
||||
body = data
|
||||
}
|
||||
}
|
||||
|
||||
if len(body) == 0 {
|
||||
logging.Errorf("Error reading HTTP request: empty body")
|
||||
http.Error(w, "Error reading HTTP request: empty body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
/* validate HTTP request headers */
|
||||
contentType := req.Header.Get("Content-Type")
|
||||
if contentType != "application/json" {
|
||||
logging.Errorf("Invalid Content-Type='%s', expected 'application/json'", contentType)
|
||||
http.Error(w, "Invalid Content-Type='%s', expected 'application/json'", http.StatusUnsupportedMediaType)
|
||||
return
|
||||
}
|
||||
|
||||
/* read AdmissionReview from the request body */
|
||||
ar, err := deserializeAdmissionReview(body)
|
||||
if err != nil {
|
||||
logging.Errorf("Error deserializing AdmissionReview: %s", err.Error())
|
||||
http.Error(w, fmt.Sprintf("Error deserializing AdmissionReview: %s", err.Error()), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
netAttachDef, err := deserializeNetworkAttachmentDefinition(ar)
|
||||
if err != nil {
|
||||
handleValidationError(w, ar, err)
|
||||
return
|
||||
}
|
||||
|
||||
/* perform actual object validation */
|
||||
allowed, err := validateNetworkAttachmentDefinition(netAttachDef)
|
||||
if err != nil {
|
||||
handleValidationError(w, ar, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = prepareAdmissionReviewResponse(allowed, "", &ar)
|
||||
if err != nil {
|
||||
logging.Errorf(err.Error())
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
writeResponse(w, ar)
|
||||
}
|
||||
|
||||
func main() {
|
||||
/* load configuration */
|
||||
port := flag.Int("port", 443, "The port on which to serve.")
|
||||
address := flag.String("bind-address", "0.0.0.0", "The IP address on which to listen for the --port port.")
|
||||
cert := flag.String("tls-cert-file", "cert.pem", "File containing the default x509 Certificate for HTTPS.")
|
||||
key := flag.String("tls-private-key-file", "key.pem", "File containing the default x509 private key matching --tls-cert-file.")
|
||||
flag.Parse()
|
||||
|
||||
/* enable logging */
|
||||
logging.SetLogLevel("debug")
|
||||
logging.Printf(logging.DebugLevel, "Starting Multus webhook server")
|
||||
|
||||
/* register handlers */
|
||||
http.HandleFunc("/validate", validateHandler)
|
||||
|
||||
/* start serving */
|
||||
err := http.ListenAndServeTLS(fmt.Sprintf("%s:%d", *address, *port), *cert, *key, nil)
|
||||
if err != nil {
|
||||
logging.Errorf("Error starting web server: %s", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
27
webhook/webhook_suite_test.go
Normal file
27
webhook/webhook_suite_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestWebhook(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Webhook Suite")
|
||||
}
|
187
webhook/webhook_test.go
Normal file
187
webhook/webhook_test.go
Normal file
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2017 Intel Corporation
|
||||
//
|
||||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
||||
"k8s.io/api/admission/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/intel/multus-cni/types"
|
||||
)
|
||||
|
||||
var _ = Describe("Webhook", func() {
|
||||
|
||||
Describe("Preparing Admission Review Response", func() {
|
||||
Context("Admission Review Request is nil", func() {
|
||||
It("should return error", func() {
|
||||
ar := &v1beta1.AdmissionReview{}
|
||||
ar.Request = nil
|
||||
Expect(prepareAdmissionReviewResponse(false, "", ar)).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
Context("Message is not empty", func() {
|
||||
It("should set message in the response", func() {
|
||||
ar := &v1beta1.AdmissionReview{}
|
||||
ar.Request = &v1beta1.AdmissionRequest{
|
||||
UID: "fake-uid",
|
||||
}
|
||||
err := prepareAdmissionReviewResponse(false, "some message", ar)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(ar.Response.Result.Message).To(Equal("some message"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Deserializing Admission Review", func() {
|
||||
Context("It's not an Admission Review", func() {
|
||||
It("should return an error", func() {
|
||||
body := []byte("some-invalid-body")
|
||||
_, err := deserializeAdmissionReview(body)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Deserializing Network Attachment Definition", func() {
|
||||
Context("It's not an Network Attachment Definition", func() {
|
||||
It("should return an error", func() {
|
||||
ar := &v1beta1.AdmissionReview{}
|
||||
ar.Request = &v1beta1.AdmissionRequest{}
|
||||
_, err := deserializeNetworkAttachmentDefinition(*ar)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Handling validation request", func() {
|
||||
Context("Request body is empty", func() {
|
||||
It("should return an error", func() {
|
||||
req := httptest.NewRequest("POST", "https://fakewebhook/validate", nil)
|
||||
w := httptest.NewRecorder()
|
||||
validateHandler(w, req)
|
||||
resp := w.Result()
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusBadRequest))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Content type is not application/json", func() {
|
||||
It("should return an error", func() {
|
||||
req := httptest.NewRequest("POST", "https://fakewebhook/validate", bytes.NewBufferString("fake-body"))
|
||||
req.Header.Set("Content-Type", "invalid-type")
|
||||
w := httptest.NewRecorder()
|
||||
validateHandler(w, req)
|
||||
resp := w.Result()
|
||||
Expect(resp.StatusCode).To(Equal(http.StatusUnsupportedMediaType))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
DescribeTable("Network Attachment Definition validation",
|
||||
func(in types.NetworkAttachmentDefinition, out bool, shouldFail bool) {
|
||||
actualOut, err := validateNetworkAttachmentDefinition(in)
|
||||
Expect(actualOut).To(Equal(out))
|
||||
if shouldFail {
|
||||
Expect(err).To(HaveOccurred())
|
||||
}
|
||||
},
|
||||
Entry(
|
||||
"empty config",
|
||||
types.NetworkAttachmentDefinition{
|
||||
Metadata: metav1.ObjectMeta{
|
||||
Name: "some-valid-name",
|
||||
},
|
||||
},
|
||||
false, true,
|
||||
),
|
||||
Entry(
|
||||
"invalid name",
|
||||
types.NetworkAttachmentDefinition{
|
||||
Metadata: metav1.ObjectMeta{
|
||||
Name: "some_invalid_name",
|
||||
},
|
||||
},
|
||||
false, true,
|
||||
),
|
||||
Entry(
|
||||
"invalid network config",
|
||||
types.NetworkAttachmentDefinition{
|
||||
Metadata: metav1.ObjectMeta{
|
||||
Name: "some-valid-name",
|
||||
},
|
||||
Spec: types.NetworkAttachmentDefinitionSpec{
|
||||
Config: `{"some-invalid": "config"}`,
|
||||
},
|
||||
},
|
||||
false, true,
|
||||
),
|
||||
Entry(
|
||||
"valid network config",
|
||||
types.NetworkAttachmentDefinition{
|
||||
Metadata: metav1.ObjectMeta{
|
||||
Name: "some-valid-name",
|
||||
},
|
||||
Spec: types.NetworkAttachmentDefinitionSpec{
|
||||
Config: `{
|
||||
"cniVersion": "0.3.0",
|
||||
"type": "some-plugin"
|
||||
}`,
|
||||
},
|
||||
},
|
||||
true, false,
|
||||
),
|
||||
Entry(
|
||||
"valid network config list",
|
||||
types.NetworkAttachmentDefinition{
|
||||
Metadata: metav1.ObjectMeta{
|
||||
Name: "some-valid-name",
|
||||
},
|
||||
Spec: types.NetworkAttachmentDefinitionSpec{
|
||||
Config: `{
|
||||
"cniVersion": "0.3.0",
|
||||
"name": "some-bridge-network",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "bridge",
|
||||
"bridge": "br0",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "192.168.1.0/24"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "some-plugin"
|
||||
},
|
||||
{
|
||||
"type": "another-plugin",
|
||||
"sysctl": {
|
||||
"net.ipv4.conf.all.log_martians": "1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
},
|
||||
},
|
||||
true, false,
|
||||
),
|
||||
)
|
||||
})
|
Reference in New Issue
Block a user