Message ID | 20241002-b4-ovpn-v8-3-37ceffcffbde@openvpn.net (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Introducing OpenVPN Data Channel Offload | expand |
Hi Antonio,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 44badc908f2c85711cb18e45e13119c10ad3a05f]
url: https://github.com/intel-lab-lkp/linux/commits/Antonio-Quartulli/netlink-add-NLA_POLICY_MAX_LEN-macro/20241002-172734
base: 44badc908f2c85711cb18e45e13119c10ad3a05f
patch link: https://lore.kernel.org/r/20241002-b4-ovpn-v8-3-37ceffcffbde%40openvpn.net
patch subject: [PATCH net-next v8 03/24] ovpn: add basic netlink support
reproduce: (https://download.01.org/0day-ci/archive/20241002/202410022156.mxbRG3on-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410022156.mxbRG3on-lkp@intel.com/
All warnings (new ones prefixed by >>):
Warning: Documentation/devicetree/bindings/regulator/siliconmitus,sm5703-regulator.yaml references a file that doesn't exist: Documentation/devicetree/bindings/mfd/siliconmitus,sm5703.yaml
Warning: Documentation/hwmon/g762.rst references a file that doesn't exist: Documentation/devicetree/bindings/hwmon/g762.txt
Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/reserved-memory/qcom
>> Warning: MAINTAINERS references a file that doesn't exist: Documentation/netlink/spec/ovpn.yaml
Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
Using alabaster theme
On Wed, 2 Oct 2024 at 10:03, Antonio Quartulli <antonio@openvpn.net> wrote: > > +definitions: > + - > + type: const > + name: nonce-tail-size > + value: 8 > + - > + type: enum > + name: cipher-alg > + value-start: 0 value-start defaults to 0 for enum so this is unnecessary. Same for the following enum definitions. > + entries: [ none, aes-gcm, chacha20-poly1305 ] > + - > + type: enum > + name: del-peer-reason > + value-start: 0 > + entries: [ teardown, userspace, expired, transport-error, transport-disconnect ] > + - > + type: enum > + name: key-slot > + value-start: 0 > + entries: [ primary, secondary ] > + - > + type: enum > + name: mode > + value-start: 0 > + entries: [ p2p, mp ] > + [...] > +operations: > + list: > + - > + name: dev-new > + attribute-set: ovpn > + flags: [ admin-perm ] > + doc: Create a new interface of type ovpn > + do: > + request: > + attributes: > + - ifname > + - mode > + reply: > + attributes: > + - ifname > + - ifindex > + - > + name: dev-del > + attribute-set: ovpn > + flags: [ admin-perm ] > + doc: Delete existing interface of type ovpn > + do: > + pre: ovpn-nl-pre-doit > + post: ovpn-nl-post-doit > + request: > + attributes: > + - ifindex There's no dev-get do/dump op. I think there should be one for diagnostics and metrics. > + - > + name: key-new > + attribute-set: ovpn > + flags: [ admin-perm ] > + doc: Add a cipher key for a specific peer > + do: > + pre: ovpn-nl-pre-doit > + post: ovpn-nl-post-doit > + request: > + attributes: > + - ifindex > + - keyconf > + - > + name: key-swap > + attribute-set: ovpn > + flags: [ admin-perm ] > + doc: Swap primary and secondary session keys for a specific peer > + do: > + pre: ovpn-nl-pre-doit > + post: ovpn-nl-post-doit > + request: > + attributes: > + - ifindex > + - keyconf > + - > + name: key-swap-ntf > + notify: key-new This doesn't work because key-new doesn't have a reply. You should define it with an event: block instead. You can see the build errors here: make -C tools/net/ynl CC ovpn-user.o In file included from ovpn-user.c:8: ovpn-user.h:1194:33: error: field ‘obj’ has incomplete type 1194 | struct ovpn_key_new_rsp obj __attribute__((aligned(8))); | ^~~ ovpn-user.c:835:35: error: ‘ovpn_key_new_rsp_parse’ undeclared here (not in a function); did you mean ‘ovpn_dev_new_rsp_parse’? 835 | .cb = ovpn_key_new_rsp_parse, | ^~~~~~~~~~~~~~~~~~~~~~ | ovpn_dev_new_rsp_parse make[1]: *** [Makefile:41: ovpn-user.o] Error 1 > + doc: | > + Notification about key having exhausted its IV space and requiring > + renegotiation > + mcgrp: peers > + - > + name: key-del > + attribute-set: ovpn > + flags: [ admin-perm ] > + doc: Delete cipher key for a specific peer > + do: > + pre: ovpn-nl-pre-doit > + post: ovpn-nl-post-doit > + request: > + attributes: > + - ifindex > + - keyconf > + > +mcast-groups: > + list: > + - > + name: peers
On 04/10/2024 18:13, Donald Hunter wrote: > On Wed, 2 Oct 2024 at 10:03, Antonio Quartulli <antonio@openvpn.net> wrote: >> >> +definitions: >> + - >> + type: const >> + name: nonce-tail-size >> + value: 8 >> + - >> + type: enum >> + name: cipher-alg >> + value-start: 0 > > value-start defaults to 0 for enum so this is unnecessary. Same for > the following enum definitions. ACK > >> + entries: [ none, aes-gcm, chacha20-poly1305 ] >> + - >> + type: enum >> + name: del-peer-reason >> + value-start: 0 >> + entries: [ teardown, userspace, expired, transport-error, transport-disconnect ] >> + - >> + type: enum >> + name: key-slot >> + value-start: 0 >> + entries: [ primary, secondary ] >> + - >> + type: enum >> + name: mode >> + value-start: 0 >> + entries: [ p2p, mp ] >> + > > [...] > >> +operations: >> + list: >> + - >> + name: dev-new >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Create a new interface of type ovpn >> + do: >> + request: >> + attributes: >> + - ifname >> + - mode >> + reply: >> + attributes: >> + - ifname >> + - ifindex >> + - >> + name: dev-del >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Delete existing interface of type ovpn >> + do: >> + pre: ovpn-nl-pre-doit >> + post: ovpn-nl-post-doit >> + request: >> + attributes: >> + - ifindex > > There's no dev-get do/dump op. I think there should be one for > diagnostics and metrics. I am not sure how much information it can provide (as of now we only have the 'mode' that is being set upon creation). In any case, I am not against implementing the op now and extend it later as we see fit. > >> + - >> + name: key-new >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Add a cipher key for a specific peer >> + do: >> + pre: ovpn-nl-pre-doit >> + post: ovpn-nl-post-doit >> + request: >> + attributes: >> + - ifindex >> + - keyconf >> + - >> + name: key-swap >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Swap primary and secondary session keys for a specific peer >> + do: >> + pre: ovpn-nl-pre-doit >> + post: ovpn-nl-post-doit >> + request: >> + attributes: >> + - ifindex >> + - keyconf >> + - >> + name: key-swap-ntf >> + notify: key-new > > This doesn't work because key-new doesn't have a reply. You should > define it with an event: block instead. You can see the build errors > here: > > make -C tools/net/ynl Oh, I wasn't aware of this subfolder. Thanks for pointing it out! I am thinking that it may make sense to implement a key-get op to extract non-sensible data about the keys (i.e. what cipher was configured). This may be useful for debugging as well. At that point the key-swap-ntf can re-use the key-get as notify. Cheers, > > CC ovpn-user.o > In file included from ovpn-user.c:8: > ovpn-user.h:1194:33: error: field ‘obj’ has incomplete type > 1194 | struct ovpn_key_new_rsp obj __attribute__((aligned(8))); > | ^~~ > ovpn-user.c:835:35: error: ‘ovpn_key_new_rsp_parse’ undeclared here > (not in a function); did you mean ‘ovpn_dev_new_rsp_parse’? > 835 | .cb = ovpn_key_new_rsp_parse, > | ^~~~~~~~~~~~~~~~~~~~~~ > | ovpn_dev_new_rsp_parse > make[1]: *** [Makefile:41: ovpn-user.o] Error 1 > >> + doc: | >> + Notification about key having exhausted its IV space and requiring >> + renegotiation >> + mcgrp: peers >> + - >> + name: key-del >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Delete cipher key for a specific peer >> + do: >> + pre: ovpn-nl-pre-doit >> + post: ovpn-nl-post-doit >> + request: >> + attributes: >> + - ifindex >> + - keyconf >> + >> +mcast-groups: >> + list: >> + - >> + name: peers
Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: [...] >+operations: >+ list: >+ - >+ name: dev-new >+ attribute-set: ovpn >+ flags: [ admin-perm ] >+ doc: Create a new interface of type ovpn >+ do: >+ request: >+ attributes: >+ - ifname >+ - mode >+ reply: >+ attributes: >+ - ifname >+ - ifindex >+ - >+ name: dev-del Why you expose new and del here in ovn specific generic netlink iface? Why can't you use the exising RTNL api which is used for creation and destruction of other types of devices? ip link add [link DEV | parentdev NAME] [ name ] NAME [ txqueuelen PACKETS ] [ address LLADDR ] [ broadcast LLADDR ] [ mtu MTU ] [index IDX ] [ numtxqueues QUEUE_COUNT ] [ numrxqueues QUEUE_COUNT ] [ netns { PID | NETNSNAME | NETNSFILE } ] type TYPE [ ARGS ] ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] Lots of examples of existing types creation is for example here: https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking >+ attribute-set: ovpn >+ flags: [ admin-perm ] >+ doc: Delete existing interface of type ovpn >+ do: >+ pre: ovpn-nl-pre-doit >+ post: ovpn-nl-post-doit >+ request: >+ attributes: >+ - ifindex [...]
Hi, On 07/10/24 17:32, Jiri Pirko wrote: > Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: > > [...] > > >> +operations: >> + list: >> + - >> + name: dev-new >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Create a new interface of type ovpn >> + do: >> + request: >> + attributes: >> + - ifname >> + - mode >> + reply: >> + attributes: >> + - ifname >> + - ifindex >> + - >> + name: dev-del > > Why you expose new and del here in ovn specific generic netlink iface? > Why can't you use the exising RTNL api which is used for creation and > destruction of other types of devices? That was my original approach in v1, but it was argued that an ovpn interface needs a userspace program to be configured and used in a meaningful way, therefore it was decided to concentrate all iface mgmt APIs along with the others in the netlink family and to not expose any RTNL ops. However, recently we decided to add a dellink implementation for better integration with network namespaces and to allow the user to wipe a dangling interface. In the future we are planning to also add the possibility to create a "persistent interface", that is an interface created before launching any userspace program and that survives when the latter is stopped. I can guess this functionality may be better suited for RTNL, but I am not sure yet. @Jiri: do you have any particular opinion why we should use RTNL ops and not netlink for creating/destroying interfaces? I feel this is mostly a matter of taste, but maybe there are technical reasons we should consider. Thanks a lot for your contribution. Regards, > > > ip link add [link DEV | parentdev NAME] [ name ] NAME > [ txqueuelen PACKETS ] > [ address LLADDR ] > [ broadcast LLADDR ] > [ mtu MTU ] [index IDX ] > [ numtxqueues QUEUE_COUNT ] > [ numrxqueues QUEUE_COUNT ] > [ netns { PID | NETNSNAME | NETNSFILE } ] > type TYPE [ ARGS ] > > ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] > > Lots of examples of existing types creation is for example here: > https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking > > > >> + attribute-set: ovpn >> + flags: [ admin-perm ] >> + doc: Delete existing interface of type ovpn >> + do: >> + pre: ovpn-nl-pre-doit >> + post: ovpn-nl-post-doit >> + request: >> + attributes: >> + - ifindex > > [...]
Tue, Oct 08, 2024 at 10:01:40AM CEST, antonio@openvpn.net wrote: >Hi, > >On 07/10/24 17:32, Jiri Pirko wrote: >> Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: >> >> [...] >> >> >> > +operations: >> > + list: >> > + - >> > + name: dev-new >> > + attribute-set: ovpn >> > + flags: [ admin-perm ] >> > + doc: Create a new interface of type ovpn >> > + do: >> > + request: >> > + attributes: >> > + - ifname >> > + - mode >> > + reply: >> > + attributes: >> > + - ifname >> > + - ifindex >> > + - >> > + name: dev-del >> >> Why you expose new and del here in ovn specific generic netlink iface? >> Why can't you use the exising RTNL api which is used for creation and >> destruction of other types of devices? > >That was my original approach in v1, but it was argued that an ovpn interface >needs a userspace program to be configured and used in a meaningful way, >therefore it was decided to concentrate all iface mgmt APIs along with the >others in the netlink family and to not expose any RTNL ops. Can you please point me to the message id? > >However, recently we decided to add a dellink implementation for better >integration with network namespaces and to allow the user to wipe a dangling >interface. Hmm, one more argument to have symmetric add/del impletentation in RTNL > >In the future we are planning to also add the possibility to create a >"persistent interface", that is an interface created before launching any >userspace program and that survives when the latter is stopped. >I can guess this functionality may be better suited for RTNL, but I am not >sure yet. That would be quite confusing to have RTNL and genetlink iface to add/del device. From what you described above, makes more sent to have it just in RTNL > >@Jiri: do you have any particular opinion why we should use RTNL ops and not >netlink for creating/destroying interfaces? I feel this is mostly a matter of >taste, but maybe there are technical reasons we should consider. Well. technically, you can probabaly do both. But it is quite common that you can add/delete these kind of devices over RTNL. Lots of examples. People are used to it, aligns with existing flows. > >Thanks a lot for your contribution. > >Regards, > > >> >> >> ip link add [link DEV | parentdev NAME] [ name ] NAME >> [ txqueuelen PACKETS ] >> [ address LLADDR ] >> [ broadcast LLADDR ] >> [ mtu MTU ] [index IDX ] >> [ numtxqueues QUEUE_COUNT ] >> [ numrxqueues QUEUE_COUNT ] >> [ netns { PID | NETNSNAME | NETNSFILE } ] >> type TYPE [ ARGS ] >> >> ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] >> >> Lots of examples of existing types creation is for example here: >> https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking >> >> >> >> > + attribute-set: ovpn >> > + flags: [ admin-perm ] >> > + doc: Delete existing interface of type ovpn >> > + do: >> > + pre: ovpn-nl-pre-doit >> > + post: ovpn-nl-post-doit >> > + request: >> > + attributes: >> > + - ifindex >> >> [...] > >-- >Antonio Quartulli >OpenVPN Inc.
On 08/10/2024 10:58, Jiri Pirko wrote: > Tue, Oct 08, 2024 at 10:01:40AM CEST, antonio@openvpn.net wrote: >> Hi, >> >> On 07/10/24 17:32, Jiri Pirko wrote: >>> Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: >>> >>> [...] >>> >>> >>>> +operations: >>>> + list: >>>> + - >>>> + name: dev-new >>>> + attribute-set: ovpn >>>> + flags: [ admin-perm ] >>>> + doc: Create a new interface of type ovpn >>>> + do: >>>> + request: >>>> + attributes: >>>> + - ifname >>>> + - mode >>>> + reply: >>>> + attributes: >>>> + - ifname >>>> + - ifindex >>>> + - >>>> + name: dev-del >>> >>> Why you expose new and del here in ovn specific generic netlink iface? >>> Why can't you use the exising RTNL api which is used for creation and >>> destruction of other types of devices? >> >> That was my original approach in v1, but it was argued that an ovpn interface >> needs a userspace program to be configured and used in a meaningful way, >> therefore it was decided to concentrate all iface mgmt APIs along with the >> others in the netlink family and to not expose any RTNL ops. > > Can you please point me to the message id? <CAHNKnsQnHAdxC-XhC9RP-cFp0d-E4YGb+7ie3WymXVL9N-QS6A@mail.gmail.com> from Sergey and subsequent replies. RTNL vs NL topic starts right after the definition of 'ovpn_link_ops' Recently Kuniyuki commented on this topic as well in: <20240919055259.17622-1-kuniyu@amazon.com> and that is why I added a default dellink implemetation. > > >> >> However, recently we decided to add a dellink implementation for better >> integration with network namespaces and to allow the user to wipe a dangling >> interface. > > Hmm, one more argument to have symmetric add/del impletentation in RTNL > > >> >> In the future we are planning to also add the possibility to create a >> "persistent interface", that is an interface created before launching any >> userspace program and that survives when the latter is stopped. >> I can guess this functionality may be better suited for RTNL, but I am not >> sure yet. > > That would be quite confusing to have RTNL and genetlink iface to > add/del device. From what you described above, makes more sent to have > it just in RTNL All in all I tend to agree. > >> >> @Jiri: do you have any particular opinion why we should use RTNL ops and not >> netlink for creating/destroying interfaces? I feel this is mostly a matter of >> taste, but maybe there are technical reasons we should consider. > > Well. technically, you can probabaly do both. But it is quite common > that you can add/delete these kind of devices over RTNL. Lots of > examples. People are used to it, aligns with existing flows. The only counterargument I see is the one brought by Sergey: "the ovpn interface is not usable after creation, if no openvpn process is running". However, allowing to create "persistent interfaces" will define a use-case for having an ovpn device without any userspace process. @Sergey what is your opinion here? I am not sure persistent interfaces were discussed at the time you brought your point about RTNL vs NL. Regards, > >> >> Thanks a lot for your contribution. >> >> Regards, >> >> >>> >>> >>> ip link add [link DEV | parentdev NAME] [ name ] NAME >>> [ txqueuelen PACKETS ] >>> [ address LLADDR ] >>> [ broadcast LLADDR ] >>> [ mtu MTU ] [index IDX ] >>> [ numtxqueues QUEUE_COUNT ] >>> [ numrxqueues QUEUE_COUNT ] >>> [ netns { PID | NETNSNAME | NETNSFILE } ] >>> type TYPE [ ARGS ] >>> >>> ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] >>> >>> Lots of examples of existing types creation is for example here: >>> https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking >>> >>> >>> >>>> + attribute-set: ovpn >>>> + flags: [ admin-perm ] >>>> + doc: Delete existing interface of type ovpn >>>> + do: >>>> + pre: ovpn-nl-pre-doit >>>> + post: ovpn-nl-post-doit >>>> + request: >>>> + attributes: >>>> + - ifindex >>> >>> [...] >> >> -- >> Antonio Quartulli >> OpenVPN Inc.
Tue, Oct 08, 2024 at 11:16:01AM CEST, antonio@openvpn.net wrote: >On 08/10/2024 10:58, Jiri Pirko wrote: >> Tue, Oct 08, 2024 at 10:01:40AM CEST, antonio@openvpn.net wrote: >> > Hi, >> > >> > On 07/10/24 17:32, Jiri Pirko wrote: >> > > Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: >> > > >> > > [...] >> > > >> > > >> > > > +operations: >> > > > + list: >> > > > + - >> > > > + name: dev-new >> > > > + attribute-set: ovpn >> > > > + flags: [ admin-perm ] >> > > > + doc: Create a new interface of type ovpn >> > > > + do: >> > > > + request: >> > > > + attributes: >> > > > + - ifname >> > > > + - mode >> > > > + reply: >> > > > + attributes: >> > > > + - ifname >> > > > + - ifindex >> > > > + - >> > > > + name: dev-del >> > > >> > > Why you expose new and del here in ovn specific generic netlink iface? >> > > Why can't you use the exising RTNL api which is used for creation and >> > > destruction of other types of devices? >> > >> > That was my original approach in v1, but it was argued that an ovpn interface >> > needs a userspace program to be configured and used in a meaningful way, >> > therefore it was decided to concentrate all iface mgmt APIs along with the >> > others in the netlink family and to not expose any RTNL ops. >> >> Can you please point me to the message id? > ><CAHNKnsQnHAdxC-XhC9RP-cFp0d-E4YGb+7ie3WymXVL9N-QS6A@mail.gmail.com> from >Sergey and subsequent replies. >RTNL vs NL topic starts right after the definition of 'ovpn_link_ops' Yeah, does not make sense to me. All devices should implement common rtnl ops, the extra-config, if needed, could be on a separate channel. I don't find Sergey's argumentation valid. > >Recently Kuniyuki commented on this topic as well in: ><20240919055259.17622-1-kuniyu@amazon.com> >and that is why I added a default dellink implemetation. Having dellink without newlink implemented is just wrong. > >> >> >> > >> > However, recently we decided to add a dellink implementation for better >> > integration with network namespaces and to allow the user to wipe a dangling >> > interface. >> >> Hmm, one more argument to have symmetric add/del impletentation in RTNL >> >> >> > >> > In the future we are planning to also add the possibility to create a >> > "persistent interface", that is an interface created before launching any >> > userspace program and that survives when the latter is stopped. >> > I can guess this functionality may be better suited for RTNL, but I am not >> > sure yet. >> >> That would be quite confusing to have RTNL and genetlink iface to >> add/del device. From what you described above, makes more sent to have >> it just in RTNL > >All in all I tend to agree. > >> >> > >> > @Jiri: do you have any particular opinion why we should use RTNL ops and not >> > netlink for creating/destroying interfaces? I feel this is mostly a matter of >> > taste, but maybe there are technical reasons we should consider. >> >> Well. technically, you can probabaly do both. But it is quite common >> that you can add/delete these kind of devices over RTNL. Lots of >> examples. People are used to it, aligns with existing flows. > >The only counterargument I see is the one brought by Sergey: "the ovpn >interface is not usable after creation, if no openvpn process is running". > >However, allowing to create "persistent interfaces" will define a use-case >for having an ovpn device without any userspace process. > >@Sergey what is your opinion here? I am not sure persistent interfaces were >discussed at the time you brought your point about RTNL vs NL. > > >Regards, > > >> >> > >> > Thanks a lot for your contribution. >> > >> > Regards, >> > >> > >> > > >> > > >> > > ip link add [link DEV | parentdev NAME] [ name ] NAME >> > > [ txqueuelen PACKETS ] >> > > [ address LLADDR ] >> > > [ broadcast LLADDR ] >> > > [ mtu MTU ] [index IDX ] >> > > [ numtxqueues QUEUE_COUNT ] >> > > [ numrxqueues QUEUE_COUNT ] >> > > [ netns { PID | NETNSNAME | NETNSFILE } ] >> > > type TYPE [ ARGS ] >> > > >> > > ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] >> > > >> > > Lots of examples of existing types creation is for example here: >> > > https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking >> > > >> > > >> > > >> > > > + attribute-set: ovpn >> > > > + flags: [ admin-perm ] >> > > > + doc: Delete existing interface of type ovpn >> > > > + do: >> > > > + pre: ovpn-nl-pre-doit >> > > > + post: ovpn-nl-post-doit >> > > > + request: >> > > > + attributes: >> > > > + - ifindex >> > > >> > > [...] >> > >> > -- >> > Antonio Quartulli >> > OpenVPN Inc. > >-- >Antonio Quartulli >OpenVPN Inc.
On 08/10/2024 14:52, Jiri Pirko wrote: > Tue, Oct 08, 2024 at 11:16:01AM CEST, antonio@openvpn.net wrote: >> On 08/10/2024 10:58, Jiri Pirko wrote: >>> Tue, Oct 08, 2024 at 10:01:40AM CEST, antonio@openvpn.net wrote: >>>> Hi, >>>> >>>> On 07/10/24 17:32, Jiri Pirko wrote: >>>>> Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: >>>>> >>>>> [...] >>>>> >>>>> >>>>>> +operations: >>>>>> + list: >>>>>> + - >>>>>> + name: dev-new >>>>>> + attribute-set: ovpn >>>>>> + flags: [ admin-perm ] >>>>>> + doc: Create a new interface of type ovpn >>>>>> + do: >>>>>> + request: >>>>>> + attributes: >>>>>> + - ifname >>>>>> + - mode >>>>>> + reply: >>>>>> + attributes: >>>>>> + - ifname >>>>>> + - ifindex >>>>>> + - >>>>>> + name: dev-del >>>>> >>>>> Why you expose new and del here in ovn specific generic netlink iface? >>>>> Why can't you use the exising RTNL api which is used for creation and >>>>> destruction of other types of devices? >>>> >>>> That was my original approach in v1, but it was argued that an ovpn interface >>>> needs a userspace program to be configured and used in a meaningful way, >>>> therefore it was decided to concentrate all iface mgmt APIs along with the >>>> others in the netlink family and to not expose any RTNL ops. >>> >>> Can you please point me to the message id? >> >> <CAHNKnsQnHAdxC-XhC9RP-cFp0d-E4YGb+7ie3WymXVL9N-QS6A@mail.gmail.com> from >> Sergey and subsequent replies. >> RTNL vs NL topic starts right after the definition of 'ovpn_link_ops' > > Yeah, does not make sense to me. All devices should implement common > rtnl ops, the extra-config, if needed, could be on a separate channel. > I don't find Sergey's argumentation valid. Thanks a lot for taking the time to read our conversation. Ok, considering all points we have discussed so far (including future developments already on the roadmap), I think it makes sense to go back to RTNL and drop the new/del-dev ops from the netlink family. Will do that in v9. Regards, > > >> >> Recently Kuniyuki commented on this topic as well in: >> <20240919055259.17622-1-kuniyu@amazon.com> >> and that is why I added a default dellink implemetation. > > Having dellink without newlink implemented is just wrong. > > >> >>> >>> >>>> >>>> However, recently we decided to add a dellink implementation for better >>>> integration with network namespaces and to allow the user to wipe a dangling >>>> interface. >>> >>> Hmm, one more argument to have symmetric add/del impletentation in RTNL >>> >>> >>>> >>>> In the future we are planning to also add the possibility to create a >>>> "persistent interface", that is an interface created before launching any >>>> userspace program and that survives when the latter is stopped. >>>> I can guess this functionality may be better suited for RTNL, but I am not >>>> sure yet. >>> >>> That would be quite confusing to have RTNL and genetlink iface to >>> add/del device. From what you described above, makes more sent to have >>> it just in RTNL >> >> All in all I tend to agree. >> >>> >>>> >>>> @Jiri: do you have any particular opinion why we should use RTNL ops and not >>>> netlink for creating/destroying interfaces? I feel this is mostly a matter of >>>> taste, but maybe there are technical reasons we should consider. >>> >>> Well. technically, you can probabaly do both. But it is quite common >>> that you can add/delete these kind of devices over RTNL. Lots of >>> examples. People are used to it, aligns with existing flows. >> >> The only counterargument I see is the one brought by Sergey: "the ovpn >> interface is not usable after creation, if no openvpn process is running". >> >> However, allowing to create "persistent interfaces" will define a use-case >> for having an ovpn device without any userspace process. >> >> @Sergey what is your opinion here? I am not sure persistent interfaces were >> discussed at the time you brought your point about RTNL vs NL. >> >> >> Regards, >> >> >>> >>>> >>>> Thanks a lot for your contribution. >>>> >>>> Regards, >>>> >>>> >>>>> >>>>> >>>>> ip link add [link DEV | parentdev NAME] [ name ] NAME >>>>> [ txqueuelen PACKETS ] >>>>> [ address LLADDR ] >>>>> [ broadcast LLADDR ] >>>>> [ mtu MTU ] [index IDX ] >>>>> [ numtxqueues QUEUE_COUNT ] >>>>> [ numrxqueues QUEUE_COUNT ] >>>>> [ netns { PID | NETNSNAME | NETNSFILE } ] >>>>> type TYPE [ ARGS ] >>>>> >>>>> ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] >>>>> >>>>> Lots of examples of existing types creation is for example here: >>>>> https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking >>>>> >>>>> >>>>> >>>>>> + attribute-set: ovpn >>>>>> + flags: [ admin-perm ] >>>>>> + doc: Delete existing interface of type ovpn >>>>>> + do: >>>>>> + pre: ovpn-nl-pre-doit >>>>>> + post: ovpn-nl-post-doit >>>>>> + request: >>>>>> + attributes: >>>>>> + - ifindex >>>>> >>>>> [...] >>>> >>>> -- >>>> Antonio Quartulli >>>> OpenVPN Inc. >> >> -- >> Antonio Quartulli >> OpenVPN Inc.
Hello Jiri, Sorry for the late reply. Could you elaborate a bit reasons for the RTNL interface implementation? Please find the questions inlined. On 08.10.2024 15:52, Jiri Pirko wrote: > Tue, Oct 08, 2024 at 11:16:01AM CEST, antonio@openvpn.net wrote: >> On 08/10/2024 10:58, Jiri Pirko wrote: >>> Tue, Oct 08, 2024 at 10:01:40AM CEST, antonio@openvpn.net wrote: >>>> Hi, >>>> >>>> On 07/10/24 17:32, Jiri Pirko wrote: >>>>> Wed, Oct 02, 2024 at 11:02:17AM CEST, antonio@openvpn.net wrote: >>>>> >>>>> [...] >>>>> >>>>> >>>>>> +operations: >>>>>> + list: >>>>>> + - >>>>>> + name: dev-new >>>>>> + attribute-set: ovpn >>>>>> + flags: [ admin-perm ] >>>>>> + doc: Create a new interface of type ovpn >>>>>> + do: >>>>>> + request: >>>>>> + attributes: >>>>>> + - ifname >>>>>> + - mode >>>>>> + reply: >>>>>> + attributes: >>>>>> + - ifname >>>>>> + - ifindex >>>>>> + - >>>>>> + name: dev-del >>>>> >>>>> Why you expose new and del here in ovn specific generic netlink iface? >>>>> Why can't you use the exising RTNL api which is used for creation and >>>>> destruction of other types of devices? >>>> >>>> That was my original approach in v1, but it was argued that an ovpn interface >>>> needs a userspace program to be configured and used in a meaningful way, >>>> therefore it was decided to concentrate all iface mgmt APIs along with the >>>> others in the netlink family and to not expose any RTNL ops. >>> >>> Can you please point me to the message id? >> >> <CAHNKnsQnHAdxC-XhC9RP-cFp0d-E4YGb+7ie3WymXVL9N-QS6A@mail.gmail.com> from >> Sergey and subsequent replies. >> RTNL vs NL topic starts right after the definition of 'ovpn_link_ops' > > Yeah, does not make sense to me. All devices should implement common > rtnl ops, the extra-config, if needed, could be on a separate channel. > I don't find Sergey's argumentation valid. Do we consider word *should* in terms of RFC 2119: SHOULD This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course. I am asking because rtnl_link_register() allows ops without .newlink implementation. What makes .newlink implementation as least optional and gives a freedom in design. Let me briefly summarize my argumentation from the referenced thread. We have two classes of links point-to-point and point-to-multipoint. The major class is PtP and RTNL is perfectly suited to manage it. While PtMP is a minor class and it is an obstacle for RTNL due to need to manage multiple peers. What requires a different interface to manage these peers. Lets call it GENL interface. A PtMP-class netdev without any configured peer is useless, what makes GENL interface for peers management mandatory. Mandatory to implement in both user- and kernel-space. Link creation can be implemented using any of these (RTNL or GENL) interfaces. GENL interface is already mandatory to implement in a user-space software, while RTNL can be considered optional to implement. So, implementing the link creation using GENL requires only a new message support implementation. While implementing the the link creation using RTNL requires a whole new interface implementation (socket read/write, messages demux, etc.). My point is, GENL-only management gives us consolidated and clear solution, while GENL+RTNL requires code duplication and causes a complexity. That's it. Jiri, do you see big flaws in this reasoning? >> Recently Kuniyuki commented on this topic as well in: >> <20240919055259.17622-1-kuniyu@amazon.com> >> and that is why I added a default dellink implemetation. > > Having dellink without newlink implemented is just wrong. Could you clarify this statement please? I can not recall any documentation or a code block that enforces .newlink implementation in case of the .dellink presence. Generally speaking, I can understand a feel of irregularity when looking at code implementing delete operation without a link creation counterpart. This confusion can be resolved taking into consideration a difference in a nature of these operations. A new link can not be created automatically while an existing link can be removed automatically without any extra inputs. .newlink designated only for fulfilling user's requests since it requires extra information unavailable inside the kernel. While .dellink has two semantics: (a) user's requests fulfilling, (b) automatic cleanup of unneeded remainders. From that perspective, having an option to implement .dellink without .newlink implementation looks reasonable. >>>> However, recently we decided to add a dellink implementation for better >>>> integration with network namespaces and to allow the user to wipe a dangling >>>> interface. >>> >>> Hmm, one more argument to have symmetric add/del impletentation in RTNL >>> >>> >>>> >>>> In the future we are planning to also add the possibility to create a >>>> "persistent interface", that is an interface created before launching any >>>> userspace program and that survives when the latter is stopped. >>>> I can guess this functionality may be better suited for RTNL, but I am not >>>> sure yet. >>> >>> That would be quite confusing to have RTNL and genetlink iface to >>> add/del device. From what you described above, makes more sent to have >>> it just in RTNL >> >> All in all I tend to agree. >> >>> >>>> >>>> @Jiri: do you have any particular opinion why we should use RTNL ops and not >>>> netlink for creating/destroying interfaces? I feel this is mostly a matter of >>>> taste, but maybe there are technical reasons we should consider. >>> >>> Well. technically, you can probabaly do both. But it is quite common >>> that you can add/delete these kind of devices over RTNL. Lots of >>> examples. People are used to it, aligns with existing flows. >> >> The only counterargument I see is the one brought by Sergey: "the ovpn >> interface is not usable after creation, if no openvpn process is running". >> >> However, allowing to create "persistent interfaces" will define a use-case >> for having an ovpn device without any userspace process. >> >> @Sergey what is your opinion here? I am not sure persistent interfaces were >> discussed at the time you brought your point about RTNL vs NL. >> >> >> Regards, >> >> >>> >>>> >>>> Thanks a lot for your contribution. >>>> >>>> Regards, >>>> >>>> >>>>> >>>>> >>>>> ip link add [link DEV | parentdev NAME] [ name ] NAME >>>>> [ txqueuelen PACKETS ] >>>>> [ address LLADDR ] >>>>> [ broadcast LLADDR ] >>>>> [ mtu MTU ] [index IDX ] >>>>> [ numtxqueues QUEUE_COUNT ] >>>>> [ numrxqueues QUEUE_COUNT ] >>>>> [ netns { PID | NETNSNAME | NETNSFILE } ] >>>>> type TYPE [ ARGS ] >>>>> >>>>> ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] >>>>> >>>>> Lots of examples of existing types creation is for example here: >>>>> https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking >>>>> >>>>> >>>>> >>>>>> + attribute-set: ovpn >>>>>> + flags: [ admin-perm ] >>>>>> + doc: Delete existing interface of type ovpn >>>>>> + do: >>>>>> + pre: ovpn-nl-pre-doit >>>>>> + post: ovpn-nl-post-doit >>>>>> + request: >>>>>> + attributes: >>>>>> + - ifindex -- Sergey
diff --git a/Documentation/netlink/specs/ovpn.yaml b/Documentation/netlink/specs/ovpn.yaml new file mode 100644 index 0000000000000000000000000000000000000000..36983f293ecbd59532114808a20737005e91ad72 --- /dev/null +++ b/Documentation/netlink/specs/ovpn.yaml @@ -0,0 +1,387 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +# +# Author: Antonio Quartulli <antonio@openvpn.net> +# +# Copyright (c) 2024, OpenVPN Inc. +# + +name: ovpn + +protocol: genetlink + +doc: Netlink protocol to control OpenVPN network devices + +definitions: + - + type: const + name: nonce-tail-size + value: 8 + - + type: enum + name: cipher-alg + value-start: 0 + entries: [ none, aes-gcm, chacha20-poly1305 ] + - + type: enum + name: del-peer-reason + value-start: 0 + entries: [ teardown, userspace, expired, transport-error, transport-disconnect ] + - + type: enum + name: key-slot + value-start: 0 + entries: [ primary, secondary ] + - + type: enum + name: mode + value-start: 0 + entries: [ p2p, mp ] + +attribute-sets: + - + name: peer + attributes: + - + name: id + type: u32 + doc: | + The unique ID of the peer. To be used to identify peers during + operations + checks: + max: 0xFFFFFF + - + name: remote-ipv4 + type: u32 + doc: The remote IPv4 address of the peer + byte-order: big-endian + display-hint: ipv4 + - + name: remote-ipv6 + type: binary + doc: The remote IPv6 address of the peer + display-hint: ipv6 + checks: + exact-len: 16 + - + name: remote-ipv6-scope-id + type: u32 + doc: The scope id of the remote IPv6 address of the peer (RFC2553) + - + name: remote-port + type: u16 + doc: The remote port of the peer + byte-order: big-endian + checks: + min: 1 + - + name: socket + type: u32 + doc: The socket to be used to communicate with the peer + - + name: vpn-ipv4 + type: u32 + doc: The IPv4 address assigned to the peer by the server + byte-order: big-endian + display-hint: ipv4 + - + name: vpn-ipv6 + type: binary + doc: The IPv6 address assigned to the peer by the server + display-hint: ipv6 + checks: + exact-len: 16 + - + name: local-ipv4 + type: u32 + doc: The local IPv4 to be used to send packets to the peer (UDP only) + byte-order: big-endian + display-hint: ipv4 + - + name: local-ipv6 + type: binary + doc: The local IPv6 to be used to send packets to the peer (UDP only) + display-hint: ipv6 + checks: + exact-len: 16 + - + name: local-port + type: u16 + doc: The local port to be used to send packets to the peer (UDP only) + byte-order: big-endian + checks: + min: 1 + - + name: keepalive-interval + type: u32 + doc: | + The number of seconds after which a keep alive message is sent to the + peer + - + name: keepalive-timeout + type: u32 + doc: | + The number of seconds from the last activity after which the peer is + assumed dead + - + name: del-reason + type: u32 + doc: The reason why a peer was deleted + enum: del-peer-reason + - + name: vpn-rx-bytes + type: uint + doc: Number of bytes received over the tunnel + - + name: vpn-tx-bytes + type: uint + doc: Number of bytes transmitted over the tunnel + - + name: vpn-rx-packets + type: uint + doc: Number of packets received over the tunnel + - + name: vpn-tx-packets + type: uint + doc: Number of packets transmitted over the tunnel + - + name: link-rx-bytes + type: uint + doc: Number of bytes received at the transport level + - + name: link-tx-bytes + type: uint + doc: Number of bytes transmitted at the transport level + - + name: link-rx-packets + type: u32 + doc: Number of packets received at the transport level + - + name: link-tx-packets + type: u32 + doc: Number of packets transmitted at the transport level + - + name: keyconf + attributes: + - + name: peer-id + type: u32 + doc: | + The unique ID of the peer. To be used to identify peers during + key operations + checks: + max: 0xFFFFFF + - + name: slot + type: u32 + doc: The slot where the key should be stored + enum: key-slot + - + name: key-id + doc: | + The unique ID of the key. Used to fetch the correct key upon + decryption + type: u32 + checks: + max: 7 + - + name: cipher-alg + type: u32 + doc: The cipher to be used when communicating with the peer + enum: cipher-alg + - + name: encrypt-dir + type: nest + doc: Key material for encrypt direction + nested-attributes: keydir + - + name: decrypt-dir + type: nest + doc: Key material for decrypt direction + nested-attributes: keydir + - + name: keydir + attributes: + - + name: cipher-key + type: binary + doc: The actual key to be used by the cipher + checks: + max-len: 256 + - + name: nonce-tail + type: binary + doc: | + Random nonce to be concatenated to the packet ID, in order to + obtain the actua cipher IV + checks: + exact-len: nonce-tail-size + - + name: ovpn + attributes: + - + name: ifindex + type: u32 + doc: Index of the ovpn interface to operate on + - + name: ifname + type: string + doc: Name of the ovpn interface that is being created + - + name: mode + type: u32 + enum: mode + doc: | + Oper mode instructing an interface to act as Point2Point or + MultiPoint + - + name: peer + type: nest + doc: | + The peer object containing the attributed of interest for the specific + operation + nested-attributes: peer + - + name: keyconf + type: nest + doc: Peer specific cipher configuration + nested-attributes: keyconf + +operations: + list: + - + name: dev-new + attribute-set: ovpn + flags: [ admin-perm ] + doc: Create a new interface of type ovpn + do: + request: + attributes: + - ifname + - mode + reply: + attributes: + - ifname + - ifindex + - + name: dev-del + attribute-set: ovpn + flags: [ admin-perm ] + doc: Delete existing interface of type ovpn + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - + name: peer-new + attribute-set: ovpn + flags: [ admin-perm ] + doc: Add a remote peer + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - peer + - + name: peer-set + attribute-set: ovpn + flags: [ admin-perm ] + doc: modify a remote peer + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - peer + - + name: peer-get + attribute-set: ovpn + flags: [ admin-perm ] + doc: Retrieve data about existing remote peers (or a specific one) + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - peer + reply: + attributes: + - peer + dump: + request: + attributes: + - ifindex + reply: + attributes: + - peer + - + name: peer-del + attribute-set: ovpn + flags: [ admin-perm ] + doc: Delete existing remote peer + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - peer + - + name: peer-del-ntf + doc: Notification about a peer being deleted + notify: peer-get + mcgrp: peers + + - + name: key-new + attribute-set: ovpn + flags: [ admin-perm ] + doc: Add a cipher key for a specific peer + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - keyconf + - + name: key-swap + attribute-set: ovpn + flags: [ admin-perm ] + doc: Swap primary and secondary session keys for a specific peer + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - keyconf + - + name: key-swap-ntf + notify: key-new + doc: | + Notification about key having exhausted its IV space and requiring + renegotiation + mcgrp: peers + - + name: key-del + attribute-set: ovpn + flags: [ admin-perm ] + doc: Delete cipher key for a specific peer + do: + pre: ovpn-nl-pre-doit + post: ovpn-nl-post-doit + request: + attributes: + - ifindex + - keyconf + +mcast-groups: + list: + - + name: peers diff --git a/MAINTAINERS b/MAINTAINERS index 0f02c9e1664fddb5ad45232e46b02c42aa27f1b6..f753060d4e2467a786778ddd4f835861a603ce02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17455,6 +17455,8 @@ L: netdev@vger.kernel.org S: Maintained T: git https://github.com/OpenVPN/linux-kernel-ovpn.git F: drivers/net/ovpn/ +F: include/uapi/linux/ovpn.h +F: Documentation/netlink/spec/ovpn.yaml P54 WIRELESS DRIVER M: Christian Lamparter <chunkeey@googlemail.com> diff --git a/drivers/net/ovpn/Makefile b/drivers/net/ovpn/Makefile index 53fb197027d787d6683e9056d3d341abf6ed38e4..201dc001419f1d99ae95c0ee0f96e68f8a4eac16 100644 --- a/drivers/net/ovpn/Makefile +++ b/drivers/net/ovpn/Makefile @@ -9,3 +9,5 @@ obj-$(CONFIG_OVPN) := ovpn.o ovpn-y += main.o ovpn-y += io.o +ovpn-y += netlink.o +ovpn-y += netlink-gen.o diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c index 2a9a8e11c5111eb36fab1fb47d6c4c6dfdf56a78..0274ddddbcd25080d7f85347f79aad0259771508 100644 --- a/drivers/net/ovpn/main.c +++ b/drivers/net/ovpn/main.c @@ -7,12 +7,16 @@ * James Yonan <james@openvpn.net> */ +#include <linux/genetlink.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/version.h> #include <net/rtnetlink.h> +#include <uapi/linux/ovpn.h> +#include "ovpnstruct.h" #include "main.h" +#include "netlink.h" #include "io.h" /* Driver info */ @@ -31,7 +35,7 @@ bool ovpn_dev_is_valid(const struct net_device *dev) } static struct rtnl_link_ops ovpn_link_ops = { - .kind = "ovpn", + .kind = OVPN_FAMILY_NAME, .netns_refund = false, .dellink = unregister_netdevice_queue, }; @@ -86,8 +90,16 @@ static int __init ovpn_init(void) goto unreg_netdev; } + err = ovpn_nl_register(); + if (err) { + pr_err("ovpn: can't register netlink family: %d\n", err); + goto unreg_rtnl; + } + return 0; +unreg_rtnl: + rtnl_link_unregister(&ovpn_link_ops); unreg_netdev: unregister_netdevice_notifier(&ovpn_netdev_notifier); return err; @@ -95,6 +107,7 @@ static int __init ovpn_init(void) static __exit void ovpn_cleanup(void) { + ovpn_nl_unregister(); rtnl_link_unregister(&ovpn_link_ops); unregister_netdevice_notifier(&ovpn_netdev_notifier); diff --git a/drivers/net/ovpn/netlink-gen.c b/drivers/net/ovpn/netlink-gen.c new file mode 100644 index 0000000000000000000000000000000000000000..9912706a2d68282e7d483404002cd0eeb1140ba6 --- /dev/null +++ b/drivers/net/ovpn/netlink-gen.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ovpn.yaml */ +/* YNL-GEN kernel source */ + +#include <net/netlink.h> +#include <net/genetlink.h> + +#include "netlink-gen.h" + +#include <uapi/linux/ovpn.h> + +/* Integer value ranges */ +static const struct netlink_range_validation ovpn_a_peer_id_range = { + .max = 16777215ULL, +}; + +static const struct netlink_range_validation ovpn_a_keyconf_peer_id_range = { + .max = 16777215ULL, +}; + +/* Common nested types */ +const struct nla_policy ovpn_keyconf_nl_policy[OVPN_A_KEYCONF_DECRYPT_DIR + 1] = { + [OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range), + [OVPN_A_KEYCONF_SLOT] = NLA_POLICY_MAX(NLA_U32, 1), + [OVPN_A_KEYCONF_KEY_ID] = NLA_POLICY_MAX(NLA_U32, 7), + [OVPN_A_KEYCONF_CIPHER_ALG] = NLA_POLICY_MAX(NLA_U32, 2), + [OVPN_A_KEYCONF_ENCRYPT_DIR] = NLA_POLICY_NESTED(ovpn_keydir_nl_policy), + [OVPN_A_KEYCONF_DECRYPT_DIR] = NLA_POLICY_NESTED(ovpn_keydir_nl_policy), +}; + +const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1] = { + [OVPN_A_KEYDIR_CIPHER_KEY] = NLA_POLICY_MAX_LEN(256), + [OVPN_A_KEYDIR_NONCE_TAIL] = NLA_POLICY_EXACT_LEN(OVPN_NONCE_TAIL_SIZE), +}; + +const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1] = { + [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), + [OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_U32, }, + [OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16), + [OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID] = { .type = NLA_U32, }, + [OVPN_A_PEER_REMOTE_PORT] = NLA_POLICY_MIN(NLA_U16, 1), + [OVPN_A_PEER_SOCKET] = { .type = NLA_U32, }, + [OVPN_A_PEER_VPN_IPV4] = { .type = NLA_U32, }, + [OVPN_A_PEER_VPN_IPV6] = NLA_POLICY_EXACT_LEN(16), + [OVPN_A_PEER_LOCAL_IPV4] = { .type = NLA_U32, }, + [OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16), + [OVPN_A_PEER_LOCAL_PORT] = NLA_POLICY_MIN(NLA_U16, 1), + [OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, }, + [OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, }, + [OVPN_A_PEER_DEL_REASON] = NLA_POLICY_MAX(NLA_U32, 4), + [OVPN_A_PEER_VPN_RX_BYTES] = { .type = NLA_UINT, }, + [OVPN_A_PEER_VPN_TX_BYTES] = { .type = NLA_UINT, }, + [OVPN_A_PEER_VPN_RX_PACKETS] = { .type = NLA_UINT, }, + [OVPN_A_PEER_VPN_TX_PACKETS] = { .type = NLA_UINT, }, + [OVPN_A_PEER_LINK_RX_BYTES] = { .type = NLA_UINT, }, + [OVPN_A_PEER_LINK_TX_BYTES] = { .type = NLA_UINT, }, + [OVPN_A_PEER_LINK_RX_PACKETS] = { .type = NLA_U32, }, + [OVPN_A_PEER_LINK_TX_PACKETS] = { .type = NLA_U32, }, +}; + +/* OVPN_CMD_DEV_NEW - do */ +static const struct nla_policy ovpn_dev_new_nl_policy[OVPN_A_MODE + 1] = { + [OVPN_A_IFNAME] = { .type = NLA_NUL_STRING, }, + [OVPN_A_MODE] = NLA_POLICY_MAX(NLA_U32, 1), +}; + +/* OVPN_CMD_DEV_DEL - do */ +static const struct nla_policy ovpn_dev_del_nl_policy[OVPN_A_IFINDEX + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, +}; + +/* OVPN_CMD_PEER_NEW - do */ +static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_PEER + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), +}; + +/* OVPN_CMD_PEER_SET - do */ +static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_PEER + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), +}; + +/* OVPN_CMD_PEER_GET - do */ +static const struct nla_policy ovpn_peer_get_do_nl_policy[OVPN_A_PEER + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), +}; + +/* OVPN_CMD_PEER_GET - dump */ +static const struct nla_policy ovpn_peer_get_dump_nl_policy[OVPN_A_IFINDEX + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, +}; + +/* OVPN_CMD_PEER_DEL - do */ +static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_PEER + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), +}; + +/* OVPN_CMD_KEY_NEW - do */ +static const struct nla_policy ovpn_key_new_nl_policy[OVPN_A_KEYCONF + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), +}; + +/* OVPN_CMD_KEY_SWAP - do */ +static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_KEYCONF + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), +}; + +/* OVPN_CMD_KEY_DEL - do */ +static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_KEYCONF + 1] = { + [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), +}; + +/* Ops table for ovpn */ +static const struct genl_split_ops ovpn_nl_ops[] = { + { + .cmd = OVPN_CMD_DEV_NEW, + .doit = ovpn_nl_dev_new_doit, + .policy = ovpn_dev_new_nl_policy, + .maxattr = OVPN_A_MODE, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_DEV_DEL, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_dev_del_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_dev_del_nl_policy, + .maxattr = OVPN_A_IFINDEX, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_PEER_NEW, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_peer_new_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_peer_new_nl_policy, + .maxattr = OVPN_A_PEER, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_PEER_SET, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_peer_set_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_peer_set_nl_policy, + .maxattr = OVPN_A_PEER, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_PEER_GET, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_peer_get_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_peer_get_do_nl_policy, + .maxattr = OVPN_A_PEER, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_PEER_GET, + .dumpit = ovpn_nl_peer_get_dumpit, + .policy = ovpn_peer_get_dump_nl_policy, + .maxattr = OVPN_A_IFINDEX, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + }, + { + .cmd = OVPN_CMD_PEER_DEL, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_peer_del_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_peer_del_nl_policy, + .maxattr = OVPN_A_PEER, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_KEY_NEW, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_key_new_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_key_new_nl_policy, + .maxattr = OVPN_A_KEYCONF, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_KEY_SWAP, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_key_swap_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_key_swap_nl_policy, + .maxattr = OVPN_A_KEYCONF, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd = OVPN_CMD_KEY_DEL, + .pre_doit = ovpn_nl_pre_doit, + .doit = ovpn_nl_key_del_doit, + .post_doit = ovpn_nl_post_doit, + .policy = ovpn_key_del_nl_policy, + .maxattr = OVPN_A_KEYCONF, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, +}; + +static const struct genl_multicast_group ovpn_nl_mcgrps[] = { + [OVPN_NLGRP_PEERS] = { "peers", }, +}; + +struct genl_family ovpn_nl_family __ro_after_init = { + .name = OVPN_FAMILY_NAME, + .version = OVPN_FAMILY_VERSION, + .netnsok = true, + .parallel_ops = true, + .module = THIS_MODULE, + .split_ops = ovpn_nl_ops, + .n_split_ops = ARRAY_SIZE(ovpn_nl_ops), + .mcgrps = ovpn_nl_mcgrps, + .n_mcgrps = ARRAY_SIZE(ovpn_nl_mcgrps), +}; diff --git a/drivers/net/ovpn/netlink-gen.h b/drivers/net/ovpn/netlink-gen.h new file mode 100644 index 0000000000000000000000000000000000000000..1b7aeb80af1091d5fe968c886fb019ba6f9a19a8 --- /dev/null +++ b/drivers/net/ovpn/netlink-gen.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ovpn.yaml */ +/* YNL-GEN kernel header */ + +#ifndef _LINUX_OVPN_GEN_H +#define _LINUX_OVPN_GEN_H + +#include <net/netlink.h> +#include <net/genetlink.h> + +#include <uapi/linux/ovpn.h> + +/* Common nested types */ +extern const struct nla_policy ovpn_keyconf_nl_policy[OVPN_A_KEYCONF_DECRYPT_DIR + 1]; +extern const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1]; +extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1]; + +int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, + struct genl_info *info); +void +ovpn_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, + struct genl_info *info); + +int ovpn_nl_dev_new_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_dev_del_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_peer_get_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_peer_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb); +int ovpn_nl_peer_del_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_key_new_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_key_swap_doit(struct sk_buff *skb, struct genl_info *info); +int ovpn_nl_key_del_doit(struct sk_buff *skb, struct genl_info *info); + +enum { + OVPN_NLGRP_PEERS, +}; + +extern struct genl_family ovpn_nl_family; + +#endif /* _LINUX_OVPN_GEN_H */ diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c new file mode 100644 index 0000000000000000000000000000000000000000..7b6b4d03b845eeb8654e37ac3495e8172ac3f291 --- /dev/null +++ b/drivers/net/ovpn/netlink.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* OpenVPN data channel offload + * + * Copyright (C) 2020-2024 OpenVPN, Inc. + * + * Author: Antonio Quartulli <antonio@openvpn.net> + */ + +#include <linux/netdevice.h> +#include <net/genetlink.h> + +#include <uapi/linux/ovpn.h> + +#include "ovpnstruct.h" +#include "main.h" +#include "io.h" +#include "netlink.h" +#include "netlink-gen.h" + +MODULE_ALIAS_GENL_FAMILY(OVPN_FAMILY_NAME); + +/** + * ovpn_get_dev_from_attrs - retrieve the netdevice a netlink message is + * targeting + * @net: network namespace where to look for the interface + * @info: generic netlink info from the user request + * + * Return: the netdevice, if found, or an error otherwise + */ +static struct net_device * +ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info) +{ + struct net_device *dev; + int ifindex; + + if (GENL_REQ_ATTR_CHECK(info, OVPN_A_IFINDEX)) + return ERR_PTR(-EINVAL); + + ifindex = nla_get_u32(info->attrs[OVPN_A_IFINDEX]); + + dev = dev_get_by_index(net, ifindex); + if (!dev) { + NL_SET_ERR_MSG_MOD(info->extack, + "ifindex does not match any interface"); + return ERR_PTR(-ENODEV); + } + + if (!ovpn_dev_is_valid(dev)) + goto err_put_dev; + + return dev; + +err_put_dev: + netdev_put(dev, NULL); + + NL_SET_ERR_MSG_MOD(info->extack, "specified interface is not ovpn"); + NL_SET_BAD_ATTR(info->extack, info->attrs[OVPN_A_IFINDEX]); + + return ERR_PTR(-EINVAL); +} + +int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, + struct genl_info *info) +{ + struct net *net = genl_info_net(info); + struct net_device *dev = ovpn_get_dev_from_attrs(net, info); + + if (IS_ERR(dev)) + return PTR_ERR(dev); + + info->user_ptr[0] = netdev_priv(dev); + + return 0; +} + +void ovpn_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, + struct genl_info *info) +{ + struct ovpn_struct *ovpn = info->user_ptr[0]; + + if (ovpn) + netdev_put(ovpn->dev, NULL); +} + +int ovpn_nl_dev_new_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_dev_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_peer_get_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_peer_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_peer_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_key_new_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_key_swap_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +int ovpn_nl_key_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + return -EOPNOTSUPP; +} + +/** + * ovpn_nl_register - perform any needed registration in the NL subsustem + * + * Return: 0 on success, a negative error code otherwise + */ +int __init ovpn_nl_register(void) +{ + int ret = genl_register_family(&ovpn_nl_family); + + if (ret) { + pr_err("ovpn: genl_register_family failed: %d\n", ret); + return ret; + } + + return 0; +} + +/** + * ovpn_nl_unregister - undo any module wide netlink registration + */ +void ovpn_nl_unregister(void) +{ + genl_unregister_family(&ovpn_nl_family); +} diff --git a/drivers/net/ovpn/netlink.h b/drivers/net/ovpn/netlink.h new file mode 100644 index 0000000000000000000000000000000000000000..9e87cf11d1e9813b7a75ddf3705ab7d5fabe899f --- /dev/null +++ b/drivers/net/ovpn/netlink.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* OpenVPN data channel offload + * + * Copyright (C) 2020-2024 OpenVPN, Inc. + * + * Author: Antonio Quartulli <antonio@openvpn.net> + */ + +#ifndef _NET_OVPN_NETLINK_H_ +#define _NET_OVPN_NETLINK_H_ + +int ovpn_nl_register(void); +void ovpn_nl_unregister(void); + +#endif /* _NET_OVPN_NETLINK_H_ */ diff --git a/drivers/net/ovpn/ovpnstruct.h b/drivers/net/ovpn/ovpnstruct.h new file mode 100644 index 0000000000000000000000000000000000000000..ff248cad1401d00c5bf0aadf9341e40d0a4aee4b --- /dev/null +++ b/drivers/net/ovpn/ovpnstruct.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* OpenVPN data channel offload + * + * Copyright (C) 2019-2024 OpenVPN, Inc. + * + * Author: James Yonan <james@openvpn.net> + * Antonio Quartulli <antonio@openvpn.net> + */ + +#ifndef _NET_OVPN_OVPNSTRUCT_H_ +#define _NET_OVPN_OVPNSTRUCT_H_ + +/** + * struct ovpn_struct - per ovpn interface state + * @dev: the actual netdev representing the tunnel + */ +struct ovpn_struct { + struct net_device *dev; +}; + +#endif /* _NET_OVPN_OVPNSTRUCT_H_ */ diff --git a/include/uapi/linux/ovpn.h b/include/uapi/linux/ovpn.h new file mode 100644 index 0000000000000000000000000000000000000000..adf4cafd9624308cc7bf1935bba55fb38bb6ba8c --- /dev/null +++ b/include/uapi/linux/ovpn.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ovpn.yaml */ +/* YNL-GEN uapi header */ + +#ifndef _UAPI_LINUX_OVPN_H +#define _UAPI_LINUX_OVPN_H + +#define OVPN_FAMILY_NAME "ovpn" +#define OVPN_FAMILY_VERSION 1 + +#define OVPN_NONCE_TAIL_SIZE 8 + +enum ovpn_cipher_alg { + OVPN_CIPHER_ALG_NONE, + OVPN_CIPHER_ALG_AES_GCM, + OVPN_CIPHER_ALG_CHACHA20_POLY1305, +}; + +enum ovpn_del_peer_reason { + OVPN_DEL_PEER_REASON_TEARDOWN, + OVPN_DEL_PEER_REASON_USERSPACE, + OVPN_DEL_PEER_REASON_EXPIRED, + OVPN_DEL_PEER_REASON_TRANSPORT_ERROR, + OVPN_DEL_PEER_REASON_TRANSPORT_DISCONNECT, +}; + +enum ovpn_key_slot { + OVPN_KEY_SLOT_PRIMARY, + OVPN_KEY_SLOT_SECONDARY, +}; + +enum ovpn_mode { + OVPN_MODE_P2P, + OVPN_MODE_MP, +}; + +enum { + OVPN_A_PEER_ID = 1, + OVPN_A_PEER_REMOTE_IPV4, + OVPN_A_PEER_REMOTE_IPV6, + OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID, + OVPN_A_PEER_REMOTE_PORT, + OVPN_A_PEER_SOCKET, + OVPN_A_PEER_VPN_IPV4, + OVPN_A_PEER_VPN_IPV6, + OVPN_A_PEER_LOCAL_IPV4, + OVPN_A_PEER_LOCAL_IPV6, + OVPN_A_PEER_LOCAL_PORT, + OVPN_A_PEER_KEEPALIVE_INTERVAL, + OVPN_A_PEER_KEEPALIVE_TIMEOUT, + OVPN_A_PEER_DEL_REASON, + OVPN_A_PEER_VPN_RX_BYTES, + OVPN_A_PEER_VPN_TX_BYTES, + OVPN_A_PEER_VPN_RX_PACKETS, + OVPN_A_PEER_VPN_TX_PACKETS, + OVPN_A_PEER_LINK_RX_BYTES, + OVPN_A_PEER_LINK_TX_BYTES, + OVPN_A_PEER_LINK_RX_PACKETS, + OVPN_A_PEER_LINK_TX_PACKETS, + + __OVPN_A_PEER_MAX, + OVPN_A_PEER_MAX = (__OVPN_A_PEER_MAX - 1) +}; + +enum { + OVPN_A_KEYCONF_PEER_ID = 1, + OVPN_A_KEYCONF_SLOT, + OVPN_A_KEYCONF_KEY_ID, + OVPN_A_KEYCONF_CIPHER_ALG, + OVPN_A_KEYCONF_ENCRYPT_DIR, + OVPN_A_KEYCONF_DECRYPT_DIR, + + __OVPN_A_KEYCONF_MAX, + OVPN_A_KEYCONF_MAX = (__OVPN_A_KEYCONF_MAX - 1) +}; + +enum { + OVPN_A_KEYDIR_CIPHER_KEY = 1, + OVPN_A_KEYDIR_NONCE_TAIL, + + __OVPN_A_KEYDIR_MAX, + OVPN_A_KEYDIR_MAX = (__OVPN_A_KEYDIR_MAX - 1) +}; + +enum { + OVPN_A_IFINDEX = 1, + OVPN_A_IFNAME, + OVPN_A_MODE, + OVPN_A_PEER, + OVPN_A_KEYCONF, + + __OVPN_A_MAX, + OVPN_A_MAX = (__OVPN_A_MAX - 1) +}; + +enum { + OVPN_CMD_DEV_NEW = 1, + OVPN_CMD_DEV_DEL, + OVPN_CMD_PEER_NEW, + OVPN_CMD_PEER_SET, + OVPN_CMD_PEER_GET, + OVPN_CMD_PEER_DEL, + OVPN_CMD_PEER_DEL_NTF, + OVPN_CMD_KEY_NEW, + OVPN_CMD_KEY_SWAP, + OVPN_CMD_KEY_SWAP_NTF, + OVPN_CMD_KEY_DEL, + + __OVPN_CMD_MAX, + OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) +}; + +#define OVPN_MCGRP_PEERS "peers" + +#endif /* _UAPI_LINUX_OVPN_H */
This commit introduces basic netlink support with family registration/unregistration functionalities and stub pre/post-doit. More importantly it introduces the YAML uAPI description along with its auto-generated files: - include/uapi/linux/ovpn.h - drivers/net/ovpn/netlink-gen.c - drivers/net/ovpn/netlink-gen.h Cc: donald.hunter@gmail.com Signed-off-by: Antonio Quartulli <antonio@openvpn.net> --- Documentation/netlink/specs/ovpn.yaml | 387 ++++++++++++++++++++++++++++++++++ MAINTAINERS | 2 + drivers/net/ovpn/Makefile | 2 + drivers/net/ovpn/main.c | 15 +- drivers/net/ovpn/netlink-gen.c | 224 ++++++++++++++++++++ drivers/net/ovpn/netlink-gen.h | 42 ++++ drivers/net/ovpn/netlink.c | 158 ++++++++++++++ drivers/net/ovpn/netlink.h | 15 ++ drivers/net/ovpn/ovpnstruct.h | 21 ++ include/uapi/linux/ovpn.h | 116 ++++++++++ 10 files changed, 981 insertions(+), 1 deletion(-)