1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * INET An implementation of the TCP/IP protocol suite for the LINUX 41da177e4SLinus Torvalds * operating system. INET is implemented using the BSD Socket 51da177e4SLinus Torvalds * interface as the means of communication with the user level. 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * INET protocol dispatch tables. 81da177e4SLinus Torvalds * 902c30a84SJesper Juhl * Authors: Ross Biro 101da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Fixes: 131da177e4SLinus Torvalds * Alan Cox : Ahah! udp icmp errors don't work because 141da177e4SLinus Torvalds * udp_err is never called! 151da177e4SLinus Torvalds * Alan Cox : Added new fields for init and ready for 161da177e4SLinus Torvalds * proper fragmentation (_NO_ 4K limits!) 171da177e4SLinus Torvalds * Richard Colella : Hang on hash collision 181da177e4SLinus Torvalds * Vince Laviano : Modified inet_del_protocol() to correctly 191da177e4SLinus Torvalds * maintain copy bit. 201da177e4SLinus Torvalds */ 21fa1a9c68SAlexey Dobriyan #include <linux/cache.h> 221da177e4SLinus Torvalds #include <linux/module.h> 231da177e4SLinus Torvalds #include <linux/netdevice.h> 24fa1a9c68SAlexey Dobriyan #include <linux/spinlock.h> 251da177e4SLinus Torvalds #include <net/protocol.h> 261da177e4SLinus Torvalds 27dddb64bcSsubashab@codeaurora.org struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly; 28b8a51b38SStefano Brivio EXPORT_SYMBOL(inet_protos); 29de27d001SVlad Yasevich const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly; 30ce3e0286STom Herbert EXPORT_SYMBOL(inet_offloads); 311da177e4SLinus Torvalds 3232613090SAlexey Dobriyan int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol) 331da177e4SLinus Torvalds { 34547472b8SDavid S. Miller if (!prot->netns_ok) { 35547472b8SDavid S. Miller pr_err("Protocol %u is not namespace aware, cannot register.\n", 36547472b8SDavid S. Miller protocol); 37547472b8SDavid S. Miller return -EINVAL; 38547472b8SDavid S. Miller } 39547472b8SDavid S. Miller 40f9242b6bSDavid S. Miller return !cmpxchg((const struct net_protocol **)&inet_protos[protocol], 41e0ad61ecSEric Dumazet NULL, prot) ? 0 : -1; 421da177e4SLinus Torvalds } 434bc2f18bSEric Dumazet EXPORT_SYMBOL(inet_add_protocol); 441da177e4SLinus Torvalds 45de27d001SVlad Yasevich int inet_add_offload(const struct net_offload *prot, unsigned char protocol) 46de27d001SVlad Yasevich { 47de27d001SVlad Yasevich return !cmpxchg((const struct net_offload **)&inet_offloads[protocol], 48de27d001SVlad Yasevich NULL, prot) ? 0 : -1; 49de27d001SVlad Yasevich } 50de27d001SVlad Yasevich EXPORT_SYMBOL(inet_add_offload); 51de27d001SVlad Yasevich 5232613090SAlexey Dobriyan int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol) 531da177e4SLinus Torvalds { 54f9242b6bSDavid S. Miller int ret; 551da177e4SLinus Torvalds 56f9242b6bSDavid S. Miller ret = (cmpxchg((const struct net_protocol **)&inet_protos[protocol], 57e0ad61ecSEric Dumazet prot, NULL) == prot) ? 0 : -1; 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds synchronize_net(); 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds return ret; 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds EXPORT_SYMBOL(inet_del_protocol); 64de27d001SVlad Yasevich 65de27d001SVlad Yasevich int inet_del_offload(const struct net_offload *prot, unsigned char protocol) 66de27d001SVlad Yasevich { 67de27d001SVlad Yasevich int ret; 68de27d001SVlad Yasevich 69de27d001SVlad Yasevich ret = (cmpxchg((const struct net_offload **)&inet_offloads[protocol], 70de27d001SVlad Yasevich prot, NULL) == prot) ? 0 : -1; 71de27d001SVlad Yasevich 72de27d001SVlad Yasevich synchronize_net(); 73de27d001SVlad Yasevich 74de27d001SVlad Yasevich return ret; 75de27d001SVlad Yasevich } 76de27d001SVlad Yasevich EXPORT_SYMBOL(inet_del_offload); 77