^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * INET An implementation of the TCP/IP protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. INET is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * INET protocol dispatch tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Authors: Ross Biro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Fixes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Alan Cox : Ahah! udp icmp errors don't work because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * udp_err is never called!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Alan Cox : Added new fields for init and ready for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * proper fragmentation (_NO_ 4K limits!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Richard Colella : Hang on hash collision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Vince Laviano : Modified inet_del_protocol() to correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * maintain copy bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) EXPORT_SYMBOL(inet_protos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) EXPORT_SYMBOL(inet_offloads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!prot->netns_ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pr_err("Protocol %u is not namespace aware, cannot register.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return !cmpxchg((const struct net_protocol **)&inet_protos[protocol],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) NULL, prot) ? 0 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) EXPORT_SYMBOL(inet_add_protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return !cmpxchg((const struct net_offload **)&inet_offloads[protocol],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) NULL, prot) ? 0 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) EXPORT_SYMBOL(inet_add_offload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ret = (cmpxchg((const struct net_protocol **)&inet_protos[protocol],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) prot, NULL) == prot) ? 0 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) synchronize_net();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) EXPORT_SYMBOL(inet_del_protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int inet_del_offload(const struct net_offload *prot, unsigned char protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret = (cmpxchg((const struct net_offload **)&inet_offloads[protocol],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) prot, NULL) == prot) ? 0 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) synchronize_net();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) EXPORT_SYMBOL(inet_del_offload);