/** 

  * enum sock_type - Socket types 

  * @SOCK_STREAM: stream (connection) socket 

  * @SOCK_DGRAM: datagram (conn.less) socket 

  * @SOCK_RAW: raw socket 

  * @SOCK_RDM: reliably-delivered message 

  * @SOCK_SEQPACKET: sequential packet socket 

  * @SOCK_DCCP: Datagram Congestion Control Protocol socket 

  * @SOCK_PACKET: linux specific way of getting packets at the dev level. 

  * 
  For writing rarp and other similar things on the user level. 

  * 

  * When adding some new socket type please 

  * grep ARCH_HAS_SOCKET_TYPE include/asm-* /socket.h, at least MIPS 

  * overrides this enum for binary compat reasons. 

  */ 

 enum sock_type { 

SOCK_STREAM 
  = 1, 

SOCK_DGRAM 
  = 2, 

SOCK_RAW 
  = 3, 

SOCK_RDM 
  = 4, 

SOCK_SEQPACKET 
 = 5, 

SOCK_DCCP 
  = 6, 

SOCK_PACKET 
  = 10, 

 }; 



 #define SOCK_MAX (SOCK_PACKET + 1) 

 /* Mask which covers at least up to SOCK_MASK-1.  The 

  * remaining bits are used as flags. */ 
#define SOCK_TYPE_MASK 0xf



/* This is used to register socket interfaces for IP protocols.  */
 struct inet_protosw {
struct list_head list;


         /* These two fields form the lookup key.  */
unsigned short type;   /* This is the 2nd argument to socket(2). */
unsigned short protocol; /* This is the L4 protocol number.  */


struct proto  *prot;
const struct proto_ops *ops;
   
unsigned char  flags;      /* See INET_PROTOSW_* below.  */
 };
 #define INET_PROTOSW_REUSE 0x01     /* Are ports automatically reusable? */
 #define INET_PROTOSW_PERMANENT 0x02  /* Permanent protocols are unremovable. */
 #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
void inet_register_protosw(struct inet_protosw *p)
 {
struct list_head *lh;
struct inet_protosw *answer;
int protocol = p->protocol;
struct list_head *last_perm;


spin_lock_bh(&inetsw_lock);


if (p->type >= SOCK_MAX)
goto out_illegal;


/* If we are trying to override a permanent protocol, bail. */
last_perm = &inetsw[p->type];
list_for_each(lh, &inetsw[p->type]) {
answer = list_entry(lh, struct inet_protosw, list);
/* Check only the non-wild match. */
if ((INET_PROTOSW_PERMANENT & answer->flags) == 0)
break;
if (protocol == answer->protocol)
goto out_permanent;
last_perm = lh;
}


/* Add the new entry after the last permanent entry if any, so that
* the new entry does not override a permanent entry when matched with
* a wild-card protocol. But it is allowed to override any existing
* non-permanent entry.  This means that when we remove this entry, the
* system automatically returns to the old behavior.
*/
list_add_rcu(&p->list, last_perm);
 out:
spin_unlock_bh(&inetsw_lock);


return;


 out_permanent:
pr_err("Attempt to override permanent protocol %d\n", protocol);
goto out;


 out_illegal:
pr_err("Ignoring attempt to register invalid socket type %d\n",
      p->type);
goto out;
 }
 EXPORT_SYMBOL(inet_register_protosw);


 void inet_unregister_protosw(struct inet_protosw *p)
 {
if (INET_PROTOSW_PERMANENT & p->flags) {
pr_err("Attempt to unregister permanent protocol %d\n",
      p->protocol);
} else {
spin_lock_bh(&inetsw_lock);
list_del_rcu(&p->list);
spin_unlock_bh(&inetsw_lock);


synchronize_net();
}
 }
 EXPORT_SYMBOL(inet_unregister_protosw);
static struct inet_protosw inetsw_array[] =
 {
{
.type =       SOCK_STREAM,
.protocol =   IPPROTO_TCP,
.prot =       &tcp_prot,
.ops =        &inet_stream_ops,
.flags =      INET_PROTOSW_PERMANENT |
     INET_PROTOSW_ICSK,
},


{
.type =       SOCK_DGRAM,
.protocol =   IPPROTO_UDP,
.prot =       &udp_prot,
.ops =        &inet_dgram_ops,
.flags =      INET_PROTOSW_PERMANENT,
        },


        {
.type =       SOCK_DGRAM,
.protocol =   IPPROTO_ICMP,
.prot =       &ping_prot,
.ops =        &inet_dgram_ops,
.flags =      INET_PROTOSW_REUSE,
        },


        {
      .type =       SOCK_RAW,
      .protocol =   IPPROTO_IP, /* wild card */
      .prot =       &raw_prot,
      .ops =        &inet_sockraw_ops,
      .flags =      INET_PROTOSW_REUSE,
        }
 };


 #define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)
static struct inet_protosw sctp_seqpacket_protosw = {
.type       = SOCK_SEQPACKET,
.protocol   = IPPROTO_SCTP,
.prot       = &sctp_prot,
.ops        = &inet_seqpacket_ops,
.flags      = SCTP_PROTOSW_FLAG
 };
 static struct inet_protosw sctp_stream_protosw = {
.type       = SOCK_STREAM,
.protocol   = IPPROTO_SCTP,
.prot       = &sctp_prot,
.ops        = &inet_seqpacket_ops,
.flags      = SCTP_PROTOSW_FLAG
 };
 static struct inet_protosw udplite4_protosw = {
.type =  SOCK_DGRAM,
.protocol  =  IPPROTO_UDPLITE,
.prot =  &udplite_prot,
.ops =  &inet_dgram_ops,
.flags  =  INET_PROTOSW_PERMANENT,
 };