Blame view

net/socket.c 55.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * NET		An implementation of the SOCKET network access protocol.
   *
   * Version:	@(#)socket.c	1.1.93	18/02/95
   *
   * Authors:	Orest Zborowski, <obz@Kodak.COM>
02c30a84e   Jesper Juhl   [PATCH] update Ro...
7
   *		Ross Biro
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *
   * Fixes:
   *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
   *					shutdown()
   *		Alan Cox	:	verify_area() fixes
   *		Alan Cox	:	Removed DDI
   *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
   *		Alan Cox	:	Moved a load of checks to the very
   *					top level.
   *		Alan Cox	:	Move address structures to/from user
   *					mode above the protocol layers.
   *		Rob Janssen	:	Allow 0 length sends.
   *		Alan Cox	:	Asynchronous I/O support (cribbed from the
   *					tty drivers).
   *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
   *		Jeff Uphoff	:	Made max number of sockets command-line
   *					configurable.
   *		Matti Aarnio	:	Made the number of sockets dynamic,
   *					to be allocated when needed, and mr.
   *					Uphoff's max is used as max to be
   *					allowed to allocate.
   *		Linus		:	Argh. removed all the socket allocation
   *					altogether: it's in the inode now.
   *		Alan Cox	:	Made sock_alloc()/sock_release() public
   *					for NetROM and future kernel nfsd type
   *					stuff.
   *		Alan Cox	:	sendmsg/recvmsg basics.
   *		Tom Dyas	:	Export net symbols.
   *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
   *		Alan Cox	:	Added thread locking to sys_* calls
   *					for sockets. May have errors at the
   *					moment.
   *		Kevin Buhr	:	Fixed the dumb errors in the above.
   *		Andi Kleen	:	Some small cleanups, optimizations,
   *					and fixed a copy_from_user() bug.
   *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
89bddce58   Stephen Hemminger   [NET] socket: cod...
45
   *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
55
   *					protocol-independent
   *
   *
   *		This program is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
   *
   *
   *	This module is effectively the top level interface to the BSD socket
89bddce58   Stephen Hemminger   [NET] socket: cod...
56
   *	paradigm.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
   *
   *	Based upon Swansea University Computer Society NET3.039
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
  #include <linux/socket.h>
  #include <linux/file.h>
  #include <linux/net.h>
  #include <linux/interrupt.h>
55737fda0   Stephen Hemminger   [NET]: socket fam...
65
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
  #include <linux/netdevice.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
69
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  #include <linux/wanrouter.h>
  #include <linux/if_bridge.h>
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
72
73
  #include <linux/if_frad.h>
  #include <linux/if_vlan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
  #include <linux/init.h>
  #include <linux/poll.h>
  #include <linux/cache.h>
  #include <linux/module.h>
  #include <linux/highmem.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/syscalls.h>
  #include <linux/compat.h>
  #include <linux/kmod.h>
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
84
  #include <linux/audit.h>
d86b5e0e6   Adrian Bunk   [PATCH] net/: fix...
85
  #include <linux/wireless.h>
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
86
  #include <linux/nsproxy.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
90
91
92
93
94
95
96
  
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
  
  #include <net/compat.h>
  
  #include <net/sock.h>
  #include <linux/netfilter.h>
  
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
027445c37   Badari Pulavarty   [PATCH] Vectorize...
97
98
99
100
  static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
  			 unsigned long nr_segs, loff_t pos);
  static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
  			  unsigned long nr_segs, loff_t pos);
89bddce58   Stephen Hemminger   [NET] socket: cod...
101
  static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
  
  static int sock_close(struct inode *inode, struct file *file);
  static unsigned int sock_poll(struct file *file,
  			      struct poll_table_struct *wait);
89bddce58   Stephen Hemminger   [NET] socket: cod...
106
  static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
107
108
  #ifdef CONFIG_COMPAT
  static long compat_sock_ioctl(struct file *file,
89bddce58   Stephen Hemminger   [NET] socket: cod...
109
  			      unsigned int cmd, unsigned long arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
110
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  static int sock_fasync(int fd, struct file *filp, int on);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
  static ssize_t sock_sendpage(struct file *file, struct page *page,
  			     int offset, size_t size, loff_t *ppos, int more);
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
114
115
116
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
  			        struct pipe_inode_info *pipe, size_t len,
  				unsigned int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
121
  /*
   *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
   *	in the operation structures but are done directly via the socketcall() multiplexor.
   */
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
122
  static const struct file_operations socket_file_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
127
128
  	.owner =	THIS_MODULE,
  	.llseek =	no_llseek,
  	.aio_read =	sock_aio_read,
  	.aio_write =	sock_aio_write,
  	.poll =		sock_poll,
  	.unlocked_ioctl = sock_ioctl,
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
129
130
131
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = compat_sock_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
  	.mmap =		sock_mmap,
  	.open =		sock_no_open,	/* special open code to disallow open via /proc */
  	.release =	sock_close,
  	.fasync =	sock_fasync,
5274f052e   Jens Axboe   [PATCH] Introduce...
136
137
  	.sendpage =	sock_sendpage,
  	.splice_write = generic_splice_sendpage,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
138
  	.splice_read =	sock_splice_read,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
  };
  
  /*
   *	The protocol list. Each protocol is registered in here.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  static DEFINE_SPINLOCK(net_family_lock);
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
145
  static const struct net_proto_family *net_families[NPROTO] __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
  /*
   *	Statistics counters of the socket lists
   */
  
  static DEFINE_PER_CPU(int, sockets_in_use) = 0;
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
154
155
156
   * Support routines.
   * Move socket addresses back and forth across the kernel/user
   * divide and look after the messy bits.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
158
  #define MAX_SOCK_ADDR	128		/* 108 for Unix domain -
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
  					   16 for IP, 16 for IPX,
  					   24 for IPv6,
89bddce58   Stephen Hemminger   [NET] socket: cod...
161
  					   about 80 for AX.25
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
  					   must be at least one bigger than
  					   the AF_UNIX size (see net/unix/af_unix.c
89bddce58   Stephen Hemminger   [NET] socket: cod...
164
  					   :unix_mkname()).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  					 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
166

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
171
172
173
174
175
176
177
178
179
  /**
   *	move_addr_to_kernel	-	copy a socket address into kernel space
   *	@uaddr: Address in user space
   *	@kaddr: Address in kernel space
   *	@ulen: Length in user space
   *
   *	The address is copied into kernel space. If the provided address is
   *	too long an error code of -EINVAL is returned. If the copy gives
   *	invalid addresses -EFAULT is returned. On a success 0 is returned.
   */
  
  int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
180
  	if (ulen < 0 || ulen > MAX_SOCK_ADDR)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
182
  	if (ulen == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  		return 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
184
  	if (copy_from_user(kaddr, uaddr, ulen))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
186
  	return audit_sockaddr(ulen, kaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  }
  
  /**
   *	move_addr_to_user	-	copy an address to user space
   *	@kaddr: kernel space address
   *	@klen: length of address in kernel
   *	@uaddr: user space address
   *	@ulen: pointer to user length field
   *
   *	The value pointed to by ulen on entry is the buffer length available.
   *	This is overwritten with the buffer space used. -EINVAL is returned
   *	if an overlong buffer is specified or a negative buffer size. -EFAULT
   *	is returned if either the buffer or the length field are not
   *	accessible.
   *	After copying the data up to the limit the user specifies, the true
   *	length of the data is written over the length limit the user
   *	specified. Zero is returned for a success.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
205
206
207
  
  int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
  		      int __user *ulen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
  {
  	int err;
  	int len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
211
212
  	err = get_user(len, ulen);
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
214
215
216
  	if (len > klen)
  		len = klen;
  	if (len < 0 || len > MAX_SOCK_ADDR)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
218
  	if (len) {
d6fe3945b   Steve Grubb   [PATCH] sockaddr ...
219
220
  		if (audit_sockaddr(klen, kaddr))
  			return -ENOMEM;
89bddce58   Stephen Hemminger   [NET] socket: cod...
221
  		if (copy_to_user(uaddr, kaddr, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
  			return -EFAULT;
  	}
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
225
226
  	 *      "fromlen shall refer to the value before truncation.."
  	 *                      1003.1g
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
  	 */
  	return __put_user(klen, ulen);
  }
  
  #define SOCKFS_MAGIC 0x534F434B
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
232
  static struct kmem_cache *sock_inode_cachep __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
  
  static struct inode *sock_alloc_inode(struct super_block *sb)
  {
  	struct socket_alloc *ei;
89bddce58   Stephen Hemminger   [NET] socket: cod...
237

e94b17660   Christoph Lameter   [PATCH] slab: rem...
238
  	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
  	if (!ei)
  		return NULL;
  	init_waitqueue_head(&ei->socket.wait);
89bddce58   Stephen Hemminger   [NET] socket: cod...
242

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
248
  	ei->socket.fasync_list = NULL;
  	ei->socket.state = SS_UNCONNECTED;
  	ei->socket.flags = 0;
  	ei->socket.ops = NULL;
  	ei->socket.sk = NULL;
  	ei->socket.file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
254
255
256
257
  
  	return &ei->vfs_inode;
  }
  
  static void sock_destroy_inode(struct inode *inode)
  {
  	kmem_cache_free(sock_inode_cachep,
  			container_of(inode, struct socket_alloc, vfs_inode));
  }
4ba9b9d0b   Christoph Lameter   Slab API: remove ...
258
  static void init_once(struct kmem_cache *cachep, void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
260
  	struct socket_alloc *ei = (struct socket_alloc *)foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261

a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
262
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
264

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  static int init_inodecache(void)
  {
  	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
89bddce58   Stephen Hemminger   [NET] socket: cod...
268
269
270
271
272
  					      sizeof(struct socket_alloc),
  					      0,
  					      (SLAB_HWCACHE_ALIGN |
  					       SLAB_RECLAIM_ACCOUNT |
  					       SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
273
  					      init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
276
277
278
279
280
281
282
283
  	if (sock_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static struct super_operations sockfs_ops = {
  	.alloc_inode =	sock_alloc_inode,
  	.destroy_inode =sock_destroy_inode,
  	.statfs =	simple_statfs,
  };
454e2398b   David Howells   [PATCH] VFS: Perm...
284
  static int sockfs_get_sb(struct file_system_type *fs_type,
89bddce58   Stephen Hemminger   [NET] socket: cod...
285
286
  			 int flags, const char *dev_name, void *data,
  			 struct vfsmount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  {
454e2398b   David Howells   [PATCH] VFS: Perm...
288
289
  	return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
  			     mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  }
ba89966c1   Eric Dumazet   [NET]: use __read...
291
  static struct vfsmount *sock_mnt __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
296
297
  
  static struct file_system_type sock_fs_type = {
  	.name =		"sockfs",
  	.get_sb =	sockfs_get_sb,
  	.kill_sb =	kill_anon_super,
  };
89bddce58   Stephen Hemminger   [NET] socket: cod...
298

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
  static int sockfs_delete_dentry(struct dentry *dentry)
  {
304e61e6f   Eric Dumazet   [PATCH] net: don'...
301
302
303
304
305
306
307
308
  	/*
  	 * At creation time, we pretended this dentry was hashed
  	 * (by clearing DCACHE_UNHASHED bit in d_flags)
  	 * At delete time, we restore the truth : not hashed.
  	 * (so that dput() can proceed correctly)
  	 */
  	dentry->d_flags |= DCACHE_UNHASHED;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  }
c23fbb6bc   Eric Dumazet   VFS: delay the de...
310
311
312
313
314
315
316
317
318
  
  /*
   * sockfs_dname() is called from d_path().
   */
  static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
  {
  	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
  				dentry->d_inode->i_ino);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  static struct dentry_operations sockfs_dentry_operations = {
89bddce58   Stephen Hemminger   [NET] socket: cod...
320
  	.d_delete = sockfs_delete_dentry,
c23fbb6bc   Eric Dumazet   VFS: delay the de...
321
  	.d_dname  = sockfs_dname,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
  };
  
  /*
   *	Obtains the first available file descriptor and sets it up for use.
   *
39d8c1b6f   David S. Miller   [NET]: Do not los...
327
328
   *	These functions create file structures and maps them to fd space
   *	of the current process. On success it returns file descriptor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
333
334
335
336
337
338
339
   *	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 increment ref. count on file by 1.
   *
   *	In any case returned fd MAY BE not valid!
   *	This race condition is unavoidable
   *	with shared fd spaces, we cannot solve it inside kernel,
   *	but we take care of internal coherence yet.
   */
39d8c1b6f   David S. Miller   [NET]: Do not los...
340
  static int sock_alloc_fd(struct file **filep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  {
  	int fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
  
  	fd = get_unused_fd();
39d8c1b6f   David S. Miller   [NET]: Do not los...
345
  	if (likely(fd >= 0)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  		struct file *file = get_empty_filp();
39d8c1b6f   David S. Miller   [NET]: Do not los...
347
348
  		*filep = file;
  		if (unlikely(!file)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  			put_unused_fd(fd);
39d8c1b6f   David S. Miller   [NET]: Do not los...
350
  			return -ENFILE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  		}
39d8c1b6f   David S. Miller   [NET]: Do not los...
352
353
354
355
  	} else
  		*filep = NULL;
  	return fd;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356

39d8c1b6f   David S. Miller   [NET]: Do not los...
357
358
  static int sock_attach_fd(struct socket *sock, struct file *file)
  {
ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
359
  	struct dentry *dentry;
c23fbb6bc   Eric Dumazet   VFS: delay the de...
360
  	struct qstr name = { .name = "" };
39d8c1b6f   David S. Miller   [NET]: Do not los...
361

ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
362
363
  	dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
  	if (unlikely(!dentry))
39d8c1b6f   David S. Miller   [NET]: Do not los...
364
  		return -ENOMEM;
ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
365
  	dentry->d_op = &sockfs_dentry_operations;
304e61e6f   Eric Dumazet   [PATCH] net: don'...
366
367
368
369
370
  	/*
  	 * We dont want to push this dentry into global dentry hash table.
  	 * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
  	 * This permits a working /proc/$pid/fd/XXX on sockets
  	 */
ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
371
372
  	dentry->d_flags &= ~DCACHE_UNHASHED;
  	d_instantiate(dentry, SOCK_INODE(sock));
39d8c1b6f   David S. Miller   [NET]: Do not los...
373
374
  
  	sock->file = file;
ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
375
376
377
  	init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
  		  &socket_file_ops);
  	SOCK_INODE(sock)->i_fop = &socket_file_ops;
39d8c1b6f   David S. Miller   [NET]: Do not los...
378
379
380
  	file->f_flags = O_RDWR;
  	file->f_pos = 0;
  	file->private_data = sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381

39d8c1b6f   David S. Miller   [NET]: Do not los...
382
383
384
385
386
387
388
389
390
391
392
393
394
  	return 0;
  }
  
  int sock_map_fd(struct socket *sock)
  {
  	struct file *newfile;
  	int fd = sock_alloc_fd(&newfile);
  
  	if (likely(fd >= 0)) {
  		int err = sock_attach_fd(sock, newfile);
  
  		if (unlikely(err < 0)) {
  			put_filp(newfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  			put_unused_fd(fd);
39d8c1b6f   David S. Miller   [NET]: Do not los...
396
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  		}
39d8c1b6f   David S. Miller   [NET]: Do not los...
398
  		fd_install(fd, newfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
  	return fd;
  }
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
402
403
  static struct socket *sock_from_file(struct file *file, int *err)
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
404
405
  	if (file->f_op == &socket_file_ops)
  		return file->private_data;	/* set in sock_map_fd */
23bb80d21   Eric Dumazet   [NET]: cleanup so...
406
407
  	*err = -ENOTSOCK;
  	return NULL;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
408
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  /**
   *	sockfd_lookup	- 	Go from a file number to its socket slot
   *	@fd: file handle
   *	@err: pointer to an error code return
   *
   *	The file handle passed in is locked and the socket it is bound
   *	too is returned. If an error occurs the err pointer is overwritten
   *	with a negative errno code and NULL is returned. The function checks
   *	for both invalid handles and passing a handle which is not a socket.
   *
   *	On a success the socket object pointer is returned.
   */
  
  struct socket *sockfd_lookup(int fd, int *err)
  {
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
426
427
  	file = fget(fd);
  	if (!file) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
  		*err = -EBADF;
  		return NULL;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
431

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
432
433
  	sock = sock_from_file(file, err);
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  		fput(file);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
435
436
  	return sock;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
438
439
440
441
  static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
  {
  	struct file *file;
  	struct socket *sock;
3672558c6   Hua Zhong   [NET]: sockfd_loo...
442
  	*err = -EBADF;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
443
444
445
446
447
448
  	file = fget_light(fd, fput_needed);
  	if (file) {
  		sock = sock_from_file(file, err);
  		if (sock)
  			return sock;
  		fput_light(file, *fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  	}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
450
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
  }
  
  /**
   *	sock_alloc	-	allocate a socket
89bddce58   Stephen Hemminger   [NET] socket: cod...
455
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
458
459
460
461
462
   *	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.
   */
  
  static struct socket *sock_alloc(void)
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
463
464
  	struct inode *inode;
  	struct socket *sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
470
  
  	inode = new_inode(sock_mnt->mnt_sb);
  	if (!inode)
  		return NULL;
  
  	sock = SOCKET_I(inode);
89bddce58   Stephen Hemminger   [NET] socket: cod...
471
  	inode->i_mode = S_IFSOCK | S_IRWXUGO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
481
482
483
484
  	inode->i_uid = current->fsuid;
  	inode->i_gid = current->fsgid;
  
  	get_cpu_var(sockets_in_use)++;
  	put_cpu_var(sockets_in_use);
  	return sock;
  }
  
  /*
   *	In theory you can't get an open on this inode, but /proc provides
   *	a back door. Remember to keep it shut otherwise you'll let the
   *	creepy crawlies in.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
485

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
  {
  	return -ENXIO;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
490
  const struct file_operations bad_sock_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
497
498
499
500
  	.owner = THIS_MODULE,
  	.open = sock_no_open,
  };
  
  /**
   *	sock_release	-	close a socket
   *	@sock: socket to close
   *
   *	The socket is released from the protocol stack if it has a release
   *	callback, and the inode is then released if the socket is bound to
89bddce58   Stephen Hemminger   [NET] socket: cod...
501
   *	an inode not a file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
503

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
  void sock_release(struct socket *sock)
  {
  	if (sock->ops) {
  		struct module *owner = sock->ops->owner;
  
  		sock->ops->release(sock);
  		sock->ops = NULL;
  		module_put(owner);
  	}
  
  	if (sock->fasync_list)
  		printk(KERN_ERR "sock_release: fasync list not empty!
  ");
  
  	get_cpu_var(sockets_in_use)--;
  	put_cpu_var(sockets_in_use);
  	if (!sock->file) {
  		iput(SOCK_INODE(sock));
  		return;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
524
  	sock->file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
526
  static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
  				 struct msghdr *msg, size_t size)
  {
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
  	int err;
  
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
  
  	err = security_socket_sendmsg(sock, msg, size);
  	if (err)
  		return err;
  
  	return sock->ops->sendmsg(iocb, sock, msg, size);
  }
  
  int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
  
  	init_sync_kiocb(&iocb, NULL);
  	iocb.private = &siocb;
  	ret = __sock_sendmsg(&iocb, sock, msg, size);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
  
  int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
  		   struct kvec *vec, size_t num, size_t size)
  {
  	mm_segment_t oldfs = get_fs();
  	int result;
  
  	set_fs(KERNEL_DS);
  	/*
  	 * the following is safe, since for compiler definitions of kvec and
  	 * iovec are identical, yielding the same in-core layout and alignment
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
569
  	msg->msg_iov = (struct iovec *)vec;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
571
572
573
574
  	msg->msg_iovlen = num;
  	result = sock_sendmsg(sock, msg, size);
  	set_fs(oldfs);
  	return result;
  }
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  /*
   * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
   */
  void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
  	struct sk_buff *skb)
  {
  	ktime_t kt = skb->tstamp;
  
  	if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
  		struct timeval tv;
  		/* Race occurred between timestamp enabling and packet
  		   receiving.  Fill in the current time for now. */
  		if (kt.tv64 == 0)
  			kt = ktime_get_real();
  		skb->tstamp = kt;
  		tv = ktime_to_timeval(kt);
  		put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv);
  	} else {
  		struct timespec ts;
  		/* Race occurred between timestamp enabling and packet
  		   receiving.  Fill in the current time for now. */
  		if (kt.tv64 == 0)
  			kt = ktime_get_real();
  		skb->tstamp = kt;
  		ts = ktime_to_timespec(kt);
  		put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts);
  	}
  }
7c81fd8bf   Arnaldo Carvalho de Melo   [SOCKET]: Export ...
603
  EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
89bddce58   Stephen Hemminger   [NET] socket: cod...
604
  static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  				 struct msghdr *msg, size_t size, int flags)
  {
  	int err;
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
  
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
  	si->flags = flags;
  
  	err = security_socket_recvmsg(sock, msg, size, flags);
  	if (err)
  		return err;
  
  	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
622
  int sock_recvmsg(struct socket *sock, struct msghdr *msg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
626
627
  		 size_t size, int flags)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
89bddce58   Stephen Hemminger   [NET] socket: cod...
628
  	init_sync_kiocb(&iocb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
630
631
632
633
634
  	iocb.private = &siocb;
  	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
635
636
  int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
  		   struct kvec *vec, size_t num, size_t size, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
639
640
641
642
643
644
645
  {
  	mm_segment_t oldfs = get_fs();
  	int result;
  
  	set_fs(KERNEL_DS);
  	/*
  	 * the following is safe, since for compiler definitions of kvec and
  	 * iovec are identical, yielding the same in-core layout and alignment
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
646
  	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
650
651
652
653
654
655
  	result = sock_recvmsg(sock, msg, size, flags);
  	set_fs(oldfs);
  	return result;
  }
  
  static void sock_aio_dtor(struct kiocb *iocb)
  {
  	kfree(iocb->private);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
656
657
  static ssize_t sock_sendpage(struct file *file, struct page *page,
  			     int offset, size_t size, loff_t *ppos, int more)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
  	struct socket *sock;
  	int flags;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
661
662
663
664
665
666
667
668
  	sock = file->private_data;
  
  	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
  	if (more)
  		flags |= MSG_MORE;
  
  	return sock->ops->sendpage(sock, page, offset, size, flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669

9c55e01c0   Jens Axboe   [TCP]: Splice rec...
670
671
672
673
674
675
676
677
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
  			        struct pipe_inode_info *pipe, size_t len,
  				unsigned int flags)
  {
  	struct socket *sock = file->private_data;
  
  	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
678
  static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89bddce58   Stephen Hemminger   [NET] socket: cod...
679
  					 struct sock_iocb *siocb)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
680
681
682
683
684
  {
  	if (!is_sync_kiocb(iocb)) {
  		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
  		if (!siocb)
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
  		iocb->ki_dtor = sock_aio_dtor;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
688
  	siocb->kiocb = iocb;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
689
690
  	iocb->private = siocb;
  	return siocb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
692
  static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
693
694
  		struct file *file, const struct iovec *iov,
  		unsigned long nr_segs)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
695
696
697
698
  {
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699

89bddce58   Stephen Hemminger   [NET] socket: cod...
700
701
  	for (i = 0; i < nr_segs; i++)
  		size += iov[i].iov_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
703
704
705
706
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
707
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
708
709
710
711
712
  	msg->msg_iovlen = nr_segs;
  	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
  
  	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
713
714
  static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
  				unsigned long nr_segs, loff_t pos)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
715
716
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
  	if (pos != 0)
  		return -ESPIPE;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
719
720
  
  	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  		return 0;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
722
723
  
  	x = alloc_sock_iocb(iocb, &siocb);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
724
725
  	if (!x)
  		return -ENOMEM;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
726
  	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
728
  static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
729
730
  			struct file *file, const struct iovec *iov,
  			unsigned long nr_segs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  {
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
732
733
734
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735

89bddce58   Stephen Hemminger   [NET] socket: cod...
736
737
  	for (i = 0; i < nr_segs; i++)
  		size += iov[i].iov_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
739
740
741
742
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
743
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
744
745
746
747
  	msg->msg_iovlen = nr_segs;
  	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
  	if (sock->type == SOCK_SEQPACKET)
  		msg->msg_flags |= MSG_EOR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
749
  	return __sock_sendmsg(iocb, sock, msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
751
752
  static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
  			  unsigned long nr_segs, loff_t pos)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
753
754
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
756
757
  	if (pos != 0)
  		return -ESPIPE;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
758

027445c37   Badari Pulavarty   [PATCH] Vectorize...
759
  	x = alloc_sock_iocb(iocb, &siocb);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
760
761
  	if (!x)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762

027445c37   Badari Pulavarty   [PATCH] Vectorize...
763
  	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
768
  /*
   * Atomic setting of ioctl hooks to avoid race
   * with module unload.
   */
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
769
  static DEFINE_MUTEX(br_ioctl_mutex);
881d966b4   Eric W. Biederman   [NET]: Make the d...
770
  static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771

881d966b4   Eric W. Biederman   [NET]: Make the d...
772
  void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
774
  	mutex_lock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
  	br_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
776
  	mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
778

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
  EXPORT_SYMBOL(brioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
780
  static DEFINE_MUTEX(vlan_ioctl_mutex);
881d966b4   Eric W. Biederman   [NET]: Make the d...
781
  static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782

881d966b4   Eric W. Biederman   [NET]: Make the d...
783
  void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
785
  	mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
  	vlan_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
787
  	mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
789

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
  EXPORT_SYMBOL(vlan_ioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
791
  static DEFINE_MUTEX(dlci_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
792
  static int (*dlci_ioctl_hook) (unsigned int, void __user *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793

89bddce58   Stephen Hemminger   [NET] socket: cod...
794
  void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
796
  	mutex_lock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  	dlci_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
798
  	mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
800

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
802
803
804
805
806
807
808
809
810
  EXPORT_SYMBOL(dlci_ioctl_set);
  
  /*
   *	With an ioctl, arg may well be a user mode pointer, but we don't know
   *	what to do with it - that's up to the protocol still.
   */
  
  static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
  {
  	struct socket *sock;
881d966b4   Eric W. Biederman   [NET]: Make the d...
811
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
  	void __user *argp = (void __user *)arg;
  	int pid, err;
881d966b4   Eric W. Biederman   [NET]: Make the d...
814
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815

b69aee04f   Eric Dumazet   [NET]: Use file->...
816
  	sock = file->private_data;
881d966b4   Eric W. Biederman   [NET]: Make the d...
817
818
  	sk = sock->sk;
  	net = sk->sk_net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
820
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  	} else
d86b5e0e6   Adrian Bunk   [PATCH] net/: fix...
822
  #ifdef CONFIG_WIRELESS_EXT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
824
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
  	} else
89bddce58   Stephen Hemminger   [NET] socket: cod...
826
827
  #endif				/* CONFIG_WIRELESS_EXT */
  		switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
831
832
833
834
835
836
  		case FIOSETOWN:
  		case SIOCSPGRP:
  			err = -EFAULT;
  			if (get_user(pid, (int __user *)argp))
  				break;
  			err = f_setown(sock->file, pid, 1);
  			break;
  		case FIOGETOWN:
  		case SIOCGPGRP:
609d7fa95   Eric W. Biederman   [PATCH] file: mod...
837
  			err = put_user(f_getown(sock->file),
89bddce58   Stephen Hemminger   [NET] socket: cod...
838
  				       (int __user *)argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
841
842
843
844
845
846
  			break;
  		case SIOCGIFBR:
  		case SIOCSIFBR:
  		case SIOCBRADDBR:
  		case SIOCBRDELBR:
  			err = -ENOPKG;
  			if (!br_ioctl_hook)
  				request_module("bridge");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
847
  			mutex_lock(&br_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
848
  			if (br_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
849
  				err = br_ioctl_hook(net, cmd, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
850
  			mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
854
855
856
  			break;
  		case SIOCGIFVLAN:
  		case SIOCSIFVLAN:
  			err = -ENOPKG;
  			if (!vlan_ioctl_hook)
  				request_module("8021q");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
857
  			mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
  			if (vlan_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
859
  				err = vlan_ioctl_hook(net, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
860
  			mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
863
864
865
866
867
868
  		case SIOCADDDLCI:
  		case SIOCDELDLCI:
  			err = -ENOPKG;
  			if (!dlci_ioctl_hook)
  				request_module("dlci");
  
  			if (dlci_ioctl_hook) {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
869
  				mutex_lock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  				err = dlci_ioctl_hook(cmd, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
871
  				mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
875
  			}
  			break;
  		default:
  			err = sock->ops->ioctl(sock, cmd, arg);
b5e5fa5e0   Christoph Hellwig   [NET]: Add a dev_...
876
877
878
879
880
881
  
  			/*
  			 * If this ioctl is unknown try to hand it down
  			 * to the NIC driver.
  			 */
  			if (err == -ENOIOCTLCMD)
881d966b4   Eric W. Biederman   [NET]: Make the d...
882
  				err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
884
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
888
889
890
891
  	return err;
  }
  
  int sock_create_lite(int family, int type, int protocol, struct socket **res)
  {
  	int err;
  	struct socket *sock = NULL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
892

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
894
895
896
897
898
899
900
901
  	err = security_socket_create(family, type, protocol, 1);
  	if (err)
  		goto out;
  
  	sock = sock_alloc();
  	if (!sock) {
  		err = -ENOMEM;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  	sock->type = type;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
903
904
905
  	err = security_socket_post_create(sock, family, type, protocol, 1);
  	if (err)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
908
  out:
  	*res = sock;
  	return err;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
909
910
911
912
  out_release:
  	sock_release(sock);
  	sock = NULL;
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
  }
  
  /* No kernel lock held - perfect */
89bddce58   Stephen Hemminger   [NET] socket: cod...
916
  static unsigned int sock_poll(struct file *file, poll_table *wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
  {
  	struct socket *sock;
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
921
  	 *      We can't return errors to poll, so it's either yes or no.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
  	 */
b69aee04f   Eric Dumazet   [NET]: Use file->...
923
  	sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
925
  	return sock->ops->poll(file, sock, wait);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
926
  static int sock_mmap(struct file *file, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
  {
b69aee04f   Eric Dumazet   [NET]: Use file->...
928
  	struct socket *sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
  
  	return sock->ops->mmap(file, sock, vma);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
932
  static int sock_close(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
934
  {
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
935
936
  	 *      It was possible the inode is NULL we were
  	 *      closing an unfinished socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
938
  	if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  		printk(KERN_DEBUG "sock_close: NULL inode
  ");
  		return 0;
  	}
  	sock_fasync(-1, filp, 0);
  	sock_release(SOCKET_I(inode));
  	return 0;
  }
  
  /*
   *	Update the socket async list
   *
   *	Fasync_list locking strategy.
   *
   *	1. fasync_list is modified only under process context socket lock
   *	   i.e. under semaphore.
   *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
   *	   or under socket lock.
   *	3. fasync_list can be used from softirq context, so that
   *	   modification under socket lock have to be enhanced with
   *	   write_lock_bh(&sk->sk_callback_lock).
   *							--ANK (990710)
   */
  
  static int sock_fasync(int fd, struct file *filp, int on)
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
965
  	struct fasync_struct *fa, *fna = NULL, **prev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
  	struct socket *sock;
  	struct sock *sk;
89bddce58   Stephen Hemminger   [NET] socket: cod...
968
  	if (on) {
8b3a70058   Kris Katterjohn   [NET]: Remove mor...
969
  		fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
970
  		if (fna == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
  			return -ENOMEM;
  	}
b69aee04f   Eric Dumazet   [NET]: Use file->...
973
  	sock = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974

89bddce58   Stephen Hemminger   [NET] socket: cod...
975
976
  	sk = sock->sk;
  	if (sk == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
979
980
981
  		kfree(fna);
  		return -EINVAL;
  	}
  
  	lock_sock(sk);
89bddce58   Stephen Hemminger   [NET] socket: cod...
982
  	prev = &(sock->fasync_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983

89bddce58   Stephen Hemminger   [NET] socket: cod...
984
985
  	for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
  		if (fa->fa_file == filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
987
988
  	if (on) {
  		if (fa != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  			write_lock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
990
  			fa->fa_fd = fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
993
994
995
  			write_unlock_bh(&sk->sk_callback_lock);
  
  			kfree(fna);
  			goto out;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
996
997
998
999
  		fna->fa_file = filp;
  		fna->fa_fd = fd;
  		fna->magic = FASYNC_MAGIC;
  		fna->fa_next = sock->fasync_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
  		write_lock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1001
  		sock->fasync_list = fna;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  		write_unlock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1003
1004
  	} else {
  		if (fa != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
  			write_lock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1006
  			*prev = fa->fa_next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
  			write_unlock_bh(&sk->sk_callback_lock);
  			kfree(fa);
  		}
  	}
  
  out:
  	release_sock(sock->sk);
  	return 0;
  }
  
  /* This function may be called only under socket lock or callback_lock */
  
  int sock_wake_async(struct socket *sock, int how, int band)
  {
  	if (!sock || !sock->fasync_list)
  		return -1;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1023
  	switch (how) {
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1024
  	case SOCK_WAKE_WAITD:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
1027
  		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
  			break;
  		goto call_kill;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1028
  	case SOCK_WAKE_SPACE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
1031
  		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
  			break;
  		/* fall through */
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1032
  	case SOCK_WAKE_IO:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1033
  call_kill:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
1035
  		__kill_fasync(sock->fasync_list, SIGIO, band);
  		break;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1036
  	case SOCK_WAKE_URG:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
1039
1040
  		__kill_fasync(sock->fasync_list, SIGURG, band);
  	}
  	return 0;
  }
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1041
  static int __sock_create(struct net *net, int family, int type, int protocol,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1042
  			 struct socket **res, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
  {
  	int err;
  	struct socket *sock;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1046
  	const struct net_proto_family *pf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1049
  	 *      Check protocol is in range
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  	 */
  	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) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1062
  		static int warned;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
1064
  		if (!warned) {
  			warned = 1;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1065
1066
1067
  			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)
  ",
  			       current->comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
1069
1070
1071
1072
1073
1074
  		}
  		family = PF_PACKET;
  	}
  
  	err = security_socket_create(family, type, protocol, kern);
  	if (err)
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1075

55737fda0   Stephen Hemminger   [NET]: socket fam...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
  	/*
  	 *	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) {
  		if (net_ratelimit())
  			printk(KERN_WARNING "socket: no more sockets
  ");
  		return -ENFILE;	/* Not exactly a match, but its the
  				   closest posix thing */
  	}
  
  	sock->type = type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
  #if defined(CONFIG_KMOD)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1092
1093
1094
  	/* Attempt to load a protocol module if the find failed.
  	 *
  	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
1096
1097
  	 * requested real, full-featured networking support upon configuration.
  	 * Otherwise module support will break!
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1098
  	if (net_families[family] == NULL)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1099
  		request_module("net-pf-%d", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  #endif
55737fda0   Stephen Hemminger   [NET]: socket fam...
1101
1102
1103
1104
1105
  	rcu_read_lock();
  	pf = rcu_dereference(net_families[family]);
  	err = -EAFNOSUPPORT;
  	if (!pf)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
1107
1108
1109
1110
  
  	/*
  	 * We will call the ->create function, that possibly is in a loadable
  	 * module, so we have to bump that loadable module refcnt first.
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1111
  	if (!try_module_get(pf->owner))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  		goto out_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1113
1114
  	/* Now protected by module ref count */
  	rcu_read_unlock();
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1115
  	err = pf->create(net, sock, protocol);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1116
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1117
  		goto out_module_put;
a79af59ef   Frank Filz   [NET]: Fix module...
1118

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
1121
1122
  	/*
  	 * Now to bump the refcnt of the [loadable] module that owns this
  	 * socket at sock_release time we decrement its refcnt.
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1123
1124
  	if (!try_module_get(sock->ops->owner))
  		goto out_module_busy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
1127
1128
  	/*
  	 * Now that we're done with the ->create function, the [loadable]
  	 * module can have its refcnt decremented
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1129
  	module_put(pf->owner);
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1130
1131
  	err = security_socket_post_create(sock, family, type, protocol, kern);
  	if (err)
3b1855255   Herbert Xu   [NET]: Fix unbala...
1132
  		goto out_sock_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1133
  	*res = sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134

55737fda0   Stephen Hemminger   [NET]: socket fam...
1135
1136
1137
1138
  	return 0;
  
  out_module_busy:
  	err = -EAFNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
  out_module_put:
55737fda0   Stephen Hemminger   [NET]: socket fam...
1140
1141
1142
  	sock->ops = NULL;
  	module_put(pf->owner);
  out_sock_release:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
  	sock_release(sock);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1144
1145
1146
1147
1148
  	return err;
  
  out_release:
  	rcu_read_unlock();
  	goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
1152
  }
  
  int sock_create(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1153
  	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
1155
1156
1157
  }
  
  int sock_create_kern(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1158
  	return __sock_create(&init_net, family, type, protocol, res, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
  }
  
  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;
  }
  
  /*
   *	Create a pair of connected sockets.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1186
1187
  asmlinkage long sys_socketpair(int family, int type, int protocol,
  			       int __user *usockvec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
  {
  	struct socket *sock1, *sock2;
  	int fd1, fd2, err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1191
  	struct file *newfile1, *newfile2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
  
  	/*
  	 * Obtain the first socket and check if the underlying protocol
  	 * supports the socketpair call.
  	 */
  
  	err = sock_create(family, type, protocol, &sock1);
  	if (err < 0)
  		goto out;
  
  	err = sock_create(family, type, protocol, &sock2);
  	if (err < 0)
  		goto out_release_1;
  
  	err = sock1->ops->socketpair(sock1, sock2);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1207
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  		goto out_release_both;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1209
  	fd1 = sock_alloc_fd(&newfile1);
bf3c23d17   David S. Miller   [NET]: Fix error ...
1210
1211
  	if (unlikely(fd1 < 0)) {
  		err = fd1;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1212
  		goto out_release_both;
bf3c23d17   David S. Miller   [NET]: Fix error ...
1213
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214

db3495099   Al Viro   [PATCH] AUDIT_FD_...
1215
1216
  	fd2 = sock_alloc_fd(&newfile2);
  	if (unlikely(fd2 < 0)) {
bf3c23d17   David S. Miller   [NET]: Fix error ...
1217
  		err = fd2;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1218
1219
  		put_filp(newfile1);
  		put_unused_fd(fd1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
  		goto out_release_both;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1221
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222

db3495099   Al Viro   [PATCH] AUDIT_FD_...
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
  	err = sock_attach_fd(sock1, newfile1);
  	if (unlikely(err < 0)) {
  		goto out_fd2;
  	}
  
  	err = sock_attach_fd(sock2, newfile2);
  	if (unlikely(err < 0)) {
  		fput(newfile1);
  		goto out_fd1;
  	}
  
  	err = audit_fd_pair(fd1, fd2);
  	if (err < 0) {
  		fput(newfile1);
  		fput(newfile2);
  		goto out_fd;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240

db3495099   Al Viro   [PATCH] AUDIT_FD_...
1241
1242
  	fd_install(fd1, newfile1);
  	fd_install(fd2, newfile2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
  	/* fd1 and fd2 may be already another descriptors.
  	 * Not kernel problem.
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1246
  	err = put_user(fd1, &usockvec[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247
1248
1249
1250
1251
1252
1253
1254
  	if (!err)
  		err = put_user(fd2, &usockvec[1]);
  	if (!err)
  		return 0;
  
  	sys_close(fd2);
  	sys_close(fd1);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
  out_release_both:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1256
  	sock_release(sock2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
  out_release_1:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1258
  	sock_release(sock1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
1260
  out:
  	return err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
  
  out_fd2:
  	put_filp(newfile1);
  	sock_release(sock1);
  out_fd1:
  	put_filp(newfile2);
  	sock_release(sock2);
  out_fd:
  	put_unused_fd(fd1);
  	put_unused_fd(fd2);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
  /*
   *	Bind a name to a socket. Nothing much to do here since it's
   *	the protocol's responsibility to handle the local address.
   *
   *	We move the socket address to kernel space before we call
   *	the protocol layer (having also checked the address is ok).
   */
  
  asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1285
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286

89bddce58   Stephen Hemminger   [NET] socket: cod...
1287
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
e71a4783a   Stephen Hemminger   [NET] core: white...
1288
  	if (sock) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1289
1290
1291
1292
1293
  		err = move_addr_to_kernel(umyaddr, addrlen, address);
  		if (err >= 0) {
  			err = security_socket_bind(sock,
  						   (struct sockaddr *)address,
  						   addrlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1294
1295
  			if (!err)
  				err = sock->ops->bind(sock,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1296
1297
  						      (struct sockaddr *)
  						      address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
  		}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1299
  		fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1300
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
1302
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
1304
1305
1306
1307
  /*
   *	Perform a listen. Basically, we allow the protocol to do anything
   *	necessary for a listen, and if that works, we mark the socket as
   *	ready for listening.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
  asmlinkage long sys_listen(int fd, int backlog)
  {
  	struct socket *sock;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1311
  	int err, fput_needed;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1312
  	int somaxconn;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1313
1314
1315
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock) {
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1316
1317
1318
  		somaxconn = sock->sk->sk_net->sysctl_somaxconn;
  		if ((unsigned)backlog > somaxconn)
  			backlog = somaxconn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
1320
  
  		err = security_socket_listen(sock, backlog);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1321
1322
  		if (!err)
  			err = sock->ops->listen(sock, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1324
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
  /*
   *	For accept, we attempt to create a new socket, set up the link
   *	with the client, wake up the client, then return the new
   *	connected fd. We collect the address of the connector in kernel
   *	space and move it to user at the very end. This is unclean because
   *	we open the socket then return an error.
   *
   *	1003.1g adds the ability to recvmsg() to query connection pending
   *	status to recvmsg. We need to add that support in a way thats
   *	clean when we restucture accept also.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1339
1340
  asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
  			   int __user *upeer_addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
  {
  	struct socket *sock, *newsock;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1343
  	struct file *newfile;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1344
  	int err, len, newfd, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1346
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
1348
1349
1350
  	if (!sock)
  		goto out;
  
  	err = -ENFILE;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1351
  	if (!(newsock = sock_alloc()))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
1354
1355
  		goto out_put;
  
  	newsock->type = sock->type;
  	newsock->ops = sock->ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
1357
1358
1359
1360
  	/*
  	 * We don't need try_module_get here, as the listening socket (sock)
  	 * has the protocol module (sock->ops->owner) held.
  	 */
  	__module_get(newsock->ops->owner);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1361
1362
1363
  	newfd = sock_alloc_fd(&newfile);
  	if (unlikely(newfd < 0)) {
  		err = newfd;
9a1875e60   David S. Miller   [NET]: Fully fix ...
1364
1365
  		sock_release(newsock);
  		goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1366
1367
1368
1369
  	}
  
  	err = sock_attach_fd(newsock, newfile);
  	if (err < 0)
79f4f6428   Alexey Dobriyan   [NET]: Correct ac...
1370
  		goto out_fd_simple;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1371

a79af59ef   Frank Filz   [NET]: Fix module...
1372
1373
  	err = security_socket_accept(sock, newsock);
  	if (err)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1374
  		goto out_fd;
a79af59ef   Frank Filz   [NET]: Fix module...
1375

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
1377
  	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
  	if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1378
  		goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
1380
  
  	if (upeer_sockaddr) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1381
1382
  		if (newsock->ops->getname(newsock, (struct sockaddr *)address,
  					  &len, 2) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
  			err = -ECONNABORTED;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1384
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1386
1387
  		err = move_addr_to_user(address, len, upeer_sockaddr,
  					upeer_addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  		if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1389
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
1392
  	}
  
  	/* File flags are not inherited via accept() unlike another OSes. */
39d8c1b6f   David S. Miller   [NET]: Do not los...
1393
1394
  	fd_install(newfd, newfile);
  	err = newfd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
1396
1397
1398
  
  	security_socket_post_accept(sock, newsock);
  
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1399
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
1401
  out:
  	return err;
79f4f6428   Alexey Dobriyan   [NET]: Correct ac...
1402
1403
1404
1405
1406
  out_fd_simple:
  	sock_release(newsock);
  	put_filp(newfile);
  	put_unused_fd(newfd);
  	goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1407
  out_fd:
9606a2163   David S. Miller   [NET]: Fix dentry...
1408
  	fput(newfile);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1409
  	put_unused_fd(newfd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410
1411
  	goto out_put;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
  /*
   *	Attempt to connect to a socket with the server address.  The address
   *	is in user space so we verify it is OK and move it to kernel space.
   *
   *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
   *	break bindings
   *
   *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
   *	other SEQPACKET protocols that take time to connect() as it doesn't
   *	include the -EINPROGRESS status for such sockets.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1423
1424
  asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
  			    int addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425
1426
1427
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1428
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1430
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431
1432
1433
1434
1435
  	if (!sock)
  		goto out;
  	err = move_addr_to_kernel(uservaddr, addrlen, address);
  	if (err < 0)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1436
1437
  	err =
  	    security_socket_connect(sock, (struct sockaddr *)address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
  	if (err)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1440
  	err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441
1442
  				 sock->file->f_flags);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1443
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1444
1445
1446
1447
1448
1449
1450
1451
  out:
  	return err;
  }
  
  /*
   *	Get the local address ('name') of a socket object. Move the obtained
   *	name to user space.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1452
1453
  asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
  				int __user *usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
1455
1456
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1457
  	int len, err, fput_needed;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1458

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1459
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  	if (!sock)
  		goto out;
  
  	err = security_socket_getsockname(sock);
  	if (err)
  		goto out_put;
  
  	err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
  	if (err)
  		goto out_put;
  	err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
  
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1473
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
1476
1477
1478
1479
1480
1481
  out:
  	return err;
  }
  
  /*
   *	Get the remote address ('name') of a socket object. Move the obtained
   *	name to user space.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1482
1483
  asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
  				int __user *usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
1485
1486
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1487
  	int len, err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488

89bddce58   Stephen Hemminger   [NET] socket: cod...
1489
1490
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
1492
  		err = security_socket_getpeername(sock);
  		if (err) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1493
  			fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
1495
  			return err;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1496
1497
1498
  		err =
  		    sock->ops->getname(sock, (struct sockaddr *)address, &len,
  				       1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
  		if (!err)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1500
1501
  			err = move_addr_to_user(address, len, usockaddr,
  						usockaddr_len);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1502
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
1504
1505
1506
1507
1508
1509
1510
1511
  	}
  	return err;
  }
  
  /*
   *	Send a datagram to a given address. We move the address into kernel
   *	space and check the user space data area is readable before invoking
   *	the protocol.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1512
1513
1514
  asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
  			   unsigned flags, struct sockaddr __user *addr,
  			   int addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1515
1516
1517
1518
1519
1520
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
  	int err;
  	struct msghdr msg;
  	struct iovec iov;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1521
  	int fput_needed;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1522

de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1523
1524
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (!sock)
4387ff75f   David S. Miller   [NET]: Fix net/so...
1525
  		goto out;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1526

89bddce58   Stephen Hemminger   [NET] socket: cod...
1527
1528
1529
1530
1531
1532
1533
1534
  	iov.iov_base = buff;
  	iov.iov_len = len;
  	msg.msg_name = NULL;
  	msg.msg_iov = &iov;
  	msg.msg_iovlen = 1;
  	msg.msg_control = NULL;
  	msg.msg_controllen = 0;
  	msg.msg_namelen = 0;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1535
  	if (addr) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536
1537
1538
  		err = move_addr_to_kernel(addr, addr_len, address);
  		if (err < 0)
  			goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1539
1540
  		msg.msg_name = address;
  		msg.msg_namelen = addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
1542
1543
1544
1545
  	}
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
  	msg.msg_flags = flags;
  	err = sock_sendmsg(sock, &msg, len);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1546
  out_put:
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1547
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1548
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
1550
1551
1552
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1553
   *	Send a datagram down a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1555
  asmlinkage long sys_send(int fd, void __user *buff, size_t len, unsigned flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
1557
1558
1559
1560
  {
  	return sys_sendto(fd, buff, len, flags, NULL, 0);
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1561
   *	Receive a frame from the socket and optionally record the address of the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
1563
1564
   *	sender. We verify the buffers are writable and if needed move the
   *	sender address from kernel to user space.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1565
1566
1567
  asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
  			     unsigned flags, struct sockaddr __user *addr,
  			     int __user *addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
1569
1570
1571
1572
  {
  	struct socket *sock;
  	struct iovec iov;
  	struct msghdr msg;
  	char address[MAX_SOCK_ADDR];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1573
  	int err, err2;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1574
  	int fput_needed;
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1575
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
  	if (!sock)
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1577
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1578

89bddce58   Stephen Hemminger   [NET] socket: cod...
1579
1580
1581
1582
1583
1584
1585
1586
  	msg.msg_control = NULL;
  	msg.msg_controllen = 0;
  	msg.msg_iovlen = 1;
  	msg.msg_iov = &iov;
  	iov.iov_len = size;
  	iov.iov_base = ubuf;
  	msg.msg_name = address;
  	msg.msg_namelen = MAX_SOCK_ADDR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
1588
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1589
  	err = sock_recvmsg(sock, &msg, size, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590

89bddce58   Stephen Hemminger   [NET] socket: cod...
1591
1592
1593
1594
  	if (err >= 0 && addr != NULL) {
  		err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
  		if (err2 < 0)
  			err = err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
  	}
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1596
1597
  
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1598
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1599
1600
1601
1602
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1603
   *	Receive a datagram from a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1605
1606
  asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
  			 unsigned flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
1608
1609
1610
1611
1612
1613
1614
  {
  	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
  }
  
  /*
   *	Set a socket option. Because we don't know the option lengths we have
   *	to pass the user mode parameter for the protocols to sort out.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1615
1616
  asmlinkage long sys_setsockopt(int fd, int level, int optname,
  			       char __user *optval, int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1618
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
1620
1621
1622
  	struct socket *sock;
  
  	if (optlen < 0)
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1623
1624
1625
1626
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
  		err = security_socket_setsockopt(sock, level, optname);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1627
1628
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1631
1632
1633
  			err =
  			    sock_setsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1634
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1635
1636
1637
  			err =
  			    sock->ops->setsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1638
1639
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
1641
1642
1643
1644
1645
1646
1647
  	}
  	return err;
  }
  
  /*
   *	Get a socket option. Because we don't know the option lengths we have
   *	to pass a user mode parameter for the protocols to sort out.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1648
1649
  asmlinkage long sys_getsockopt(int fd, int level, int optname,
  			       char __user *optval, int __user *optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1651
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1653
1654
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1655
1656
1657
  		err = security_socket_getsockopt(sock, level, optname);
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
1659
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1660
1661
1662
  			err =
  			    sock_getsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1664
1665
1666
  			err =
  			    sock->ops->getsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1667
1668
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
1670
1671
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
1673
1674
1675
1676
1677
  /*
   *	Shutdown a socket.
   */
  
  asmlinkage long sys_shutdown(int fd, int how)
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1678
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1680
1681
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
  		err = security_socket_shutdown(sock, how);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1683
1684
1685
  		if (!err)
  			err = sock->ops->shutdown(sock, how);
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
1687
1688
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
1689
  /* A couple of helpful macros for getting the address of the 32/64 bit
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
1691
1692
1693
1694
   * fields which are the same type (int / unsigned) on our platforms.
   */
  #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
  #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
  #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
1696
1697
1698
1699
1700
  /*
   *	BSD sendmsg interface
   */
  
  asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1701
1702
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
1704
1705
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
  	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
b9d717a7b   Alex Williamson   [NET]: Make sure ...
1706
  	unsigned char ctl[sizeof(struct cmsghdr) + 20]
89bddce58   Stephen Hemminger   [NET] socket: cod...
1707
1708
  	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
  	/* 20 is size of ipv6_pktinfo */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709
1710
1711
  	unsigned char *ctl_buf = ctl;
  	struct msghdr msg_sys;
  	int err, ctl_len, iov_size, total_len;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1712
  	int fput_needed;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1713

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
1715
1716
1717
  	err = -EFAULT;
  	if (MSG_CMSG_COMPAT & flags) {
  		if (get_compat_msghdr(&msg_sys, msg_compat))
  			return -EFAULT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1718
1719
  	}
  	else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
  		return -EFAULT;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1721
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1722
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
1725
1726
1727
1728
  		goto out;
  
  	/* do not move before msg_sys is valid */
  	err = -EMSGSIZE;
  	if (msg_sys.msg_iovlen > UIO_MAXIOV)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1729
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
  	err = -ENOMEM;
  	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
  	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
  		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
  		if (!iov)
  			goto out_put;
  	}
  
  	/* This will also move the address data into kernel space */
  	if (MSG_CMSG_COMPAT & flags) {
  		err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
  	} else
  		err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1743
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1744
1745
1746
1747
1748
1749
1750
  		goto out_freeiov;
  	total_len = err;
  
  	err = -ENOBUFS;
  
  	if (msg_sys.msg_controllen > INT_MAX)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1751
  	ctl_len = msg_sys.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1752
  	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1753
1754
1755
  		err =
  		    cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
  						     sizeof(ctl));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756
1757
1758
  		if (err)
  			goto out_freeiov;
  		ctl_buf = msg_sys.msg_control;
8920e8f94   Al Viro   [PATCH] Fix 32bit...
1759
  		ctl_len = msg_sys.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
  	} else if (ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1761
  		if (ctl_len > sizeof(ctl)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1762
  			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1763
  			if (ctl_buf == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1764
1765
1766
1767
1768
1769
1770
1771
  				goto out_freeiov;
  		}
  		err = -EFAULT;
  		/*
  		 * Careful! Before this, msg_sys.msg_control contains a user pointer.
  		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
  		 * checking falls down on this.
  		 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1772
1773
  		if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
  				   ctl_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
  			goto out_freectl;
  		msg_sys.msg_control = ctl_buf;
  	}
  	msg_sys.msg_flags = flags;
  
  	if (sock->file->f_flags & O_NONBLOCK)
  		msg_sys.msg_flags |= MSG_DONTWAIT;
  	err = sock_sendmsg(sock, &msg_sys, total_len);
  
  out_freectl:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1784
  	if (ctl_buf != ctl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
1786
1787
1788
1789
  		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
  out_freeiov:
  	if (iov != iovstack)
  		sock_kfree_s(sock->sk, iov, iov_size);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1790
  	fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1791
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1792
1793
1794
1795
1796
1797
  	return err;
  }
  
  /*
   *	BSD recvmsg interface
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1798
1799
  asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
  			    unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1801
1802
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
1804
  	struct socket *sock;
  	struct iovec iovstack[UIO_FASTIOV];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1805
  	struct iovec *iov = iovstack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
1807
1808
  	struct msghdr msg_sys;
  	unsigned long cmsg_ptr;
  	int err, iov_size, total_len, len;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1809
  	int fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
1811
1812
1813
1814
1815
1816
  
  	/* kernel mode address */
  	char addr[MAX_SOCK_ADDR];
  
  	/* user mode address pointers */
  	struct sockaddr __user *uaddr;
  	int __user *uaddr_len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1817

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
1819
1820
  	if (MSG_CMSG_COMPAT & flags) {
  		if (get_compat_msghdr(&msg_sys, msg_compat))
  			return -EFAULT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1821
1822
1823
  	}
  	else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1825
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
1827
1828
1829
1830
1831
  	if (!sock)
  		goto out;
  
  	err = -EMSGSIZE;
  	if (msg_sys.msg_iovlen > UIO_MAXIOV)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1832
1833
  
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834
1835
1836
1837
1838
1839
1840
1841
1842
  	err = -ENOMEM;
  	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
  	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
  		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
  		if (!iov)
  			goto out_put;
  	}
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1843
1844
  	 *      Save the user-mode address (verify_iovec will change the
  	 *      kernel msghdr to use the kernel address space)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1846

cfcabdcc2   Stephen Hemminger   [NET]: sparse war...
1847
  	uaddr = (__force void __user *)msg_sys.msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848
1849
1850
1851
1852
1853
1854
  	uaddr_len = COMPAT_NAMELEN(msg);
  	if (MSG_CMSG_COMPAT & flags) {
  		err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
  	} else
  		err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
  	if (err < 0)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1855
  	total_len = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
1857
  
  	cmsg_ptr = (unsigned long)msg_sys.msg_control;
4a19542e5   Ulrich Drepper   O_CLOEXEC for SCM...
1858
  	msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1859

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
1861
1862
1863
1864
1865
1866
1867
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
  	err = sock_recvmsg(sock, &msg_sys, total_len, flags);
  	if (err < 0)
  		goto out_freeiov;
  	len = err;
  
  	if (uaddr != NULL) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1868
1869
  		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
  					uaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
1871
1872
  		if (err < 0)
  			goto out_freeiov;
  	}
37f7f421c   David S. Miller   [NET]: Do not lea...
1873
1874
  	err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT),
  			 COMPAT_FLAGS(msg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1875
1876
1877
  	if (err)
  		goto out_freeiov;
  	if (MSG_CMSG_COMPAT & flags)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1878
  		err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1879
1880
  				 &msg_compat->msg_controllen);
  	else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1881
  		err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
1883
1884
1885
1886
1887
1888
1889
1890
  				 &msg->msg_controllen);
  	if (err)
  		goto out_freeiov;
  	err = len;
  
  out_freeiov:
  	if (iov != iovstack)
  		sock_kfree_s(sock->sk, iov, iov_size);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1891
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1892
1893
1894
1895
1896
1897
1898
1899
  out:
  	return err;
  }
  
  #ifdef __ARCH_WANT_SYS_SOCKETCALL
  
  /* Argument list sizes for sys_socketcall */
  #define AL(x) ((x) * sizeof(unsigned long))
89bddce58   Stephen Hemminger   [NET] socket: cod...
1900
1901
1902
1903
1904
  static const unsigned char nargs[18]={
  	AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
  	AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
  	AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905
1906
1907
  #undef AL
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1908
   *	System call vectors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1909
1910
1911
   *
   *	Argument checking cleaned up. Saved 20% in size.
   *  This function doesn't need to set the kernel lock because
89bddce58   Stephen Hemminger   [NET] socket: cod...
1912
   *  it is set by the callees.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
1914
1915
1916
1917
   */
  
  asmlinkage long sys_socketcall(int call, unsigned long __user *args)
  {
  	unsigned long a[6];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1918
  	unsigned long a0, a1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1919
  	int err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1920
  	if (call < 1 || call > SYS_RECVMSG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
1922
1923
1924
1925
  		return -EINVAL;
  
  	/* copy_from_user should be SMP safe. */
  	if (copy_from_user(a, args, nargs[call]))
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
1926

89bddce58   Stephen Hemminger   [NET] socket: cod...
1927
  	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
1928
1929
  	if (err)
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
  	a0 = a[0];
  	a1 = a[1];
  
  	switch (call) {
  	case SYS_SOCKET:
  		err = sys_socket(a0, a1, a[2]);
  		break;
  	case SYS_BIND:
  		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
  		break;
  	case SYS_CONNECT:
  		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
  		break;
  	case SYS_LISTEN:
  		err = sys_listen(a0, a1);
  		break;
  	case SYS_ACCEPT:
  		err =
  		    sys_accept(a0, (struct sockaddr __user *)a1,
  			       (int __user *)a[2]);
  		break;
  	case SYS_GETSOCKNAME:
  		err =
  		    sys_getsockname(a0, (struct sockaddr __user *)a1,
  				    (int __user *)a[2]);
  		break;
  	case SYS_GETPEERNAME:
  		err =
  		    sys_getpeername(a0, (struct sockaddr __user *)a1,
  				    (int __user *)a[2]);
  		break;
  	case SYS_SOCKETPAIR:
  		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
  		break;
  	case SYS_SEND:
  		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
  		break;
  	case SYS_SENDTO:
  		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
  				 (struct sockaddr __user *)a[4], a[5]);
  		break;
  	case SYS_RECV:
  		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
  		break;
  	case SYS_RECVFROM:
  		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
  				   (struct sockaddr __user *)a[4],
  				   (int __user *)a[5]);
  		break;
  	case SYS_SHUTDOWN:
  		err = sys_shutdown(a0, a1);
  		break;
  	case SYS_SETSOCKOPT:
  		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
  		break;
  	case SYS_GETSOCKOPT:
  		err =
  		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
  				   (int __user *)a[4]);
  		break;
  	case SYS_SENDMSG:
  		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
  		break;
  	case SYS_RECVMSG:
  		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
  		break;
  	default:
  		err = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1999
2000
2001
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2002
  #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003

55737fda0   Stephen Hemminger   [NET]: socket fam...
2004
2005
2006
2007
  /**
   *	sock_register - add a socket protocol handler
   *	@ops: description of protocol
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008
2009
   *	This function is called by a protocol handler that wants to
   *	advertise its address family, and have it linked into the
55737fda0   Stephen Hemminger   [NET]: socket fam...
2010
2011
   *	socket interface. The value ops->family coresponds to the
   *	socket system call protocol family.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2012
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2013
  int sock_register(const struct net_proto_family *ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014
2015
2016
2017
  {
  	int err;
  
  	if (ops->family >= NPROTO) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2018
2019
2020
  		printk(KERN_CRIT "protocol %d >= NPROTO(%d)
  ", ops->family,
  		       NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021
2022
  		return -ENOBUFS;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2023
2024
2025
2026
2027
  
  	spin_lock(&net_family_lock);
  	if (net_families[ops->family])
  		err = -EEXIST;
  	else {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2028
  		net_families[ops->family] = ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2029
2030
  		err = 0;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2031
  	spin_unlock(&net_family_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2032
2033
  	printk(KERN_INFO "NET: Registered protocol family %d
  ", ops->family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2034
2035
  	return err;
  }
55737fda0   Stephen Hemminger   [NET]: socket fam...
2036
2037
2038
2039
  /**
   *	sock_unregister - remove a protocol handler
   *	@family: protocol family to remove
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2040
2041
   *	This function is called by a protocol handler that wants to
   *	remove its address family, and have it unlinked from the
55737fda0   Stephen Hemminger   [NET]: socket fam...
2042
2043
2044
2045
2046
2047
   *	new socket creation.
   *
   *	If protocol handler is a module, then it can use module reference
   *	counts to protect against new references. If protocol handler is not
   *	a module then it needs to provide its own protection in
   *	the ops->create routine.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2049
  void sock_unregister(int family)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2050
  {
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2051
  	BUG_ON(family < 0 || family >= NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052

55737fda0   Stephen Hemminger   [NET]: socket fam...
2053
  	spin_lock(&net_family_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2054
  	net_families[family] = NULL;
55737fda0   Stephen Hemminger   [NET]: socket fam...
2055
2056
2057
  	spin_unlock(&net_family_lock);
  
  	synchronize_rcu();
89bddce58   Stephen Hemminger   [NET] socket: cod...
2058
2059
  	printk(KERN_INFO "NET: Unregistered protocol family %d
  ", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2060
  }
77d76ea31   Andi Kleen   [NET]: Small clea...
2061
  static int __init sock_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2062
2063
  {
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2064
  	 *      Initialize sock SLAB cache.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2065
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
2066

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067
  	sk_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2069
  	 *      Initialize skbuff SLAB cache
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
2071
  	 */
  	skb_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2072
2073
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2074
  	 *      Initialize the protocols module.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2075
2076
2077
2078
2079
  	 */
  
  	init_inodecache();
  	register_filesystem(&sock_fs_type);
  	sock_mnt = kern_mount(&sock_fs_type);
77d76ea31   Andi Kleen   [NET]: Small clea...
2080
2081
  
  	/* The real protocol initialization is performed in later initcalls.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2082
2083
2084
2085
2086
  	 */
  
  #ifdef CONFIG_NETFILTER
  	netfilter_init();
  #endif
cbeb321a6   David S. Miller   [NET]: Fix sock_i...
2087
2088
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
  }
77d76ea31   Andi Kleen   [NET]: Small clea...
2090
  core_initcall(sock_init);	/* early initcall */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2091
2092
2093
2094
2095
  #ifdef CONFIG_PROC_FS
  void socket_seq_show(struct seq_file *seq)
  {
  	int cpu;
  	int counter = 0;
6f9120422   KAMEZAWA Hiroyuki   [PATCH] for_each_...
2096
  	for_each_possible_cpu(cpu)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2097
  	    counter += per_cpu(sockets_in_use, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2098
2099
2100
2101
2102
2103
2104
2105
  
  	/* It can be negative, by the way. 8) */
  	if (counter < 0)
  		counter = 0;
  
  	seq_printf(seq, "sockets: used %d
  ", counter);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2106
  #endif				/* CONFIG_PROC_FS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2107

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2108
2109
  #ifdef CONFIG_COMPAT
  static long compat_sock_ioctl(struct file *file, unsigned cmd,
89bddce58   Stephen Hemminger   [NET] socket: cod...
2110
  			      unsigned long arg)
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
  {
  	struct socket *sock = file->private_data;
  	int ret = -ENOIOCTLCMD;
  
  	if (sock->ops->compat_ioctl)
  		ret = sock->ops->compat_ioctl(sock, cmd, arg);
  
  	return ret;
  }
  #endif
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
  int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
  {
  	return sock->ops->bind(sock, addr, addrlen);
  }
  
  int kernel_listen(struct socket *sock, int backlog)
  {
  	return sock->ops->listen(sock, backlog);
  }
  
  int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
  {
  	struct sock *sk = sock->sk;
  	int err;
  
  	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
  			       newsock);
  	if (err < 0)
  		goto done;
  
  	err = sock->ops->accept(sock, *newsock, flags);
  	if (err < 0) {
  		sock_release(*newsock);
fa8705b00   Tony Battersby   [NET]: sanitize k...
2144
  		*newsock = NULL;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
  		goto done;
  	}
  
  	(*newsock)->ops = sock->ops;
  
  done:
  	return err;
  }
  
  int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
2155
  		   int flags)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
  {
  	return sock->ops->connect(sock, addr, addrlen, flags);
  }
  
  int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 0);
  }
  
  int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 1);
  }
  
  int kernel_getsockopt(struct socket *sock, int level, int optname,
  			char *optval, int *optlen)
  {
  	mm_segment_t oldfs = get_fs();
  	int err;
  
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
  		err = sock_getsockopt(sock, level, optname, optval, optlen);
  	else
  		err = sock->ops->getsockopt(sock, level, optname, optval,
  					    optlen);
  	set_fs(oldfs);
  	return err;
  }
  
  int kernel_setsockopt(struct socket *sock, int level, int optname,
  			char *optval, int optlen)
  {
  	mm_segment_t oldfs = get_fs();
  	int err;
  
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
  		err = sock_setsockopt(sock, level, optname, optval, optlen);
  	else
  		err = sock->ops->setsockopt(sock, level, optname, optval,
  					    optlen);
  	set_fs(oldfs);
  	return err;
  }
  
  int kernel_sendpage(struct socket *sock, struct page *page, int offset,
  		    size_t size, int flags)
  {
  	if (sock->ops->sendpage)
  		return sock->ops->sendpage(sock, page, offset, size, flags);
  
  	return sock_no_sendpage(sock, page, offset, size, flags);
  }
  
  int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
  {
  	mm_segment_t oldfs = get_fs();
  	int err;
  
  	set_fs(KERNEL_DS);
  	err = sock->ops->ioctl(sock, cmd, arg);
  	set_fs(oldfs);
  
  	return err;
  }
91cf45f02   Trond Myklebust   [NET]: Add the he...
2224
2225
2226
2227
  int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
  {
  	return sock->ops->shutdown(sock, how);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
  /* ABI emulation layers need these two */
  EXPORT_SYMBOL(move_addr_to_kernel);
  EXPORT_SYMBOL(move_addr_to_user);
  EXPORT_SYMBOL(sock_create);
  EXPORT_SYMBOL(sock_create_kern);
  EXPORT_SYMBOL(sock_create_lite);
  EXPORT_SYMBOL(sock_map_fd);
  EXPORT_SYMBOL(sock_recvmsg);
  EXPORT_SYMBOL(sock_register);
  EXPORT_SYMBOL(sock_release);
  EXPORT_SYMBOL(sock_sendmsg);
  EXPORT_SYMBOL(sock_unregister);
  EXPORT_SYMBOL(sock_wake_async);
  EXPORT_SYMBOL(sockfd_lookup);
  EXPORT_SYMBOL(kernel_sendmsg);
  EXPORT_SYMBOL(kernel_recvmsg);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
  EXPORT_SYMBOL(kernel_bind);
  EXPORT_SYMBOL(kernel_listen);
  EXPORT_SYMBOL(kernel_accept);
  EXPORT_SYMBOL(kernel_connect);
  EXPORT_SYMBOL(kernel_getsockname);
  EXPORT_SYMBOL(kernel_getpeername);
  EXPORT_SYMBOL(kernel_getsockopt);
  EXPORT_SYMBOL(kernel_setsockopt);
  EXPORT_SYMBOL(kernel_sendpage);
  EXPORT_SYMBOL(kernel_sock_ioctl);
91cf45f02   Trond Myklebust   [NET]: Add the he...
2254
  EXPORT_SYMBOL(kernel_sock_shutdown);