1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * INET An implementation of the TCP/I 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 4 * operating system. INET is imp 3 * operating system. INET is implemented using the BSD Socket 5 * interface as the means of comm 4 * interface as the means of communication with the user level. 6 * 5 * 7 * PF_INET6 protocol dispatch tab 6 * PF_INET6 protocol dispatch tables. 8 * 7 * 9 * Authors: Pedro Roque <roque@di.fc.u !! 8 * Version: $Id: protocol.c,v 1.10 2001/05/18 02:25:49 davem Exp $ >> 9 * >> 10 * Authors: Pedro Roque <pedro_m@yahoo.com> >> 11 * >> 12 * This program is free software; you can redistribute it and/or >> 13 * modify it under the terms of the GNU General Public License >> 14 * as published by the Free Software Foundation; either version >> 15 * 2 of the License, or (at your option) any later version. 10 */ 16 */ 11 17 12 /* 18 /* 13 * Changes: 19 * Changes: 14 * 20 * 15 * Vince Laviano (vince@cs.stanford.edu) 21 * Vince Laviano (vince@cs.stanford.edu) 16 May 2001 16 * - Removed unused variable 'inet6_proto 22 * - Removed unused variable 'inet6_protocol_base' 17 * - Modified inet6_del_protocol() to cor 23 * - Modified inet6_del_protocol() to correctly maintain copy bit. 18 */ 24 */ 19 #include <linux/module.h> << 20 #include <linux/netdevice.h> << 21 #include <linux/spinlock.h> << 22 #include <net/protocol.h> << 23 << 24 #if IS_ENABLED(CONFIG_IPV6) << 25 struct inet6_protocol __rcu *inet6_protos[MAX_ << 26 EXPORT_SYMBOL(inet6_protos); << 27 << 28 int inet6_add_protocol(const struct inet6_prot << 29 { << 30 return !cmpxchg((const struct inet6_pr << 31 NULL, prot) ? 0 : -1; << 32 } << 33 EXPORT_SYMBOL(inet6_add_protocol); << 34 << 35 int inet6_del_protocol(const struct inet6_prot << 36 { << 37 int ret; << 38 25 39 ret = (cmpxchg((const struct inet6_pro !! 26 #include <linux/errno.h> 40 prot, NULL) == prot) ? !! 27 #include <linux/types.h> >> 28 #include <linux/socket.h> >> 29 #include <linux/sockios.h> >> 30 #include <linux/sched.h> >> 31 #include <linux/net.h> >> 32 #include <linux/in6.h> >> 33 #include <linux/netdevice.h> >> 34 #include <linux/if_arp.h> >> 35 #include <linux/brlock.h> 41 36 42 synchronize_net(); !! 37 #include <net/sock.h> >> 38 #include <net/snmp.h> 43 39 44 return ret; !! 40 #include <net/ipv6.h> 45 } !! 41 #include <net/protocol.h> 46 EXPORT_SYMBOL(inet6_del_protocol); << 47 #endif << 48 42 49 const struct net_offload __rcu *inet6_offloads !! 43 struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; 50 EXPORT_SYMBOL(inet6_offloads); << 51 44 52 int inet6_add_offload(const struct net_offload !! 45 void inet6_add_protocol(struct inet6_protocol *prot) 53 { 46 { 54 return !cmpxchg((const struct net_offl !! 47 unsigned char hash; 55 NULL, prot) ? 0 : -1; !! 48 struct inet6_protocol *p2; >> 49 >> 50 hash = prot->protocol & (MAX_INET_PROTOS - 1); >> 51 br_write_lock_bh(BR_NETPROTO_LOCK); >> 52 prot->next = inet6_protos[hash]; >> 53 inet6_protos[hash] = prot; >> 54 prot->copy = 0; >> 55 >> 56 /* >> 57 * Set the copy bit if we need to. >> 58 */ >> 59 >> 60 p2 = (struct inet6_protocol *) prot->next; >> 61 while(p2 != NULL) { >> 62 if (p2->protocol == prot->protocol) { >> 63 prot->copy = 1; >> 64 break; >> 65 } >> 66 p2 = (struct inet6_protocol *) p2->next; >> 67 } >> 68 br_write_unlock_bh(BR_NETPROTO_LOCK); 56 } 69 } 57 EXPORT_SYMBOL(inet6_add_offload); << 58 70 59 int inet6_del_offload(const struct net_offload !! 71 /* >> 72 * Remove a protocol from the hash tables. >> 73 */ >> 74 >> 75 int inet6_del_protocol(struct inet6_protocol *prot) 60 { 76 { 61 int ret; !! 77 struct inet6_protocol *p; 62 !! 78 struct inet6_protocol *lp = NULL; 63 ret = (cmpxchg((const struct net_offlo !! 79 unsigned char hash; 64 prot, NULL) == prot) ? !! 80 65 !! 81 hash = prot->protocol & (MAX_INET_PROTOS - 1); 66 synchronize_net(); !! 82 br_write_lock_bh(BR_NETPROTO_LOCK); 67 !! 83 if (prot == inet6_protos[hash]) { 68 return ret; !! 84 inet6_protos[hash] = (struct inet6_protocol *) inet6_protos[hash]->next; >> 85 br_write_unlock_bh(BR_NETPROTO_LOCK); >> 86 return(0); >> 87 } >> 88 >> 89 p = (struct inet6_protocol *) inet6_protos[hash]; >> 90 >> 91 if (p != NULL && p->protocol == prot->protocol) >> 92 lp = p; >> 93 >> 94 while(p != NULL) { >> 95 /* >> 96 * We have to worry if the protocol being deleted is >> 97 * the last one on the list, then we may need to reset >> 98 * someone's copied bit. >> 99 */ >> 100 if (p->next != NULL && p->next == prot) { >> 101 /* >> 102 * if we are the last one with this protocol and >> 103 * there is a previous one, reset its copy bit. >> 104 */ >> 105 if (prot->copy == 0 && lp != NULL) >> 106 lp->copy = 0; >> 107 p->next = prot->next; >> 108 br_write_unlock_bh(BR_NETPROTO_LOCK); >> 109 return(0); >> 110 } >> 111 if (p->next != NULL && p->next->protocol == prot->protocol) >> 112 lp = p->next; >> 113 >> 114 p = (struct inet6_protocol *) p->next; >> 115 } >> 116 br_write_unlock_bh(BR_NETPROTO_LOCK); >> 117 return(-1); 69 } 118 } 70 EXPORT_SYMBOL(inet6_del_offload); << 71 119
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.