xref: /linux/net/ipv6/protocol.c (revision 41135cc8)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * INET		An implementation of the TCP/IP protocol suite for the LINUX
31da177e4SLinus Torvalds  *		operating system.  INET is implemented using the  BSD Socket
41da177e4SLinus Torvalds  *		interface as the means of communication with the user level.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *		PF_INET6 protocol dispatch tables.
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * Authors:	Pedro Roque	<roque@di.fc.ul.pt>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
111da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
121da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
131da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds /*
171da177e4SLinus Torvalds  *      Changes:
181da177e4SLinus Torvalds  *
191da177e4SLinus Torvalds  *      Vince Laviano (vince@cs.stanford.edu)       16 May 2001
201da177e4SLinus Torvalds  *      - Removed unused variable 'inet6_protocol_base'
211da177e4SLinus Torvalds  *      - Modified inet6_del_protocol() to correctly maintain copy bit.
221da177e4SLinus Torvalds  */
23fa1a9c68SAlexey Dobriyan #include <linux/module.h>
241da177e4SLinus Torvalds #include <linux/netdevice.h>
25fa1a9c68SAlexey Dobriyan #include <linux/spinlock.h>
261da177e4SLinus Torvalds #include <net/protocol.h>
271da177e4SLinus Torvalds 
28*41135cc8SAlexey Dobriyan const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
291da177e4SLinus Torvalds static DEFINE_SPINLOCK(inet6_proto_lock);
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 
32*41135cc8SAlexey Dobriyan int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds 	int ret, hash = protocol & (MAX_INET_PROTOS - 1);
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds 	spin_lock_bh(&inet6_proto_lock);
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds 	if (inet6_protos[hash]) {
391da177e4SLinus Torvalds 		ret = -1;
401da177e4SLinus Torvalds 	} else {
411da177e4SLinus Torvalds 		inet6_protos[hash] = prot;
421da177e4SLinus Torvalds 		ret = 0;
431da177e4SLinus Torvalds 	}
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds 	spin_unlock_bh(&inet6_proto_lock);
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds 	return ret;
481da177e4SLinus Torvalds }
491da177e4SLinus Torvalds 
507159039aSYOSHIFUJI Hideaki EXPORT_SYMBOL(inet6_add_protocol);
517159039aSYOSHIFUJI Hideaki 
521da177e4SLinus Torvalds /*
531da177e4SLinus Torvalds  *	Remove a protocol from the hash tables.
541da177e4SLinus Torvalds  */
551da177e4SLinus Torvalds 
56*41135cc8SAlexey Dobriyan int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol)
571da177e4SLinus Torvalds {
581da177e4SLinus Torvalds 	int ret, hash = protocol & (MAX_INET_PROTOS - 1);
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds 	spin_lock_bh(&inet6_proto_lock);
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds 	if (inet6_protos[hash] != prot) {
631da177e4SLinus Torvalds 		ret = -1;
641da177e4SLinus Torvalds 	} else {
651da177e4SLinus Torvalds 		inet6_protos[hash] = NULL;
661da177e4SLinus Torvalds 		ret = 0;
671da177e4SLinus Torvalds 	}
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	spin_unlock_bh(&inet6_proto_lock);
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds 	synchronize_net();
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds 	return ret;
741da177e4SLinus Torvalds }
757159039aSYOSHIFUJI Hideaki 
767159039aSYOSHIFUJI Hideaki EXPORT_SYMBOL(inet6_del_protocol);
77