asmlinkage long sys_socket (int family, int type, int protocol) { int retval; struct socket *sock; retval = sock_create (family, type, protocol, &sock); if (retval < 0) goto out; retval = sock_map_fd(sock); 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) { int i; struct socket *sock; /* * Check protocol is in range */ if(family<0 || family>=NPROTO) return -EINVAL; ..... net_family_read_lock(); if (net_families[family] == NULL) { i = -EINVAL; goto out; } /* * 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. */ if (!(sock = sock_alloc ())) { printk(KERN_WARNING "socket: no more sockets

"); i = -ENFILE; /* Not exactly a match, but its the closest posix thing */ goto out; } sock->type = type; if ((i = net_families[family]-> create(sock, protocol) ) < 0) { sock_release(sock); goto out; } *res = sock; out: net_family_read_unlock(); return i; } /** * 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 = get_empty_inode(); if (!inode) return NULL; sock = socki_lookup (inode); inode->i_mode = S_IFSOCK|S_IRWXUGO; inode->i_sock = 1; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; sock->inode = inode; init_waitqueue_head(&sock->wait); sock->fasync_list = NULL; sock->state = SS_UNCONNECTED; sock->flags = 0; sock->ops = NULL; sock->sk = NULL; sock->file = NULL; sockets_in_use[smp_processor_id()].counter++; return sock; } extern __inline__ struct socket * socki_lookup (struct inode *inode) { return &inode->u.socket_i; } /* * Obtains the first available file descriptor and sets it up for use. * * This functions creates file structure and maps it to fd space * of current process. On success it returns file descriptor * and file struct implicitly stored in sock->file. * Note that another thread may close file descriptor before we return * from this function. We use the fact that now we do not refer * to socket after mapping. If one day we will need it, this * function will inincrement ref. count on file by 1. * * In any case returned fd MAY BE not valid! * This race condition is inavoidable * with shared fd spaces, we cannot solve is inside kernel, * but we take care of internal coherence yet. */ static int sock_map_fd (struct socket *sock) { int fd; /* * Find a file descriptor suitable for return to the user. */ fd = get_unused_fd(); if (fd >= 0) { struct file *file = get_empty_filp(); if (!file) { put_unused_fd(fd); fd = -ENFILE; goto out; } file->f_dentry = d_alloc_root(sock->inode); /* MOUNT_REWRITE: set to sockfs internal vfsmnt */ file->f_vfsmnt = NULL; if (!file->f_dentry) { put_filp(file); put_unused_fd(fd); fd = -ENOMEM; goto out; } sock->file = file; file->f_op = & socket_file_ops ; file->f_mode = 3; file->f_flags = O_RDWR; file->f_pos = 0; fd_install(fd, file); } out: return fd; } /* * Socket files have a set of 'special' operations as well as the generic file ones. Th ese don't appear * in the operation structures but are done directly via the socketcall() multiplexor. */ static struct file_operations socket_file_ops = { llseek: sock_lseek, read: sock_read, write: sock_write, poll: sock_poll, ioctl: sock_ioctl, mmap: sock_mmap, open: sock_no_open, /* special open code to disallow open via /proc */ release: sock_close, fasync: sock_fasync, readv: sock_readv, writev: sock_writev };