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