Linux TCP/IP socket 实现

简要记录函数调用流程



SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
int retval;
struct socket *sock;
int flags;


/* Check the SOCK_* constants for consistency.  */
BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);


flags = type & ~SOCK_TYPE_MASK;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
return -EINVAL;
type &= SOCK_TYPE_MASK;


if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;


retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;


retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;


out:
/* It may be already another descriptor 8) Not kernel problem. */
return retval;


out_release:
sock_release(sock);
return retval;
}


int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
}
EXPORT_SYMBOL(sock_create);




int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
{
int err;
struct socket *sock;
const struct net_proto_family *pf;


/*
*      Check protocol is in range
*/
if (family < 0 || family >= NPROTO)
return -EAFNOSUPPORT;
if (type < 0 || type >= SOCK_MAX)
return -EINVAL;


/* Compatibility.


  This uglymoron is moved from INET layer to here to avoid
  deadlock in module load.
*/
if (family == PF_INET && type == SOCK_PACKET) {
pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
    current->comm);
family = PF_PACKET;
}


err = security_socket_create(family, type, protocol, kern);
if (err)
return err;


/*
* Allocate the socket and allow the family to set things up. if
* the protocol is 0, the family is instructed to select an appropriate
* default.
*/
sock = sock_alloc();
if (!sock) {
net_warn_ratelimited("socket: no more sockets\n");
return -ENFILE;/* Not exactly a match, but its the
  closest posix thing */
}


sock->type = type;


#ifdef CONFIG_MODULES
/* Attempt to load a protocol module if the find failed.
*
* 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
* requested real, full-featured networking support upon configuration.
* Otherwise module support will break!
*/
if (rcu_access_pointer(net_families[family]) == NULL)
request_module("net-pf-%d", family);
#endif


rcu_read_lock();
pf = rcu_dereference(net_families[family]);
err = -EAFNOSUPPORT;
if (!pf)
goto out_release;


/*
* We will call the ->create function, that possibly is in a loadable
* module, so we have to bump that loadable module refcnt first.
*/
if (!try_module_get(pf->owner))
goto out_release;


/* Now protected by module ref count */
rcu_read_unlock();


err = pf->create(net, sock, protocol, kern);
if (err < 0)
goto out_module_put;


/*
* Now to bump the refcnt of the [loadable] module that owns this
* socket at sock_release time we decrement its refcnt.
*/
if (!try_module_get(sock->ops->owner))
goto out_module_busy;


/*
* Now that we're done with the ->create function, the [loadable]
* module can have its refcnt decremented
*/
module_put(pf->owner);
err = security_socket_post_create(sock, family, type, protocol, kern);
if (err)
goto out_sock_release;
*res = sock;


return 0;


out_module_busy:
err = -EAFNOSUPPORT;
out_module_put:
sock->ops = NULL;
module_put(pf->owner);
out_sock_release:
sock_release(sock);
return err;


out_release:
rcu_read_unlock();
goto out_sock_release;
}





/**
 * sock_alloc - allocate a socket
 *
 * Allocate a new inode and socket object. The two are bound together
 * and initialised. The socket is then returned. If we are out of inodes
 * NULL is returned.
 */


struct socket *sock_alloc(void)
{
struct inode *inode;
struct socket *sock;


inode = new_inode_pseudo(sock_mnt->mnt_sb);
if (!inode)
return NULL;


sock = SOCKET_I(inode);


kmemcheck_annotate_bitfield(sock, type);
inode->i_ino = get_next_ino();
inode->i_mode = S_IFSOCK | S_IRWXUGO;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
inode->i_op = &sockfs_inode_ops;


this_cpu_add(sockets_in_use, 1);
return sock;
}


static DEFINE_SPINLOCK(net_family_lock);
static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;



/* Supported address families. */
#define AF_UNSPEC 0
#define AF_UNIX 1/* Unix domain sockets */
#define AF_LOCAL 1/* POSIX name for AF_UNIX */
#define AF_INET 2/* Internet IP Protocol */
#define AF_AX25 3/* Amateur Radio AX.25 */
#define AF_IPX 4/* Novell IPX */
#define AF_APPLETALK 5/* AppleTalk DDP */
#define AF_NETROM 6/* Amateur Radio NET/ROM */
#define AF_BRIDGE 7/* Multiprotocol bridge */
#define AF_ATMPVC 8/* ATM PVCs */
#define AF_X25 9/* Reserved for X.25 project */
#define AF_INET6 10/* IP version 6 */
#define AF_ROSE 11/* Amateur Radio X.25 PLP */
#define AF_DECnet 12/* Reserved for DECnet project */
#define AF_NETBEUI 13/* Reserved for 802.2LLC project*/
#define AF_SECURITY 14/* Security callback pseudo AF */
#define AF_KEY 15      /* PF_KEY key management API */
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */
#define AF_PACKET 17/* Packet family */
#define AF_ASH 18/* Ash */
#define AF_ECONET 19/* Acorn Econet */
#define AF_ATMSVC 20/* ATM SVCs */
#define AF_RDS 21/* RDS sockets */
#define AF_SNA 22/* Linux SNA Project (nutters!) */
#define AF_IRDA 23/* IRDA sockets */
#define AF_PPPOX 24/* PPPoX sockets */
#define AF_WANPIPE 25/* Wanpipe API Sockets */
#define AF_LLC 26/* Linux LLC */
#define AF_IB 27/* Native InfiniBand address */
#define AF_MPLS 28/* MPLS */
#define AF_CAN 29/* Controller Area Network      */
#define AF_TIPC 30/* TIPC sockets */
#define AF_BLUETOOTH 31/* Bluetooth sockets */
#define AF_IUCV 32/* IUCV sockets */
#define AF_RXRPC 33/* RxRPC sockets */
#define AF_ISDN 34/* mISDN sockets */
#define AF_PHONET 35/* Phonet sockets */
#define AF_IEEE802154 36/* IEEE802154 sockets */
#define AF_CAIF 37/* CAIF sockets */
#define AF_ALG 38/* Algorithm sockets */
#define AF_NFC 39/* NFC sockets */
#define AF_VSOCK 40/* vSockets */
#define AF_KCM 41/* Kernel Connection Multiplexor*/
#define AF_QIPCRTR 42/* Qualcomm IPC Router          */


#define AF_MAX 43/* For now.. */


/* Protocol families, same as address families. */
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_LOCAL AF_LOCAL
#define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
#define PF_APPLETALK AF_APPLETALK
#define PF_NETROMAF_NETROM
#define PF_BRIDGE AF_BRIDGE
#define PF_ATMPVC AF_ATMPVC
#define PF_X25 AF_X25
#define PF_INET6 AF_INET6
#define PF_ROSE AF_ROSE
#define PF_DECnet AF_DECnet
#define PF_NETBEUI AF_NETBEUI
#define PF_SECURITY AF_SECURITY
#define PF_KEY AF_KEY
#define PF_NETLINK AF_NETLINK
#define PF_ROUTE AF_ROUTE
#define PF_PACKET AF_PACKET
#define PF_ASH AF_ASH
#define PF_ECONET AF_ECONET
#define PF_ATMSVC AF_ATMSVC
#define PF_RDS AF_RDS
#define PF_SNA AF_SNA
#define PF_IRDA AF_IRDA
#define PF_PPPOX AF_PPPOX
#define PF_WANPIPE AF_WANPIPE
#define PF_LLC AF_LLC
#define PF_IB AF_IB
#define PF_MPLS AF_MPLS
#define PF_CAN AF_CAN
#define PF_TIPC AF_TIPC
#define PF_BLUETOOTH AF_BLUETOOTH
#define PF_IUCV AF_IUCV
#define PF_RXRPC AF_RXRPC
#define PF_ISDN AF_ISDN
#define PF_PHONET AF_PHONET
#define PF_IEEE802154 AF_IEEE802154
#define PF_CAIF AF_CAIF
#define PF_ALG AF_ALG
#define PF_NFC AF_NFC
#define PF_VSOCK AF_VSOCK
#define PF_KCM AF_KCM
#define PF_QIPCRTR AF_QIPCRTR
#define PF_MAX AF_MAX


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值