ソースを参照

Merge pull request #423 from squat/dependabot/go_modules/github.com/containernetworking/cni-1.3.0

build(deps): bump github.com/containernetworking/cni from 1.0.1 to 1.3.0
Lucas Servén Marín 2 ヶ月 前
コミット
6f2029a4dd

+ 1 - 1
go.mod

@@ -4,7 +4,7 @@ go 1.25.0
 
 require (
 	github.com/awalterschulze/gographviz v0.0.0-20181013152038-b2885df04310
-	github.com/containernetworking/cni v1.0.1
+	github.com/containernetworking/cni v1.3.0
 	github.com/containernetworking/plugins v1.1.1
 	github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1
 	github.com/go-kit/kit v0.9.0

+ 2 - 37
go.sum

@@ -20,8 +20,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
-github.com/containernetworking/cni v1.0.1 h1:9OIL/sZmMYDBe+G8svzILAlulUpaDTUjeAbtH/JNLBo=
-github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
+github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
+github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
 github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNGz0C1d3wVYlHE=
 github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
 github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1 h1:zSiUKnogKeEwIIeUQP/WPH7m0BJ/IvW0VyL4muaauUY=
@@ -36,8 +36,6 @@ github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr
 github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
 github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
 github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
 github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
@@ -69,16 +67,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
 github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -92,7 +83,6 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
 github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -168,20 +158,14 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWu
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
 github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
 github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
-github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
 github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
-github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
 github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -212,7 +196,6 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1 h1:ZFfeKAhIQiiOrQaI3/znw0gOmYpO28Tcu1YaqMa/jtQ=
 github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
@@ -257,7 +240,6 @@ golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e h1:qyrTQ++p1afMkO
 golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
 golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
 golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
-golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -265,7 +247,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -281,14 +262,12 @@ golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
 golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
 golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
 golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
 golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -296,14 +275,9 @@ golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -331,7 +305,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
 golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
 golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
@@ -353,12 +326,6 @@ golang.zx2c4.com/wireguard v0.0.0-20211123210315-387f7c461a16 h1:SCBV/ayxt56AuC0
 golang.zx2c4.com/wireguard v0.0.0-20211123210315-387f7c461a16/go.mod h1:TjUWrnD5ATh7bFvmm/ALEJZQ4ivKbETb6pmyj1vUoNI=
 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20211124212657-dd7407c86d22 h1:TnoJ6AWs/q4xGE9smgTi+bJmEDet3nrBqdHSV0d5/zA=
 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20211124212657-dd7407c86d22/go.mod h1:ELrVb7MHNIb8OV6iZ6TP/ScunqUha+vWsUP+SVBH7lQ=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
 google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -368,7 +335,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
 gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
-gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@@ -377,7 +343,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 259 - 38
vendor/github.com/containernetworking/cni/libcni/api.go

@@ -15,7 +15,7 @@
 package libcni
 
 // Note this is the actual implementation of the CNI specification, which
-// is reflected in the https://github.com/containernetworking/cni/blob/master/SPEC.md file
+// is reflected in the SPEC.md file.
 // it is typically bundled into runtime providers (i.e. containerd or cri-o would use this
 // before calling runc or hcsshim).  It is also bundled into CNI providers as well, for example,
 // to add an IP to a container, to parse the configuration of the CNI and so on.
@@ -23,10 +23,11 @@ package libcni
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
+	"sort"
 	"strings"
 
 	"github.com/containernetworking/cni/pkg/invoke"
@@ -38,6 +39,8 @@ import (
 
 var (
 	CacheDir = "/var/lib/cni"
+	// slightly awkward wording to preserve anyone matching on error strings
+	ErrorCheckNotSupp = fmt.Errorf("does not support the CHECK command")
 )
 
 const (
@@ -64,17 +67,37 @@ type RuntimeConf struct {
 	CacheDir string
 }
 
-type NetworkConfig struct {
-	Network *types.NetConf
+// Use PluginConfig instead of NetworkConfig, the NetworkConfig
+// backwards-compat alias will be removed in a future release.
+type NetworkConfig = PluginConfig
+
+type PluginConfig struct {
+	Network *types.PluginConf
 	Bytes   []byte
 }
 
 type NetworkConfigList struct {
-	Name         string
-	CNIVersion   string
-	DisableCheck bool
-	Plugins      []*NetworkConfig
-	Bytes        []byte
+	Name                   string
+	CNIVersion             string
+	DisableCheck           bool
+	DisableGC              bool
+	LoadOnlyInlinedPlugins bool
+	Plugins                []*PluginConfig
+	Bytes                  []byte
+}
+
+type NetworkAttachment struct {
+	ContainerID    string
+	Network        string
+	IfName         string
+	Config         []byte
+	NetNS          string
+	CniArgs        [][2]string
+	CapabilityArgs map[string]interface{}
+}
+
+type GCArgs struct {
+	ValidAttachments []types.GCAttachment
 }
 
 type CNI interface {
@@ -84,14 +107,21 @@ type CNI interface {
 	GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
 	GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
 
-	AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
-	CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
-	DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
-	GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
-	GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
+	AddNetwork(ctx context.Context, net *PluginConfig, rt *RuntimeConf) (types.Result, error)
+	CheckNetwork(ctx context.Context, net *PluginConfig, rt *RuntimeConf) error
+	DelNetwork(ctx context.Context, net *PluginConfig, rt *RuntimeConf) error
+	GetNetworkCachedResult(net *PluginConfig, rt *RuntimeConf) (types.Result, error)
+	GetNetworkCachedConfig(net *PluginConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
 
 	ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
-	ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
+	ValidateNetwork(ctx context.Context, net *PluginConfig) ([]string, error)
+
+	GCNetworkList(ctx context.Context, net *NetworkConfigList, args *GCArgs) error
+	GetStatusNetworkList(ctx context.Context, net *NetworkConfigList) error
+
+	GetCachedAttachments(containerID string) ([]*NetworkAttachment, error)
+
+	GetVersionInfo(ctx context.Context, pluginType string) (version.PluginInfo, error)
 }
 
 type CNIConfig struct {
@@ -122,7 +152,7 @@ func NewCNIConfigWithCacheDir(path []string, cacheDir string, exec invoke.Exec)
 	}
 }
 
-func buildOneConfig(name, cniVersion string, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) {
+func buildOneConfig(name, cniVersion string, orig *PluginConfig, prevResult types.Result, rt *RuntimeConf) (*PluginConfig, error) {
 	var err error
 
 	inject := map[string]interface{}{
@@ -139,8 +169,11 @@ func buildOneConfig(name, cniVersion string, orig *NetworkConfig, prevResult typ
 	if err != nil {
 		return nil, err
 	}
+	if rt != nil {
+		return injectRuntimeConfig(orig, rt)
+	}
 
-	return injectRuntimeConfig(orig, rt)
+	return orig, nil
 }
 
 // This function takes a libcni RuntimeConf structure and injects values into
@@ -155,7 +188,7 @@ func buildOneConfig(name, cniVersion string, orig *NetworkConfig, prevResult typ
 // capabilities include "portMappings", and the CapabilityArgs map includes a
 // "portMappings" key, that key and its value are added to the "runtimeConfig"
 // dictionary to be passed to the plugin's stdin.
-func injectRuntimeConfig(orig *NetworkConfig, rt *RuntimeConf) (*NetworkConfig, error) {
+func injectRuntimeConfig(orig *PluginConfig, rt *RuntimeConf) (*PluginConfig, error) {
 	var err error
 
 	rc := make(map[string]interface{})
@@ -195,6 +228,7 @@ type cachedInfo struct {
 	Config         []byte                 `json:"config"`
 	IfName         string                 `json:"ifName"`
 	NetworkName    string                 `json:"networkName"`
+	NetNS          string                 `json:"netns,omitempty"`
 	CniArgs        [][2]string            `json:"cniArgs,omitempty"`
 	CapabilityArgs map[string]interface{} `json:"capabilityArgs,omitempty"`
 	RawResult      map[string]interface{} `json:"result,omitempty"`
@@ -229,6 +263,7 @@ func (c *CNIConfig) cacheAdd(result types.Result, config []byte, netName string,
 		Config:         config,
 		IfName:         rt.IfName,
 		NetworkName:    netName,
+		NetNS:          rt.NetNS,
 		CniArgs:        rt.Args,
 		CapabilityArgs: rt.CapabilityArgs,
 	}
@@ -254,11 +289,11 @@ func (c *CNIConfig) cacheAdd(result types.Result, config []byte, netName string,
 	if err != nil {
 		return err
 	}
-	if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil {
+	if err := os.MkdirAll(filepath.Dir(fname), 0o700); err != nil {
 		return err
 	}
 
-	return ioutil.WriteFile(fname, newBytes, 0600)
+	return os.WriteFile(fname, newBytes, 0o600)
 }
 
 func (c *CNIConfig) cacheDel(netName string, rt *RuntimeConf) error {
@@ -277,7 +312,7 @@ func (c *CNIConfig) getCachedConfig(netName string, rt *RuntimeConf) ([]byte, *R
 	if err != nil {
 		return nil, nil, err
 	}
-	bytes, err = ioutil.ReadFile(fname)
+	bytes, err = os.ReadFile(fname)
 	if err != nil {
 		// Ignore read errors; the cached result may not exist on-disk
 		return nil, nil, nil
@@ -305,7 +340,7 @@ func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *Runtim
 	if err != nil {
 		return nil, err
 	}
-	data, err := ioutil.ReadFile(fname)
+	data, err := os.ReadFile(fname)
 	if err != nil {
 		// Ignore read errors; the cached result may not exist on-disk
 		return nil, nil
@@ -333,7 +368,7 @@ func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf)
 	if err != nil {
 		return nil, err
 	}
-	fdata, err := ioutil.ReadFile(fname)
+	fdata, err := os.ReadFile(fname)
 	if err != nil {
 		// Ignore read errors; the cached result may not exist on-disk
 		return nil, nil
@@ -374,7 +409,7 @@ func (c *CNIConfig) GetNetworkListCachedResult(list *NetworkConfigList, rt *Runt
 
 // GetNetworkCachedResult returns the cached Result of the previous
 // AddNetwork() operation for a network, or an error.
-func (c *CNIConfig) GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
+func (c *CNIConfig) GetNetworkCachedResult(net *PluginConfig, rt *RuntimeConf) (types.Result, error) {
 	return c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
 }
 
@@ -386,11 +421,73 @@ func (c *CNIConfig) GetNetworkListCachedConfig(list *NetworkConfigList, rt *Runt
 
 // GetNetworkCachedConfig copies the input RuntimeConf to output
 // RuntimeConf with fields updated with info from the cached Config.
-func (c *CNIConfig) GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) {
+func (c *CNIConfig) GetNetworkCachedConfig(net *PluginConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) {
 	return c.getCachedConfig(net.Network.Name, rt)
 }
 
-func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
+// GetCachedAttachments returns a list of network attachments from the cache.
+// The returned list will be filtered by the containerID if the value is not empty.
+func (c *CNIConfig) GetCachedAttachments(containerID string) ([]*NetworkAttachment, error) {
+	dirPath := filepath.Join(c.getCacheDir(&RuntimeConf{}), "results")
+	entries, err := os.ReadDir(dirPath)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return nil, nil
+		}
+		return nil, err
+	}
+
+	fileNames := make([]string, 0, len(entries))
+	for _, e := range entries {
+		fileNames = append(fileNames, e.Name())
+	}
+	sort.Strings(fileNames)
+
+	attachments := []*NetworkAttachment{}
+	for _, fname := range fileNames {
+		if len(containerID) > 0 {
+			part := fmt.Sprintf("-%s-", containerID)
+			pos := strings.Index(fname, part)
+			if pos <= 0 || pos+len(part) >= len(fname) {
+				continue
+			}
+		}
+
+		cacheFile := filepath.Join(dirPath, fname)
+		bytes, err := os.ReadFile(cacheFile)
+		if err != nil {
+			continue
+		}
+
+		cachedInfo := cachedInfo{}
+
+		if err := json.Unmarshal(bytes, &cachedInfo); err != nil {
+			continue
+		}
+		if cachedInfo.Kind != CNICacheV1 {
+			continue
+		}
+		if len(containerID) > 0 && cachedInfo.ContainerID != containerID {
+			continue
+		}
+		if cachedInfo.IfName == "" || cachedInfo.NetworkName == "" {
+			continue
+		}
+
+		attachments = append(attachments, &NetworkAttachment{
+			ContainerID:    cachedInfo.ContainerID,
+			Network:        cachedInfo.NetworkName,
+			IfName:         cachedInfo.IfName,
+			Config:         cachedInfo.Config,
+			NetNS:          cachedInfo.NetNS,
+			CniArgs:        cachedInfo.CniArgs,
+			CapabilityArgs: cachedInfo.CapabilityArgs,
+		})
+	}
+	return attachments, nil
+}
+
+func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *PluginConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
 	c.ensureExec()
 	pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
 	if err != nil {
@@ -432,7 +529,7 @@ func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList,
 	return result, nil
 }
 
-func (c *CNIConfig) checkNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error {
+func (c *CNIConfig) checkNetwork(ctx context.Context, name, cniVersion string, net *PluginConfig, prevResult types.Result, rt *RuntimeConf) error {
 	c.ensureExec()
 	pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
 	if err != nil {
@@ -453,7 +550,7 @@ func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigLis
 	if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
 		return err
 	} else if !gtet {
-		return fmt.Errorf("configuration version %q does not support the CHECK command", list.CNIVersion)
+		return fmt.Errorf("configuration version %q %w", list.CNIVersion, ErrorCheckNotSupp)
 	}
 
 	if list.DisableCheck {
@@ -474,7 +571,7 @@ func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigLis
 	return nil
 }
 
-func (c *CNIConfig) delNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error {
+func (c *CNIConfig) delNetwork(ctx context.Context, name, cniVersion string, net *PluginConfig, prevResult types.Result, rt *RuntimeConf) error {
 	c.ensureExec()
 	pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
 	if err != nil {
@@ -497,9 +594,9 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
 	if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
 		return err
 	} else if gtet {
-		cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt)
-		if err != nil {
-			return fmt.Errorf("failed to get network %q cached result: %w", list.Name, err)
+		if cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt); err != nil {
+			_ = c.cacheDel(list.Name, rt)
+			cachedResult = nil
 		}
 	}
 
@@ -509,12 +606,13 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
 			return fmt.Errorf("plugin %s failed (delete): %w", pluginDescription(net.Network), err)
 		}
 	}
+
 	_ = c.cacheDel(list.Name, rt)
 
 	return nil
 }
 
-func pluginDescription(net *types.NetConf) string {
+func pluginDescription(net *types.PluginConf) string {
 	if net == nil {
 		return "<missing>"
 	}
@@ -528,7 +626,7 @@ func pluginDescription(net *types.NetConf) string {
 }
 
 // AddNetwork executes the plugin with the ADD command
-func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
+func (c *CNIConfig) AddNetwork(ctx context.Context, net *PluginConfig, rt *RuntimeConf) (types.Result, error) {
 	result, err := c.addNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, nil, rt)
 	if err != nil {
 		return nil, err
@@ -542,12 +640,12 @@ func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
 }
 
 // CheckNetwork executes the plugin with the CHECK command
-func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error {
+func (c *CNIConfig) CheckNetwork(ctx context.Context, net *PluginConfig, rt *RuntimeConf) error {
 	// CHECK was added in CNI spec version 0.4.0 and higher
 	if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
 		return err
 	} else if !gtet {
-		return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion)
+		return fmt.Errorf("configuration version %q %w", net.Network.CNIVersion, ErrorCheckNotSupp)
 	}
 
 	cachedResult, err := c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
@@ -558,7 +656,7 @@ func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *Ru
 }
 
 // DelNetwork executes the plugin with the DEL command
-func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error {
+func (c *CNIConfig) DelNetwork(ctx context.Context, net *PluginConfig, rt *RuntimeConf) error {
 	var cachedResult types.Result
 
 	// Cached result on DEL was added in CNI spec version 0.4.0 and higher
@@ -618,7 +716,7 @@ func (c *CNIConfig) ValidateNetworkList(ctx context.Context, list *NetworkConfig
 // ValidateNetwork checks that a configuration is reasonably valid.
 // It uses the same logic as ValidateNetworkList)
 // Returns a list of capabilities
-func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error) {
+func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *PluginConfig) ([]string, error) {
 	caps := []string{}
 	for c, ok := range net.Network.Capabilities {
 		if ok {
@@ -666,6 +764,129 @@ func (c *CNIConfig) GetVersionInfo(ctx context.Context, pluginType string) (vers
 	return invoke.GetVersionInfo(ctx, pluginPath, c.exec)
 }
 
+// GCNetworkList will do two things
+// - dump the list of cached attachments, and issue deletes as necessary
+// - issue a GC to the underlying plugins (if the version is high enough)
+func (c *CNIConfig) GCNetworkList(ctx context.Context, list *NetworkConfigList, args *GCArgs) error {
+	// If DisableGC is set, then don't bother GCing at all.
+	if list.DisableGC {
+		return nil
+	}
+
+	// First, get the list of cached attachments
+	cachedAttachments, err := c.GetCachedAttachments("")
+	if err != nil {
+		return nil
+	}
+
+	var validAttachments map[types.GCAttachment]interface{}
+	if args != nil {
+		validAttachments = make(map[types.GCAttachment]interface{}, len(args.ValidAttachments))
+		for _, a := range args.ValidAttachments {
+			validAttachments[a] = nil
+		}
+	}
+
+	var errs []error
+
+	for _, cachedAttachment := range cachedAttachments {
+		if cachedAttachment.Network != list.Name {
+			continue
+		}
+		// we found this attachment
+		gca := types.GCAttachment{
+			ContainerID: cachedAttachment.ContainerID,
+			IfName:      cachedAttachment.IfName,
+		}
+		if _, ok := validAttachments[gca]; ok {
+			continue
+		}
+		// otherwise, this attachment wasn't valid and we should issue a CNI DEL
+		rt := RuntimeConf{
+			ContainerID:    cachedAttachment.ContainerID,
+			NetNS:          cachedAttachment.NetNS,
+			IfName:         cachedAttachment.IfName,
+			Args:           cachedAttachment.CniArgs,
+			CapabilityArgs: cachedAttachment.CapabilityArgs,
+		}
+		if err := c.DelNetworkList(ctx, list, &rt); err != nil {
+			errs = append(errs, fmt.Errorf("failed to delete stale attachment %s %s: %w", rt.ContainerID, rt.IfName, err))
+		}
+	}
+
+	// now, if the version supports it, issue a GC
+	if gt, _ := version.GreaterThanOrEqualTo(list.CNIVersion, "1.1.0"); gt {
+		inject := map[string]interface{}{
+			"name":       list.Name,
+			"cniVersion": list.CNIVersion,
+		}
+		if args != nil {
+			inject["cni.dev/valid-attachments"] = args.ValidAttachments
+			// #1101: spec used incorrect variable name
+			inject["cni.dev/attachments"] = args.ValidAttachments
+		}
+
+		for _, plugin := range list.Plugins {
+			// build config here
+			pluginConfig, err := InjectConf(plugin, inject)
+			if err != nil {
+				errs = append(errs, fmt.Errorf("failed to generate configuration to GC plugin %s: %w", plugin.Network.Type, err))
+			}
+			if err := c.gcNetwork(ctx, pluginConfig); err != nil {
+				errs = append(errs, fmt.Errorf("failed to GC plugin %s: %w", plugin.Network.Type, err))
+			}
+		}
+	}
+
+	return errors.Join(errs...)
+}
+
+func (c *CNIConfig) gcNetwork(ctx context.Context, net *PluginConfig) error {
+	c.ensureExec()
+	pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
+	if err != nil {
+		return err
+	}
+	args := c.args("GC", &RuntimeConf{})
+
+	return invoke.ExecPluginWithoutResult(ctx, pluginPath, net.Bytes, args, c.exec)
+}
+
+func (c *CNIConfig) GetStatusNetworkList(ctx context.Context, list *NetworkConfigList) error {
+	// If the version doesn't support status, abort.
+	if gt, _ := version.GreaterThanOrEqualTo(list.CNIVersion, "1.1.0"); !gt {
+		return nil
+	}
+
+	inject := map[string]interface{}{
+		"name":       list.Name,
+		"cniVersion": list.CNIVersion,
+	}
+
+	for _, plugin := range list.Plugins {
+		// build config here
+		pluginConfig, err := InjectConf(plugin, inject)
+		if err != nil {
+			return fmt.Errorf("failed to generate configuration to get plugin STATUS %s: %w", plugin.Network.Type, err)
+		}
+		if err := c.getStatusNetwork(ctx, pluginConfig); err != nil {
+			return err // Don't collect errors here, so we return a clean error code.
+		}
+	}
+	return nil
+}
+
+func (c *CNIConfig) getStatusNetwork(ctx context.Context, net *PluginConfig) error {
+	c.ensureExec()
+	pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
+	if err != nil {
+		return err
+	}
+	args := c.args("STATUS", &RuntimeConf{})
+
+	return invoke.ExecPluginWithoutResult(ctx, pluginPath, net.Bytes, args, c.exec)
+}
+
 // =====
 func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args {
 	return &invoke.Args{

+ 208 - 31
vendor/github.com/containernetworking/cni/libcni/conf.go

@@ -16,11 +16,16 @@ package libcni
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
+	"slices"
 	"sort"
+	"strings"
+
+	"github.com/containernetworking/cni/pkg/types"
+	"github.com/containernetworking/cni/pkg/version"
 )
 
 type NotFoundError struct {
@@ -40,9 +45,16 @@ func (e NoConfigsFoundError) Error() string {
 	return fmt.Sprintf(`no net configurations found in %s`, e.Dir)
 }
 
-func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
-	conf := &NetworkConfig{Bytes: bytes}
-	if err := json.Unmarshal(bytes, &conf.Network); err != nil {
+// This will not validate that the plugins actually belong to the netconfig by ensuring
+// that they are loaded from a directory named after the networkName, relative to the network config.
+//
+// Since here we are just accepting raw bytes, the caller is responsible for ensuring that the plugin
+// config provided here actually "belongs" to the networkconfig in question.
+func NetworkPluginConfFromBytes(pluginConfBytes []byte) (*PluginConfig, error) {
+	// TODO why are we creating a struct that holds both the byte representation and the deserialized
+	// representation, and returning that, instead of just returning the deserialized representation?
+	conf := &PluginConfig{Bytes: pluginConfBytes, Network: &types.PluginConf{}}
+	if err := json.Unmarshal(pluginConfBytes, conf.Network); err != nil {
 		return nil, fmt.Errorf("error parsing configuration: %w", err)
 	}
 	if conf.Network.Type == "" {
@@ -51,17 +63,35 @@ func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
 	return conf, nil
 }
 
-func ConfFromFile(filename string) (*NetworkConfig, error) {
-	bytes, err := ioutil.ReadFile(filename)
+// Given a path to a directory containing a network configuration, and the name of a network,
+// loads all plugin definitions found at path `networkConfPath/networkName/*.conf`
+func NetworkPluginConfsFromFiles(networkConfPath, networkName string) ([]*PluginConfig, error) {
+	var pConfs []*PluginConfig
+
+	pluginConfPath := filepath.Join(networkConfPath, networkName)
+
+	pluginConfFiles, err := ConfFiles(pluginConfPath, []string{".conf"})
 	if err != nil {
-		return nil, fmt.Errorf("error reading %s: %w", filename, err)
+		return nil, fmt.Errorf("failed to read plugin config files in %s: %w", pluginConfPath, err)
 	}
-	return ConfFromBytes(bytes)
+
+	for _, pluginConfFile := range pluginConfFiles {
+		pluginConfBytes, err := os.ReadFile(pluginConfFile)
+		if err != nil {
+			return nil, fmt.Errorf("error reading %s: %w", pluginConfFile, err)
+		}
+		pluginConf, err := NetworkPluginConfFromBytes(pluginConfBytes)
+		if err != nil {
+			return nil, err
+		}
+		pConfs = append(pConfs, pluginConf)
+	}
+	return pConfs, nil
 }
 
-func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
+func NetworkConfFromBytes(confBytes []byte) (*NetworkConfigList, error) {
 	rawList := make(map[string]interface{})
-	if err := json.Unmarshal(bytes, &rawList); err != nil {
+	if err := json.Unmarshal(confBytes, &rawList); err != nil {
 		return nil, fmt.Errorf("error parsing configuration list: %w", err)
 	}
 
@@ -83,26 +113,115 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
 		}
 	}
 
-	disableCheck := false
-	if rawDisableCheck, ok := rawList["disableCheck"]; ok {
-		disableCheck, ok = rawDisableCheck.(bool)
+	rawVersions, ok := rawList["cniVersions"]
+	if ok {
+		// Parse the current package CNI version
+		rvs, ok := rawVersions.([]interface{})
 		if !ok {
-			return nil, fmt.Errorf("error parsing configuration list: invalid disableCheck type %T", rawDisableCheck)
+			return nil, fmt.Errorf("error parsing configuration list: invalid type for cniVersions: %T", rvs)
 		}
+		vs := make([]string, 0, len(rvs))
+		for i, rv := range rvs {
+			v, ok := rv.(string)
+			if !ok {
+				return nil, fmt.Errorf("error parsing configuration list: invalid type for cniVersions index %d: %T", i, rv)
+			}
+			gt, err := version.GreaterThan(v, version.Current())
+			if err != nil {
+				return nil, fmt.Errorf("error parsing configuration list: invalid cniVersions entry %s at index %d: %w", v, i, err)
+			} else if !gt {
+				// Skip versions "greater" than this implementation of the spec
+				vs = append(vs, v)
+			}
+		}
+
+		// if cniVersion was already set, append it to the list for sorting.
+		if cniVersion != "" {
+			gt, err := version.GreaterThan(cniVersion, version.Current())
+			if err != nil {
+				return nil, fmt.Errorf("error parsing configuration list: invalid cniVersion %s: %w", cniVersion, err)
+			} else if !gt {
+				// ignore any versions higher than the current implemented spec version
+				vs = append(vs, cniVersion)
+			}
+		}
+		slices.SortFunc[[]string](vs, func(v1, v2 string) int {
+			if v1 == v2 {
+				return 0
+			}
+			if gt, _ := version.GreaterThan(v1, v2); gt {
+				return 1
+			}
+			return -1
+		})
+		if len(vs) > 0 {
+			cniVersion = vs[len(vs)-1]
+		}
+	}
+
+	readBool := func(key string) (bool, error) {
+		rawVal, ok := rawList[key]
+		if !ok {
+			return false, nil
+		}
+		if b, ok := rawVal.(bool); ok {
+			return b, nil
+		}
+
+		s, ok := rawVal.(string)
+		if !ok {
+			return false, fmt.Errorf("error parsing configuration list: invalid type %T for %s", rawVal, key)
+		}
+		s = strings.ToLower(s)
+		switch s {
+		case "false":
+			return false, nil
+		case "true":
+			return true, nil
+		}
+		return false, fmt.Errorf("error parsing configuration list: invalid value %q for %s", s, key)
+	}
+
+	disableCheck, err := readBool("disableCheck")
+	if err != nil {
+		return nil, err
+	}
+
+	disableGC, err := readBool("disableGC")
+	if err != nil {
+		return nil, err
+	}
+
+	loadOnlyInlinedPlugins, err := readBool("loadOnlyInlinedPlugins")
+	if err != nil {
+		return nil, err
 	}
 
 	list := &NetworkConfigList{
-		Name:         name,
-		DisableCheck: disableCheck,
-		CNIVersion:   cniVersion,
-		Bytes:        bytes,
+		Name:                   name,
+		DisableCheck:           disableCheck,
+		DisableGC:              disableGC,
+		LoadOnlyInlinedPlugins: loadOnlyInlinedPlugins,
+		CNIVersion:             cniVersion,
+		Bytes:                  confBytes,
 	}
 
 	var plugins []interface{}
 	plug, ok := rawList["plugins"]
-	if !ok {
-		return nil, fmt.Errorf("error parsing configuration list: no 'plugins' key")
+	// We can have a `plugins` list key in the main conf,
+	// We can also have `loadOnlyInlinedPlugins == true`
+	//
+	// If `plugins` is there, then `loadOnlyInlinedPlugins` can be true
+	//
+	// If plugins is NOT there, then `loadOnlyInlinedPlugins` cannot be true
+	//
+	// We have to have at least some plugins.
+	if !ok && loadOnlyInlinedPlugins {
+		return nil, fmt.Errorf("error parsing configuration list: `loadOnlyInlinedPlugins` is true, and no 'plugins' key")
+	} else if !ok && !loadOnlyInlinedPlugins {
+		return list, nil
 	}
+
 	plugins, ok = plug.([]interface{})
 	if !ok {
 		return nil, fmt.Errorf("error parsing configuration list: invalid 'plugins' type %T", plug)
@@ -122,24 +241,68 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
 		}
 		list.Plugins = append(list.Plugins, netConf)
 	}
-
 	return list, nil
 }
 
-func ConfListFromFile(filename string) (*NetworkConfigList, error) {
-	bytes, err := ioutil.ReadFile(filename)
+func NetworkConfFromFile(filename string) (*NetworkConfigList, error) {
+	bytes, err := os.ReadFile(filename)
 	if err != nil {
 		return nil, fmt.Errorf("error reading %s: %w", filename, err)
 	}
-	return ConfListFromBytes(bytes)
+
+	conf, err := NetworkConfFromBytes(bytes)
+	if err != nil {
+		return nil, err
+	}
+
+	if !conf.LoadOnlyInlinedPlugins {
+		plugins, err := NetworkPluginConfsFromFiles(filepath.Dir(filename), conf.Name)
+		if err != nil {
+			return nil, err
+		}
+		conf.Plugins = append(conf.Plugins, plugins...)
+	}
+
+	if len(conf.Plugins) == 0 {
+		// Having 0 plugins for a given network is not necessarily a problem,
+		// but return as error for caller to decide, since they tried to load
+		return nil, fmt.Errorf("no plugin configs found")
+	}
+	return conf, nil
+}
+
+// Deprecated: This file format is no longer supported, use NetworkConfXXX and NetworkPluginXXX functions
+func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
+	return NetworkPluginConfFromBytes(bytes)
+}
+
+// Deprecated: This file format is no longer supported, use NetworkConfXXX and NetworkPluginXXX functions
+func ConfFromFile(filename string) (*NetworkConfig, error) {
+	bytes, err := os.ReadFile(filename)
+	if err != nil {
+		return nil, fmt.Errorf("error reading %s: %w", filename, err)
+	}
+	return ConfFromBytes(bytes)
+}
+
+func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
+	return NetworkConfFromBytes(bytes)
+}
+
+func ConfListFromFile(filename string) (*NetworkConfigList, error) {
+	return NetworkConfFromFile(filename)
 }
 
+// ConfFiles simply returns a slice of all files in the provided directory
+// with extensions matching the provided set.
 func ConfFiles(dir string, extensions []string) ([]string, error) {
 	// In part, adapted from rkt/networking/podenv.go#listFiles
-	files, err := ioutil.ReadDir(dir)
+	files, err := os.ReadDir(dir)
 	switch {
 	case err == nil: // break
 	case os.IsNotExist(err):
+		// If folder not there, return no error - only return an
+		// error if we cannot read contents or there are no contents.
 		return nil, nil
 	default:
 		return nil, err
@@ -160,6 +323,7 @@ func ConfFiles(dir string, extensions []string) ([]string, error) {
 	return confFiles, nil
 }
 
+// Deprecated: This file format is no longer supported, use NetworkConfXXX and NetworkPluginXXX functions
 func LoadConf(dir, name string) (*NetworkConfig, error) {
 	files, err := ConfFiles(dir, []string{".conf", ".json"})
 	switch {
@@ -183,6 +347,15 @@ func LoadConf(dir, name string) (*NetworkConfig, error) {
 }
 
 func LoadConfList(dir, name string) (*NetworkConfigList, error) {
+	return LoadNetworkConf(dir, name)
+}
+
+// LoadNetworkConf looks at all the network configs in a given dir,
+// loads and parses them all, and returns the first one with an extension of `.conf`
+// that matches the provided network name predicate.
+func LoadNetworkConf(dir, name string) (*NetworkConfigList, error) {
+	// TODO this .conflist/.conf extension thing is confusing and inexact
+	// for implementors. We should pick one extension for everything and stick with it.
 	files, err := ConfFiles(dir, []string{".conflist"})
 	if err != nil {
 		return nil, err
@@ -190,7 +363,7 @@ func LoadConfList(dir, name string) (*NetworkConfigList, error) {
 	sort.Strings(files)
 
 	for _, confFile := range files {
-		conf, err := ConfListFromFile(confFile)
+		conf, err := NetworkConfFromFile(confFile)
 		if err != nil {
 			return nil, err
 		}
@@ -199,12 +372,13 @@ func LoadConfList(dir, name string) (*NetworkConfigList, error) {
 		}
 	}
 
-	// Try and load a network configuration file (instead of list)
+	// Deprecated: Try and load a network configuration file (instead of list)
 	// from the same name, then upconvert.
 	singleConf, err := LoadConf(dir, name)
 	if err != nil {
 		// A little extra logic so the error makes sense
-		if _, ok := err.(NoConfigsFoundError); len(files) != 0 && ok {
+		var ncfErr NoConfigsFoundError
+		if len(files) != 0 && errors.As(err, &ncfErr) {
 			// Config lists found but no config files found
 			return nil, NotFoundError{dir, name}
 		}
@@ -214,7 +388,8 @@ func LoadConfList(dir, name string) (*NetworkConfigList, error) {
 	return ConfListFromConf(singleConf)
 }
 
-func InjectConf(original *NetworkConfig, newValues map[string]interface{}) (*NetworkConfig, error) {
+// InjectConf takes a PluginConfig and inserts additional values into it, ensuring the result is serializable.
+func InjectConf(original *PluginConfig, newValues map[string]interface{}) (*PluginConfig, error) {
 	config := make(map[string]interface{})
 	err := json.Unmarshal(original.Bytes, &config)
 	if err != nil {
@@ -238,12 +413,14 @@ func InjectConf(original *NetworkConfig, newValues map[string]interface{}) (*Net
 		return nil, err
 	}
 
-	return ConfFromBytes(newBytes)
+	return NetworkPluginConfFromBytes(newBytes)
 }
 
 // ConfListFromConf "upconverts" a network config in to a NetworkConfigList,
 // with the single network as the only entry in the list.
-func ConfListFromConf(original *NetworkConfig) (*NetworkConfigList, error) {
+//
+// Deprecated: Non-conflist file formats are unsupported, use NetworkConfXXX and NetworkPluginXXX functions
+func ConfListFromConf(original *PluginConfig) (*NetworkConfigList, error) {
 	// Re-deserialize the config's json, then make a raw map configlist.
 	// This may seem a bit strange, but it's to make the Bytes fields
 	// actually make sense. Otherwise, the generated json is littered with

+ 17 - 8
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go

@@ -51,25 +51,34 @@ func DelegateAdd(ctx context.Context, delegatePlugin string, netconf []byte, exe
 // DelegateCheck calls the given delegate plugin with the CNI CHECK action and
 // JSON configuration
 func DelegateCheck(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error {
+	return delegateNoResult(ctx, delegatePlugin, netconf, exec, "CHECK")
+}
+
+func delegateNoResult(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec, verb string) error {
 	pluginPath, realExec, err := delegateCommon(delegatePlugin, exec)
 	if err != nil {
 		return err
 	}
 
-	// DelegateCheck will override the original CNI_COMMAND env from process with CHECK
-	return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("CHECK"), realExec)
+	return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs(verb), realExec)
 }
 
 // DelegateDel calls the given delegate plugin with the CNI DEL action and
 // JSON configuration
 func DelegateDel(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error {
-	pluginPath, realExec, err := delegateCommon(delegatePlugin, exec)
-	if err != nil {
-		return err
-	}
+	return delegateNoResult(ctx, delegatePlugin, netconf, exec, "DEL")
+}
 
-	// DelegateDel will override the original CNI_COMMAND env from process with DEL
-	return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("DEL"), realExec)
+// DelegateStatus calls the given delegate plugin with the CNI STATUS action and
+// JSON configuration
+func DelegateStatus(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error {
+	return delegateNoResult(ctx, delegatePlugin, netconf, exec, "STATUS")
+}
+
+// DelegateGC calls the given delegate plugin with the CNI GC action and
+// JSON configuration
+func DelegateGC(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error {
+	return delegateNoResult(ctx, delegatePlugin, netconf, exec, "GC")
 }
 
 // return CNIArgs used by delegation

+ 58 - 9
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go

@@ -16,6 +16,7 @@ package invoke
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 	"os"
 
@@ -33,21 +34,64 @@ type Exec interface {
 	Decode(jsonBytes []byte) (version.PluginInfo, error)
 }
 
+// Plugin must return result in same version as specified in netconf; but
+// for backwards compatibility reasons if the result version is empty use
+// config version (rather than technically correct 0.1.0).
+// https://github.com/containernetworking/cni/issues/895
+func fixupResultVersion(netconf, result []byte) (string, []byte, error) {
+	versionDecoder := &version.ConfigDecoder{}
+	confVersion, err := versionDecoder.Decode(netconf)
+	if err != nil {
+		return "", nil, err
+	}
+
+	var rawResult map[string]interface{}
+	if err := json.Unmarshal(result, &rawResult); err != nil {
+		return "", nil, fmt.Errorf("failed to unmarshal raw result: %w", err)
+	}
+
+	// plugin output of "null" is successfully unmarshalled, but results in a nil
+	// map which causes a panic when the confVersion is assigned below.
+	if rawResult == nil {
+		rawResult = make(map[string]interface{})
+	}
+
+	// Manually decode Result version; we need to know whether its cniVersion
+	// is empty, while built-in decoders (correctly) substitute 0.1.0 for an
+	// empty version per the CNI spec.
+	if resultVerRaw, ok := rawResult["cniVersion"]; ok {
+		resultVer, ok := resultVerRaw.(string)
+		if ok && resultVer != "" {
+			return resultVer, result, nil
+		}
+	}
+
+	// If the cniVersion is not present or empty, assume the result is
+	// the same CNI spec version as the config
+	rawResult["cniVersion"] = confVersion
+	newBytes, err := json.Marshal(rawResult)
+	if err != nil {
+		return "", nil, fmt.Errorf("failed to remarshal fixed result: %w", err)
+	}
+
+	return confVersion, newBytes, nil
+}
+
 // For example, a testcase could pass an instance of the following fakeExec
 // object to ExecPluginWithResult() to verify the incoming stdin and environment
 // and provide a tailored response:
 //
-//import (
+// import (
 //	"encoding/json"
 //	"path"
 //	"strings"
-//)
+// )
 //
-//type fakeExec struct {
+// type fakeExec struct {
 //	version.PluginDecoder
-//}
+// }
 //
-//func (f *fakeExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
+// func (f *fakeExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
 //	net := &types.NetConf{}
 //	err := json.Unmarshal(stdinData, net)
 //	if err != nil {
@@ -65,14 +109,14 @@ type Exec interface {
 //		}
 //	}
 //	return []byte("{\"CNIVersion\":\"0.4.0\"}"), nil
-//}
+// }
 //
-//func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) {
+// func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) {
 //	if len(paths) > 0 {
 //		return path.Join(paths[0], plugin), nil
 //	}
 //	return "", fmt.Errorf("failed to find plugin %s in paths %v", plugin, paths)
-//}
+// }
 
 func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) {
 	if exec == nil {
@@ -84,7 +128,12 @@ func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte
 		return nil, err
 	}
 
-	return create.CreateFromBytes(stdoutBytes)
+	resultVersion, fixedBytes, err := fixupResultVersion(netconf, stdoutBytes)
+	if err != nil {
+		return nil, err
+	}
+
+	return create.Create(resultVersion, fixedBytes)
 }
 
 func ExecPluginWithoutResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) error {

+ 1 - 0
vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go

@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package invoke

+ 51 - 6
vendor/github.com/containernetworking/cni/pkg/types/100/types.go

@@ -26,9 +26,10 @@ import (
 	convert "github.com/containernetworking/cni/pkg/types/internal"
 )
 
-const ImplementedSpecVersion string = "1.0.0"
+// The types did not change between v1.0 and v1.1
+const ImplementedSpecVersion string = "1.1.0"
 
-var supportedVersions = []string{ImplementedSpecVersion}
+var supportedVersions = []string{"1.0.0", "1.1.0"}
 
 // Register converters for all versions less than the implemented spec version
 func init() {
@@ -38,10 +39,14 @@ func init() {
 	convert.RegisterConverter("0.3.0", supportedVersions, convertFrom04x)
 	convert.RegisterConverter("0.3.1", supportedVersions, convertFrom04x)
 	convert.RegisterConverter("0.4.0", supportedVersions, convertFrom04x)
+	convert.RegisterConverter("1.0.0", []string{"1.1.0"}, convertFrom100)
 
 	// Down-converters
 	convert.RegisterConverter("1.0.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
 	convert.RegisterConverter("1.0.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+	convert.RegisterConverter("1.1.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
+	convert.RegisterConverter("1.1.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+	convert.RegisterConverter("1.1.0", []string{"1.0.0"}, convertFrom100)
 
 	// Creator
 	convert.RegisterCreator(supportedVersions, NewResult)
@@ -90,12 +95,49 @@ type Result struct {
 	DNS        types.DNS      `json:"dns,omitempty"`
 }
 
+// Note: DNS should be omit if DNS is empty but default Marshal function
+// will output empty structure hence need to write a Marshal function
+func (r *Result) MarshalJSON() ([]byte, error) {
+	// use type alias to escape recursion for json.Marshal() to MarshalJSON()
+	type fixObjType = Result
+
+	bytes, err := json.Marshal(fixObjType(*r)) //nolint:all
+	if err != nil {
+		return nil, err
+	}
+
+	fixupObj := make(map[string]interface{})
+	if err := json.Unmarshal(bytes, &fixupObj); err != nil {
+		return nil, err
+	}
+
+	if r.DNS.IsEmpty() {
+		delete(fixupObj, "dns")
+	}
+
+	return json.Marshal(fixupObj)
+}
+
+// convertFrom100 does nothing except set the version; the types are the same
+func convertFrom100(from types.Result, toVersion string) (types.Result, error) {
+	fromResult := from.(*Result)
+
+	result := &Result{
+		CNIVersion: toVersion,
+		Interfaces: fromResult.Interfaces,
+		IPs:        fromResult.IPs,
+		Routes:     fromResult.Routes,
+		DNS:        fromResult.DNS,
+	}
+	return result, nil
+}
+
 func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
 	result040, err := convert.Convert(from, "0.4.0")
 	if err != nil {
 		return nil, err
 	}
-	result100, err := convertFrom04x(result040, ImplementedSpecVersion)
+	result100, err := convertFrom04x(result040, toVersion)
 	if err != nil {
 		return nil, err
 	}
@@ -226,9 +268,12 @@ func (r *Result) PrintTo(writer io.Writer) error {
 
 // Interface contains values about the created interfaces
 type Interface struct {
-	Name    string `json:"name"`
-	Mac     string `json:"mac,omitempty"`
-	Sandbox string `json:"sandbox,omitempty"`
+	Name       string `json:"name"`
+	Mac        string `json:"mac,omitempty"`
+	Mtu        int    `json:"mtu,omitempty"`
+	Sandbox    string `json:"sandbox,omitempty"`
+	SocketPath string `json:"socketPath,omitempty"`
+	PciID      string `json:"pciID,omitempty"`
 }
 
 func (i *Interface) String() string {

+ 2 - 2
vendor/github.com/containernetworking/cni/pkg/types/args.go

@@ -26,8 +26,8 @@ import (
 type UnmarshallableBool bool
 
 // UnmarshalText implements the encoding.TextUnmarshaler interface.
-// Returns boolean true if the string is "1" or "[Tt]rue"
-// Returns boolean false if the string is "0" or "[Ff]alse"
+// Returns boolean true if the string is "1" or "true" or "True"
+// Returns boolean false if the string is "0" or "false" or "False”
 func (b *UnmarshallableBool) UnmarshalText(data []byte) error {
 	s := strings.ToLower(string(data))
 	switch s {

+ 3 - 0
vendor/github.com/containernetworking/cni/pkg/types/create/create.go

@@ -19,6 +19,9 @@ import (
 	"fmt"
 
 	"github.com/containernetworking/cni/pkg/types"
+	_ "github.com/containernetworking/cni/pkg/types/020"
+	_ "github.com/containernetworking/cni/pkg/types/040"
+	_ "github.com/containernetworking/cni/pkg/types/100"
 	convert "github.com/containernetworking/cni/pkg/types/internal"
 )
 

+ 117 - 26
vendor/github.com/containernetworking/cni/pkg/types/types.go

@@ -56,31 +56,72 @@ func (n *IPNet) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
-// NetConf describes a network.
-type NetConf struct {
+// Use PluginConf instead of NetConf, the NetConf
+// backwards-compat alias will be removed in a future release.
+type NetConf = PluginConf
+
+// PluginConf describes a plugin configuration for a specific network.
+type PluginConf struct {
 	CNIVersion string `json:"cniVersion,omitempty"`
 
 	Name         string          `json:"name,omitempty"`
 	Type         string          `json:"type,omitempty"`
 	Capabilities map[string]bool `json:"capabilities,omitempty"`
 	IPAM         IPAM            `json:"ipam,omitempty"`
-	DNS          DNS             `json:"dns"`
+	DNS          DNS             `json:"dns,omitempty"`
 
 	RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
 	PrevResult    Result                 `json:"-"`
+
+	// ValidAttachments is only supplied when executing a GC operation
+	ValidAttachments []GCAttachment `json:"cni.dev/valid-attachments,omitempty"`
+}
+
+// GCAttachment is the parameters to a GC call -- namely,
+// the container ID and ifname pair that represents a
+// still-valid attachment.
+type GCAttachment struct {
+	ContainerID string `json:"containerID"`
+	IfName      string `json:"ifname"`
+}
+
+// Note: DNS should be omit if DNS is empty but default Marshal function
+// will output empty structure hence need to write a Marshal function
+func (n *PluginConf) MarshalJSON() ([]byte, error) {
+	bytes, err := json.Marshal(*n)
+	if err != nil {
+		return nil, err
+	}
+
+	fixupObj := make(map[string]interface{})
+	if err := json.Unmarshal(bytes, &fixupObj); err != nil {
+		return nil, err
+	}
+
+	if n.DNS.IsEmpty() {
+		delete(fixupObj, "dns")
+	}
+
+	return json.Marshal(fixupObj)
 }
 
 type IPAM struct {
 	Type string `json:"type,omitempty"`
 }
 
+// IsEmpty returns true if IPAM structure has no value, otherwise return false
+func (i *IPAM) IsEmpty() bool {
+	return i.Type == ""
+}
+
 // NetConfList describes an ordered list of networks.
 type NetConfList struct {
 	CNIVersion string `json:"cniVersion,omitempty"`
 
-	Name         string     `json:"name,omitempty"`
-	DisableCheck bool       `json:"disableCheck,omitempty"`
-	Plugins      []*NetConf `json:"plugins,omitempty"`
+	Name         string        `json:"name,omitempty"`
+	DisableCheck bool          `json:"disableCheck,omitempty"`
+	DisableGC    bool          `json:"disableGC,omitempty"`
+	Plugins      []*PluginConf `json:"plugins,omitempty"`
 }
 
 // Result is an interface that provides the result of plugin execution
@@ -116,31 +157,48 @@ type DNS struct {
 	Options     []string `json:"options,omitempty"`
 }
 
+// IsEmpty returns true if DNS structure has no value, otherwise return false
+func (d *DNS) IsEmpty() bool {
+	if len(d.Nameservers) == 0 && d.Domain == "" && len(d.Search) == 0 && len(d.Options) == 0 {
+		return true
+	}
+	return false
+}
+
 func (d *DNS) Copy() *DNS {
 	if d == nil {
 		return nil
 	}
 
 	to := &DNS{Domain: d.Domain}
-	for _, ns := range d.Nameservers {
-		to.Nameservers = append(to.Nameservers, ns)
-	}
-	for _, s := range d.Search {
-		to.Search = append(to.Search, s)
-	}
-	for _, o := range d.Options {
-		to.Options = append(to.Options, o)
-	}
+	to.Nameservers = append(to.Nameservers, d.Nameservers...)
+	to.Search = append(to.Search, d.Search...)
+	to.Options = append(to.Options, d.Options...)
 	return to
 }
 
 type Route struct {
-	Dst net.IPNet
-	GW  net.IP
+	Dst      net.IPNet
+	GW       net.IP
+	MTU      int
+	AdvMSS   int
+	Priority int
+	Table    *int
+	Scope    *int
 }
 
 func (r *Route) String() string {
-	return fmt.Sprintf("%+v", *r)
+	table := "<nil>"
+	if r.Table != nil {
+		table = fmt.Sprintf("%d", *r.Table)
+	}
+
+	scope := "<nil>"
+	if r.Scope != nil {
+		scope = fmt.Sprintf("%d", *r.Scope)
+	}
+
+	return fmt.Sprintf("{Dst:%+v GW:%v MTU:%d AdvMSS:%d Priority:%d Table:%s Scope:%s}", r.Dst, r.GW, r.MTU, r.AdvMSS, r.Priority, table, scope)
 }
 
 func (r *Route) Copy() *Route {
@@ -148,14 +206,30 @@ func (r *Route) Copy() *Route {
 		return nil
 	}
 
-	return &Route{
-		Dst: r.Dst,
-		GW:  r.GW,
+	route := &Route{
+		Dst:      r.Dst,
+		GW:       r.GW,
+		MTU:      r.MTU,
+		AdvMSS:   r.AdvMSS,
+		Priority: r.Priority,
+		Scope:    r.Scope,
+	}
+
+	if r.Table != nil {
+		table := *r.Table
+		route.Table = &table
 	}
+
+	if r.Scope != nil {
+		scope := *r.Scope
+		route.Scope = &scope
+	}
+
+	return route
 }
 
 // Well known error codes
-// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
+// see https://github.com/containernetworking/cni/blob/main/SPEC.md#well-known-error-codes
 const (
 	ErrUnknown                     uint = iota // 0
 	ErrIncompatibleCNIVersion                  // 1
@@ -165,6 +239,7 @@ const (
 	ErrIOFailure                               // 5
 	ErrDecodingFailure                         // 6
 	ErrInvalidNetworkConfig                    // 7
+	ErrInvalidNetNS                            // 8
 	ErrTryAgainLater               uint = 11
 	ErrInternal                    uint = 999
 )
@@ -200,8 +275,13 @@ func (e *Error) Print() error {
 
 // JSON (un)marshallable types
 type route struct {
-	Dst IPNet  `json:"dst"`
-	GW  net.IP `json:"gw,omitempty"`
+	Dst      IPNet  `json:"dst"`
+	GW       net.IP `json:"gw,omitempty"`
+	MTU      int    `json:"mtu,omitempty"`
+	AdvMSS   int    `json:"advmss,omitempty"`
+	Priority int    `json:"priority,omitempty"`
+	Table    *int   `json:"table,omitempty"`
+	Scope    *int   `json:"scope,omitempty"`
 }
 
 func (r *Route) UnmarshalJSON(data []byte) error {
@@ -212,13 +292,24 @@ func (r *Route) UnmarshalJSON(data []byte) error {
 
 	r.Dst = net.IPNet(rt.Dst)
 	r.GW = rt.GW
+	r.MTU = rt.MTU
+	r.AdvMSS = rt.AdvMSS
+	r.Priority = rt.Priority
+	r.Table = rt.Table
+	r.Scope = rt.Scope
+
 	return nil
 }
 
 func (r Route) MarshalJSON() ([]byte, error) {
 	rt := route{
-		Dst: IPNet(r.Dst),
-		GW:  r.GW,
+		Dst:      IPNet(r.Dst),
+		GW:       r.GW,
+		MTU:      r.MTU,
+		AdvMSS:   r.AdvMSS,
+		Priority: r.Priority,
+		Table:    r.Table,
+		Scope:    r.Scope,
 	}
 
 	return json.Marshal(rt)

+ 2 - 4
vendor/github.com/containernetworking/cni/pkg/utils/utils.go

@@ -36,7 +36,6 @@ var cniReg = regexp.MustCompile(`^` + cniValidNameChars + `*$`)
 
 // ValidateContainerID will validate that the supplied containerID is not empty does not contain invalid characters
 func ValidateContainerID(containerID string) *types.Error {
-
 	if containerID == "" {
 		return types.NewError(types.ErrUnknownContainer, "missing containerID", "")
 	}
@@ -48,7 +47,6 @@ func ValidateContainerID(containerID string) *types.Error {
 
 // ValidateNetworkName will validate that the supplied networkName does not contain invalid characters
 func ValidateNetworkName(networkName string) *types.Error {
-
 	if networkName == "" {
 		return types.NewError(types.ErrInvalidNetworkConfig, "missing network name:", "")
 	}
@@ -58,11 +56,11 @@ func ValidateNetworkName(networkName string) *types.Error {
 	return nil
 }
 
-// ValidateInterfaceName will validate the interface name based on the three rules below
+// ValidateInterfaceName will validate the interface name based on the four rules below
 // 1. The name must not be empty
 // 2. The name must be less than 16 characters
 // 3. The name must not be "." or ".."
-// 3. The name must not contain / or : or any whitespace characters
+// 4. The name must not contain / or : or any whitespace characters
 // ref to https://github.com/torvalds/linux/blob/master/net/core/dev.c#L1024
 func ValidateInterfaceName(ifName string) *types.Error {
 	if len(ifName) == 0 {

+ 26 - 2
vendor/github.com/containernetworking/cni/pkg/version/plugin.go

@@ -86,8 +86,8 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) {
 // minor, and micro numbers or returns an error
 func ParseVersion(version string) (int, int, int, error) {
 	var major, minor, micro int
-	if version == "" {
-		return -1, -1, -1, fmt.Errorf("invalid version %q: the version is empty", version)
+	if version == "" { // special case: no version declared == v0.1.0
+		return 0, 1, 0, nil
 	}
 
 	parts := strings.Split(version, ".")
@@ -142,3 +142,27 @@ func GreaterThanOrEqualTo(version, otherVersion string) (bool, error) {
 	}
 	return false, nil
 }
+
+// GreaterThan returns true if the first version is greater than the second
+func GreaterThan(version, otherVersion string) (bool, error) {
+	firstMajor, firstMinor, firstMicro, err := ParseVersion(version)
+	if err != nil {
+		return false, err
+	}
+
+	secondMajor, secondMinor, secondMicro, err := ParseVersion(otherVersion)
+	if err != nil {
+		return false, err
+	}
+
+	if firstMajor > secondMajor {
+		return true, nil
+	} else if firstMajor == secondMajor {
+		if firstMinor > secondMinor {
+			return true, nil
+		} else if firstMinor == secondMinor && firstMicro > secondMicro {
+			return true, nil
+		}
+	}
+	return false, nil
+}

+ 6 - 5
vendor/github.com/containernetworking/cni/pkg/version/version.go

@@ -19,13 +19,12 @@ import (
 	"fmt"
 
 	"github.com/containernetworking/cni/pkg/types"
-	types100 "github.com/containernetworking/cni/pkg/types/100"
 	"github.com/containernetworking/cni/pkg/types/create"
 )
 
 // Current reports the version of the CNI spec implemented by this library
 func Current() string {
-	return types100.ImplementedSpecVersion
+	return "1.1.0"
 }
 
 // Legacy PluginInfo describes a plugin that is backwards compatible with the
@@ -35,8 +34,10 @@ func Current() string {
 //
 // Any future CNI spec versions which meet this definition should be added to
 // this list.
-var Legacy = PluginSupports("0.1.0", "0.2.0")
-var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0")
+var (
+	Legacy = PluginSupports("0.1.0", "0.2.0")
+	All    = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0", "1.1.0")
+)
 
 // VersionsFrom returns a list of versions starting from min, inclusive
 func VersionsStartingFrom(min string) PluginInfo {
@@ -62,7 +63,7 @@ func NewResult(version string, resultBytes []byte) (types.Result, error) {
 
 // ParsePrevResult parses a prevResult in a NetConf structure and sets
 // the NetConf's PrevResult member to the parsed Result object.
-func ParsePrevResult(conf *types.NetConf) error {
+func ParsePrevResult(conf *types.PluginConf) error {
 	if conf.RawPrevResult == nil {
 		return nil
 	}

+ 2 - 2
vendor/modules.txt

@@ -20,8 +20,8 @@ github.com/campoy/embedmd/embedmd
 # github.com/cespare/xxhash/v2 v2.3.0
 ## explicit; go 1.11
 github.com/cespare/xxhash/v2
-# github.com/containernetworking/cni v1.0.1
-## explicit; go 1.14
+# github.com/containernetworking/cni v1.3.0
+## explicit; go 1.21
 github.com/containernetworking/cni/libcni
 github.com/containernetworking/cni/pkg/invoke
 github.com/containernetworking/cni/pkg/types