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 * INET protocol dispatch tables. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Version: $Id: protocol.c,v 1.14 2001/05/18 02:25:49 davem Exp $ 91da177e4SLinus Torvalds * 10*02c30a84SJesper Juhl * Authors: Ross Biro 111da177e4SLinus Torvalds * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * Fixes: 141da177e4SLinus Torvalds * Alan Cox : Ahah! udp icmp errors don't work because 151da177e4SLinus Torvalds * udp_err is never called! 161da177e4SLinus Torvalds * Alan Cox : Added new fields for init and ready for 171da177e4SLinus Torvalds * proper fragmentation (_NO_ 4K limits!) 181da177e4SLinus Torvalds * Richard Colella : Hang on hash collision 191da177e4SLinus Torvalds * Vince Laviano : Modified inet_del_protocol() to correctly 201da177e4SLinus Torvalds * maintain copy bit. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 231da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 241da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 251da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 261da177e4SLinus Torvalds */ 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <asm/uaccess.h> 291da177e4SLinus Torvalds #include <asm/system.h> 301da177e4SLinus Torvalds #include <linux/module.h> 311da177e4SLinus Torvalds #include <linux/types.h> 321da177e4SLinus Torvalds #include <linux/kernel.h> 331da177e4SLinus Torvalds #include <linux/sched.h> 341da177e4SLinus Torvalds #include <linux/string.h> 351da177e4SLinus Torvalds #include <linux/config.h> 361da177e4SLinus Torvalds #include <linux/socket.h> 371da177e4SLinus Torvalds #include <linux/in.h> 381da177e4SLinus Torvalds #include <linux/inet.h> 391da177e4SLinus Torvalds #include <linux/netdevice.h> 401da177e4SLinus Torvalds #include <linux/timer.h> 411da177e4SLinus Torvalds #include <net/ip.h> 421da177e4SLinus Torvalds #include <net/protocol.h> 431da177e4SLinus Torvalds #include <net/tcp.h> 441da177e4SLinus Torvalds #include <linux/skbuff.h> 451da177e4SLinus Torvalds #include <net/sock.h> 461da177e4SLinus Torvalds #include <net/icmp.h> 471da177e4SLinus Torvalds #include <net/udp.h> 481da177e4SLinus Torvalds #include <net/ipip.h> 491da177e4SLinus Torvalds #include <linux/igmp.h> 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds struct net_protocol *inet_protos[MAX_INET_PROTOS]; 521da177e4SLinus Torvalds static DEFINE_SPINLOCK(inet_proto_lock); 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds /* 551da177e4SLinus Torvalds * Add a protocol handler to the hash tables 561da177e4SLinus Torvalds */ 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds int inet_add_protocol(struct net_protocol *prot, unsigned char protocol) 591da177e4SLinus Torvalds { 601da177e4SLinus Torvalds int hash, ret; 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds hash = protocol & (MAX_INET_PROTOS - 1); 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds spin_lock_bh(&inet_proto_lock); 651da177e4SLinus Torvalds if (inet_protos[hash]) { 661da177e4SLinus Torvalds ret = -1; 671da177e4SLinus Torvalds } else { 681da177e4SLinus Torvalds inet_protos[hash] = prot; 691da177e4SLinus Torvalds ret = 0; 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds spin_unlock_bh(&inet_proto_lock); 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds return ret; 741da177e4SLinus Torvalds } 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds /* 771da177e4SLinus Torvalds * Remove a protocol from the hash tables. 781da177e4SLinus Torvalds */ 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds int inet_del_protocol(struct net_protocol *prot, unsigned char protocol) 811da177e4SLinus Torvalds { 821da177e4SLinus Torvalds int hash, ret; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds hash = protocol & (MAX_INET_PROTOS - 1); 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds spin_lock_bh(&inet_proto_lock); 871da177e4SLinus Torvalds if (inet_protos[hash] == prot) { 881da177e4SLinus Torvalds inet_protos[hash] = NULL; 891da177e4SLinus Torvalds ret = 0; 901da177e4SLinus Torvalds } else { 911da177e4SLinus Torvalds ret = -1; 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds spin_unlock_bh(&inet_proto_lock); 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds synchronize_net(); 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds return ret; 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds EXPORT_SYMBOL(inet_add_protocol); 1011da177e4SLinus Torvalds EXPORT_SYMBOL(inet_del_protocol); 102