Blame view

net/socket.c 55 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
  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;
997b37da1   Rémi Denis-Courmont   [NET]: Make sure ...
675
676
  	if (unlikely(!sock->ops->splice_read))
  		return -EINVAL;
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
677
678
  	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
679
  static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89bddce58   Stephen Hemminger   [NET] socket: cod...
680
  					 struct sock_iocb *siocb)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
681
682
683
684
685
  {
  	if (!is_sync_kiocb(iocb)) {
  		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
  		if (!siocb)
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  		iocb->ki_dtor = sock_aio_dtor;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688

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

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

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

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

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
740
741
742
743
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
744
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
745
746
747
748
  	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
749

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
750
  	return __sock_sendmsg(iocb, sock, msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
752
753
  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...
754
755
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756

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

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

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

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
806
807
808
809
810
811
  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...
812
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
  	void __user *argp = (void __user *)arg;
  	int pid, err;
881d966b4   Eric W. Biederman   [NET]: Make the d...
815
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816

b69aee04f   Eric Dumazet   [NET]: Use file->...
817
  	sock = file->private_data;
881d966b4   Eric W. Biederman   [NET]: Make the d...
818
  	sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
819
  	net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
821
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  	} else
d86b5e0e6   Adrian Bunk   [PATCH] net/: fix...
823
  #ifdef CONFIG_WIRELESS_EXT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
825
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
  	} else
89bddce58   Stephen Hemminger   [NET] socket: cod...
827
828
  #endif				/* CONFIG_WIRELESS_EXT */
  		switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
830
831
832
833
834
835
836
837
  		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...
838
  			err = put_user(f_getown(sock->file),
89bddce58   Stephen Hemminger   [NET] socket: cod...
839
  				       (int __user *)argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
842
843
844
845
846
847
  			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: ...
848
  			mutex_lock(&br_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
849
  			if (br_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
850
  				err = br_ioctl_hook(net, cmd, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
851
  			mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
854
855
856
857
  			break;
  		case SIOCGIFVLAN:
  		case SIOCSIFVLAN:
  			err = -ENOPKG;
  			if (!vlan_ioctl_hook)
  				request_module("8021q");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
858
  			mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
  			if (vlan_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
860
  				err = vlan_ioctl_hook(net, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
861
  			mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
865
866
867
  		case SIOCADDDLCI:
  		case SIOCDELDLCI:
  			err = -ENOPKG;
  			if (!dlci_ioctl_hook)
  				request_module("dlci");
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
868
869
  			mutex_lock(&dlci_ioctl_mutex);
  			if (dlci_ioctl_hook)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  				err = dlci_ioctl_hook(cmd, argp);
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
871
  			mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
  			break;
  		default:
  			err = sock->ops->ioctl(sock, cmd, arg);
b5e5fa5e0   Christoph Hellwig   [NET]: Add a dev_...
875
876
877
878
879
880
  
  			/*
  			 * 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...
881
  				err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
883
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
886
887
888
889
890
  	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...
891

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
893
894
895
896
897
898
899
900
  	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
901
  	sock->type = type;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
902
903
904
  	err = security_socket_post_create(sock, family, type, protocol, 1);
  	if (err)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
  out:
  	*res = sock;
  	return err;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
908
909
910
911
  out_release:
  	sock_release(sock);
  	sock = NULL;
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
  }
  
  /* No kernel lock held - perfect */
89bddce58   Stephen Hemminger   [NET] socket: cod...
915
  static unsigned int sock_poll(struct file *file, poll_table *wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
917
918
919
  {
  	struct socket *sock;
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
920
  	 *      We can't return errors to poll, so it's either yes or no.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  	 */
b69aee04f   Eric Dumazet   [NET]: Use file->...
922
  	sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
  	return sock->ops->poll(file, sock, wait);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
925
  static int sock_mmap(struct file *file, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  {
b69aee04f   Eric Dumazet   [NET]: Use file->...
927
  	struct socket *sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
929
930
  
  	return sock->ops->mmap(file, sock, vma);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
931
  static int sock_close(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
  {
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
934
935
  	 *      It was possible the inode is NULL we were
  	 *      closing an unfinished socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
937
  	if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
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
  		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...
964
  	struct fasync_struct *fa, *fna = NULL, **prev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
966
  	struct socket *sock;
  	struct sock *sk;
89bddce58   Stephen Hemminger   [NET] socket: cod...
967
  	if (on) {
8b3a70058   Kris Katterjohn   [NET]: Remove mor...
968
  		fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
969
  		if (fna == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
  			return -ENOMEM;
  	}
b69aee04f   Eric Dumazet   [NET]: Use file->...
972
  	sock = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973

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

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

55737fda0   Stephen Hemminger   [NET]: socket fam...
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
  	/*
  	 *	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
1090
  #if defined(CONFIG_KMOD)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1091
1092
1093
  	/* 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
1094
1095
1096
  	 * requested real, full-featured networking support upon configuration.
  	 * Otherwise module support will break!
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1097
  	if (net_families[family] == NULL)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1098
  		request_module("net-pf-%d", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
  #endif
55737fda0   Stephen Hemminger   [NET]: socket fam...
1100
1101
1102
1103
1104
  	rcu_read_lock();
  	pf = rcu_dereference(net_families[family]);
  	err = -EAFNOSUPPORT;
  	if (!pf)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
1107
1108
1109
  
  	/*
  	 * 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...
1110
  	if (!try_module_get(pf->owner))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
  		goto out_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1112
1113
  	/* Now protected by module ref count */
  	rcu_read_unlock();
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1114
  	err = pf->create(net, sock, protocol);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1115
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
  		goto out_module_put;
a79af59ef   Frank Filz   [NET]: Fix module...
1117

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

55737fda0   Stephen Hemminger   [NET]: socket fam...
1134
1135
1136
1137
  	return 0;
  
  out_module_busy:
  	err = -EAFNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
  out_module_put:
55737fda0   Stephen Hemminger   [NET]: socket fam...
1139
1140
1141
  	sock->ops = NULL;
  	module_put(pf->owner);
  out_sock_release:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
  	sock_release(sock);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1143
1144
1145
1146
1147
  	return err;
  
  out_release:
  	rcu_read_unlock();
  	goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1148
1149
1150
1151
  }
  
  int sock_create(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1152
  	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
1155
1156
  }
  
  int sock_create_kern(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1157
  	return __sock_create(&init_net, family, type, protocol, res, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
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
  }
  
  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...
1185
1186
  asmlinkage long sys_socketpair(int family, int type, int protocol,
  			       int __user *usockvec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
1188
1189
  {
  	struct socket *sock1, *sock2;
  	int fd1, fd2, err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1190
  	struct file *newfile1, *newfile2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
  
  	/*
  	 * 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...
1206
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1207
  		goto out_release_both;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1208
  	fd1 = sock_alloc_fd(&newfile1);
bf3c23d17   David S. Miller   [NET]: Fix error ...
1209
1210
  	if (unlikely(fd1 < 0)) {
  		err = fd1;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1211
  		goto out_release_both;
bf3c23d17   David S. Miller   [NET]: Fix error ...
1212
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213

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

db3495099   Al Viro   [PATCH] AUDIT_FD_...
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
  	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
1239

db3495099   Al Viro   [PATCH] AUDIT_FD_...
1240
1241
  	fd_install(fd1, newfile1);
  	fd_install(fd2, newfile2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
1243
1244
  	/* fd1 and fd2 may be already another descriptors.
  	 * Not kernel problem.
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1245
  	err = put_user(fd1, &usockvec[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
1247
1248
1249
1250
1251
1252
1253
  	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
1254
  out_release_both:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1255
  	sock_release(sock2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  out_release_1:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1257
  	sock_release(sock1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
  out:
  	return err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  
  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
1271
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
  /*
   *	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...
1284
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285

89bddce58   Stephen Hemminger   [NET] socket: cod...
1286
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
e71a4783a   Stephen Hemminger   [NET] core: white...
1287
  	if (sock) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1288
1289
1290
1291
1292
  		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...
1293
1294
  			if (!err)
  				err = sock->ops->bind(sock,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1295
1296
  						      (struct sockaddr *)
  						      address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
  		}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1298
  		fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1299
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
1301
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
1305
1306
  /*
   *	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
1307
1308
1309
  asmlinkage long sys_listen(int fd, int backlog)
  {
  	struct socket *sock;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1310
  	int err, fput_needed;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1311
  	int somaxconn;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1312
1313
1314
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock) {
8efa6e93c   Pavel Emelyanov   [NETNS]: Introduc...
1315
  		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1316
1317
  		if ((unsigned)backlog > somaxconn)
  			backlog = somaxconn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
1319
  
  		err = security_socket_listen(sock, backlog);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1320
1321
  		if (!err)
  			err = sock->ops->listen(sock, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1323
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324
1325
1326
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
  /*
   *	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...
1338
1339
  asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
  			   int __user *upeer_addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
  {
  	struct socket *sock, *newsock;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1342
  	struct file *newfile;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1343
  	int err, len, newfd, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1345
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
1348
1349
  	if (!sock)
  		goto out;
  
  	err = -ENFILE;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1350
  	if (!(newsock = sock_alloc()))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
1352
1353
1354
  		goto out_put;
  
  	newsock->type = sock->type;
  	newsock->ops = sock->ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
1356
1357
1358
1359
  	/*
  	 * 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...
1360
1361
1362
  	newfd = sock_alloc_fd(&newfile);
  	if (unlikely(newfd < 0)) {
  		err = newfd;
9a1875e60   David S. Miller   [NET]: Fully fix ...
1363
1364
  		sock_release(newsock);
  		goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1365
1366
1367
1368
  	}
  
  	err = sock_attach_fd(newsock, newfile);
  	if (err < 0)
79f4f6428   Alexey Dobriyan   [NET]: Correct ac...
1369
  		goto out_fd_simple;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1370

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
1376
  	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
  	if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1377
  		goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
1379
  
  	if (upeer_sockaddr) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1380
1381
  		if (newsock->ops->getname(newsock, (struct sockaddr *)address,
  					  &len, 2) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
  			err = -ECONNABORTED;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1383
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1385
1386
  		err = move_addr_to_user(address, len, upeer_sockaddr,
  					upeer_addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
  		if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1388
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
1390
1391
  	}
  
  	/* File flags are not inherited via accept() unlike another OSes. */
39d8c1b6f   David S. Miller   [NET]: Do not los...
1392
1393
  	fd_install(newfd, newfile);
  	err = newfd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
1396
1397
  
  	security_socket_post_accept(sock, newsock);
  
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1398
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399
1400
  out:
  	return err;
79f4f6428   Alexey Dobriyan   [NET]: Correct ac...
1401
1402
1403
1404
1405
  out_fd_simple:
  	sock_release(newsock);
  	put_filp(newfile);
  	put_unused_fd(newfd);
  	goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1406
  out_fd:
9606a2163   David S. Miller   [NET]: Fix dentry...
1407
  	fput(newfile);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1408
  	put_unused_fd(newfd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
1410
  	goto out_put;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
  /*
   *	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...
1422
1423
  asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
  			    int addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
1426
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1427
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428

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

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1458
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
  	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...
1472
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
1474
1475
1476
1477
1478
1479
1480
  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...
1481
1482
  asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
  				int __user *usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
1485
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1486
  	int len, err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487

89bddce58   Stephen Hemminger   [NET] socket: cod...
1488
1489
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490
1491
  		err = security_socket_getpeername(sock);
  		if (err) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1492
  			fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493
1494
  			return err;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1495
1496
1497
  		err =
  		    sock->ops->getname(sock, (struct sockaddr *)address, &len,
  				       1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
  		if (!err)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1499
1500
  			err = move_addr_to_user(address, len, usockaddr,
  						usockaddr_len);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1501
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502
1503
1504
1505
1506
1507
1508
1509
1510
  	}
  	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...
1511
1512
1513
  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
1514
1515
1516
1517
1518
1519
  {
  	struct socket *sock;
  	char address[MAX_SOCK_ADDR];
  	int err;
  	struct msghdr msg;
  	struct iovec iov;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1520
  	int fput_needed;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1521

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

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

89bddce58   Stephen Hemminger   [NET] socket: cod...
1578
1579
1580
1581
1582
1583
1584
1585
  	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
1586
1587
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1588
  	err = sock_recvmsg(sock, &msg, size, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713
1714
1715
1716
  	err = -EFAULT;
  	if (MSG_CMSG_COMPAT & flags) {
  		if (get_compat_msghdr(&msg_sys, msg_compat))
  			return -EFAULT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1717
1718
  	}
  	else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1719
  		return -EFAULT;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1720
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1721
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1722
1723
1724
1725
1726
1727
  		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...
1728
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
  	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...
1742
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743
1744
1745
1746
1747
1748
1749
  		goto out_freeiov;
  	total_len = err;
  
  	err = -ENOBUFS;
  
  	if (msg_sys.msg_controllen > INT_MAX)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1750
  	ctl_len = msg_sys.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
  	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1752
1753
1754
  		err =
  		    cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
  						     sizeof(ctl));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
1756
1757
  		if (err)
  			goto out_freeiov;
  		ctl_buf = msg_sys.msg_control;
8920e8f94   Al Viro   [PATCH] Fix 32bit...
1758
  		ctl_len = msg_sys.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759
  	} else if (ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1760
  		if (ctl_len > sizeof(ctl)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
  			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1762
  			if (ctl_buf == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
1765
1766
1767
1768
1769
1770
  				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...
1771
1772
  		if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
  				   ctl_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
  			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...
1783
  	if (ctl_buf != ctl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
1785
1786
1787
1788
  		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...
1789
  	fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1790
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
1792
1793
1794
1795
1796
  	return err;
  }
  
  /*
   *	BSD recvmsg interface
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1797
1798
  asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
  			    unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1800
1801
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1802
1803
  	struct socket *sock;
  	struct iovec iovstack[UIO_FASTIOV];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1804
  	struct iovec *iov = iovstack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
1806
1807
  	struct msghdr msg_sys;
  	unsigned long cmsg_ptr;
  	int err, iov_size, total_len, len;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1808
  	int fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1809
1810
1811
1812
1813
1814
1815
  
  	/* 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...
1816

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

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1824
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
1827
1828
1829
1830
  	if (!sock)
  		goto out;
  
  	err = -EMSGSIZE;
  	if (msg_sys.msg_iovlen > UIO_MAXIOV)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1831
1832
  
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
1834
1835
1836
1837
1838
1839
1840
1841
  	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...
1842
1843
  	 *      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
1844
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1845

cfcabdcc2   Stephen Hemminger   [NET]: sparse war...
1846
  	uaddr = (__force void __user *)msg_sys.msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
1848
1849
1850
1851
1852
1853
  	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...
1854
  	total_len = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
1856
  
  	cmsg_ptr = (unsigned long)msg_sys.msg_control;
4a19542e5   Ulrich Drepper   O_CLOEXEC for SCM...
1857
  	msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1858

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1859
1860
1861
1862
1863
1864
1865
1866
  	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...
1867
1868
  		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
  					uaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1869
1870
1871
  		if (err < 0)
  			goto out_freeiov;
  	}
37f7f421c   David S. Miller   [NET]: Do not lea...
1872
1873
  	err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT),
  			 COMPAT_FLAGS(msg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
1875
1876
  	if (err)
  		goto out_freeiov;
  	if (MSG_CMSG_COMPAT & flags)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1877
  		err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1878
1879
  				 &msg_compat->msg_controllen);
  	else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1880
  		err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
1882
1883
1884
1885
1886
1887
1888
1889
  				 &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...
1890
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
1892
1893
1894
1895
1896
1897
1898
  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...
1899
1900
1901
1902
1903
  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
1904
1905
1906
  #undef AL
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1907
   *	System call vectors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1908
1909
1910
   *
   *	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...
1911
   *  it is set by the callees.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
1913
1914
1915
1916
   */
  
  asmlinkage long sys_socketcall(int call, unsigned long __user *args)
  {
  	unsigned long a[6];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1917
  	unsigned long a0, a1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1918
  	int err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1919
  	if (call < 1 || call > SYS_RECVMSG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1920
1921
1922
1923
1924
  		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...
1925

89bddce58   Stephen Hemminger   [NET] socket: cod...
1926
  	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
1927
1928
  	if (err)
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1929
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
  	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
1998
1999
2000
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2001
  #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2002

55737fda0   Stephen Hemminger   [NET]: socket fam...
2003
2004
2005
2006
  /**
   *	sock_register - add a socket protocol handler
   *	@ops: description of protocol
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
2008
   *	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...
2009
2010
   *	socket interface. The value ops->family coresponds to the
   *	socket system call protocol family.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2012
  int sock_register(const struct net_proto_family *ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2013
2014
2015
2016
  {
  	int err;
  
  	if (ops->family >= NPROTO) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2017
2018
2019
  		printk(KERN_CRIT "protocol %d >= NPROTO(%d)
  ", ops->family,
  		       NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2020
2021
  		return -ENOBUFS;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2022
2023
2024
2025
2026
  
  	spin_lock(&net_family_lock);
  	if (net_families[ops->family])
  		err = -EEXIST;
  	else {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2027
  		net_families[ops->family] = ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2028
2029
  		err = 0;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2030
  	spin_unlock(&net_family_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2031
2032
  	printk(KERN_INFO "NET: Registered protocol family %d
  ", ops->family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2033
2034
  	return err;
  }
55737fda0   Stephen Hemminger   [NET]: socket fam...
2035
2036
2037
2038
  /**
   *	sock_unregister - remove a protocol handler
   *	@family: protocol family to remove
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2039
2040
   *	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...
2041
2042
2043
2044
2045
2046
   *	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
2047
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2048
  void sock_unregister(int family)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2049
  {
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2050
  	BUG_ON(family < 0 || family >= NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2051

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

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

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2107
2108
  #ifdef CONFIG_COMPAT
  static long compat_sock_ioctl(struct file *file, unsigned cmd,
89bddce58   Stephen Hemminger   [NET] socket: cod...
2109
  			      unsigned long arg)
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
  {
  	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 ...
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
  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...
2143
  		*newsock = NULL;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
  		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...
2154
  		   int flags)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2155
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
  {
  	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...
2223
2224
2225
2226
  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
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
  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 ...
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
  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...
2250
  EXPORT_SYMBOL(kernel_sock_shutdown);