1 /*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * Generic socket support routines. Memory allocators, sk->inuse/release
7 * handler for protocols to use and generic option handler.
8 *
9 *
10 * Version: @(#)sock.c 1.0.17 06/02/93
11 *
12 * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
13 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
14 * Florian La Roche, <flla@stud.uni-sb.de>
15 * Alan Cox, <A.Cox@swansea.ac.uk>
16 *
17 * Fixes:
18 * Alan Cox : Numerous verify_area() problems
19 * Alan Cox : Connecting on a connecting socket
20 * now returns an error for tcp.
21 * Alan Cox : sock->protocol is set correctly.
22 * and is not sometimes left as 0.
23 * Alan Cox : connect handles icmp errors on a
24 * connect properly. Unfortunately there
25 * is a restart syscall nasty there. I
26 * can't match BSD without hacking the C
27 * library. Ideas urgently sought!
28 * Alan Cox : Disallow bind() to addresses that are
29 * not ours - especially broadcast ones!!
30 * Alan Cox : Socket 1024 _IS_ ok for users. (fencepost)
31 * Alan Cox : sock_wfree/sock_rfree don't destroy sockets,
32 * instead they leave that for the DESTROY timer.
33 * Alan Cox : Clean up error flag in accept
34 * Alan Cox : TCP ack handling is buggy, the DESTROY timer
35 * was buggy. Put a remove_sock() in the handler
36 * for memory when we hit 0. Also altered the timer
37 * code. The ACK stuff can wait and needs major
38 * TCP layer surgery.
39 * Alan Cox : Fixed TCP ack bug, removed remove sock
40 * and fixed timer/inet_bh race.
41 * Alan Cox : Added zapped flag for TCP
42 * Alan Cox : Move kfree_skb into skbuff.c and tidied up surplus code
43 * Alan Cox : for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
44 * Alan Cox : kfree_s calls now are kfree_skbmem so we can track skb resources
45 * Alan Cox : Supports socket option broadcast now as does udp. Packet and raw need fixing.
46 * Alan Cox : Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
47 * Rick Sladkey : Relaxed UDP rules for matching packets.
48 * C.E.Hawkins : IFF_PROMISC/SIOCGHWADDR support
49 * Pauline Middelink : identd support
50 * Alan Cox : Fixed connect() taking signals I think.
51 * Alan Cox : SO_LINGER supported
52 * Alan Cox : Error reporting fixes
53 * Anonymous : inet_create tidied up (sk->reuse setting)
54 * Alan Cox : inet sockets don't set sk->type!
55 * Alan Cox : Split socket option code
56 * Alan Cox : Callbacks
57 * Alan Cox : Nagle flag for Charles & Johannes stuff
58 * Alex : Removed restriction on inet fioctl
59 * Alan Cox : Splitting INET from NET core
60 * Alan Cox : Fixed bogus SO_TYPE handling in getsockopt()
61 * Adam Caldwell : Missing return in SO_DONTROUTE/SO_DEBUG code
62 * Alan Cox : Split IP from generic code
63 * Alan Cox : New kfree_skbmem()
64 * Alan Cox : Make SO_DEBUG superuser only.
65 * Alan Cox : Allow anyone to clear SO_DEBUG
66 * (compatibility fix)
67 * Alan Cox : Added optimistic memory grabbing for AF_UNIX throughput.
68 * Alan Cox : Allocator for a socket is settable.
69 *
70 * To Fix:
71 *
72 *
73 * This program is free software; you can redistribute it and/or
74 * modify it under the terms of the GNU General Public License
75 * as published by the Free Software Foundation; either version
76 * 2 of the License, or (at your option) any later version.
77 */
78
79 #include <linux/config.h>
80 #include <linux/errno.h>
81 #include <linux/types.h>
82 #include <linux/socket.h>
83 #include <linux/in.h>
84 #include <linux/kernel.h>
85 #include <linux/major.h>
86 #include <linux/sched.h>
87 #include <linux/timer.h>
88 #include <linux/string.h>
89 #include <linux/sockios.h>
90 #include <linux/net.h>
91 #include <linux/fcntl.h>
92 #include <linux/mm.h>
93 #include <linux/interrupt.h>
94
95 #include <asm/segment.h>
96 #include <asm/system.h>
97
98 #include <linux/inet.h>
99 #include <linux/netdevice.h>
100 #include <net/ip.h>
101 #include <net/protocol.h>
102 #include <net/arp.h>
103 #include <net/rarp.h>
104 #include <net/route.h>
105 #include <net/tcp.h>
106 #include <net/udp.h>
107 #include <linux/skbuff.h>
108 #include <net/sock.h>
109 #include <net/raw.h>
110 #include <net/icmp.h>
111
112 #define min(a,b) ((a)<(b)?(a):(b))
113
114 /*
115 * This is meant for all protocols to use and covers goings on
116 * at the socket level. Everything here is generic.
117 */
118
119 int sock_setsockopt(struct sock *sk, int level, int optname,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
120 char *optval, int optlen)
121 {
122 int val;
123 int valbool;
124 int err;
125 struct linger ling;
126
127 if (optval == NULL)
128 return(-EINVAL);
129
130 err=verify_area(VERIFY_READ, optval, sizeof(int));
131 if(err)
132 return err;
133
134 val = get_user((int *)optval);
135 valbool = val?1:0;
136
137 switch(optname)
138 {
139 case SO_DEBUG:
140 if(val && !suser())
141 return(-EPERM);
142 sk->debug=valbool;
143 return 0;
144 case SO_REUSEADDR:
145 sk->reuse = valbool;
146 return(0);
147 case SO_TYPE:
148 case SO_ERROR:
149 return(-ENOPROTOOPT);
150 case SO_DONTROUTE:
151 sk->localroute=valbool;
152 return 0;
153 case SO_BROADCAST:
154 sk->broadcast=valbool;
155 return 0;
156 case SO_SNDBUF:
157 if(val>32767)
158 val=32767;
159 if(val<256)
160 val=256;
161 sk->sndbuf=val;
162 return 0;
163
164 case SO_RCVBUF:
165 if(val>32767)
166 val=32767;
167 if(val<256)
168 val=256;
169 sk->rcvbuf=val;
170 return(0);
171
172 case SO_KEEPALIVE:
173 sk->keepopen = valbool;
174 return(0);
175
176 case SO_OOBINLINE:
177 sk->urginline = valbool;
178 return(0);
179
180 case SO_NO_CHECK:
181 sk->no_check = valbool;
182 return(0);
183
184 case SO_PRIORITY:
185 if (val >= 0 && val < DEV_NUMBUFFS)
186 {
187 sk->priority = val;
188 }
189 else
190 {
191 return(-EINVAL);
192 }
193 return(0);
194
195
196 case SO_LINGER:
197 err=verify_area(VERIFY_READ,optval,sizeof(ling));
198 if(err)
199 return err;
200 memcpy_fromfs(&ling,optval,sizeof(ling));
201 if(ling.l_onoff==0)
202 sk->linger=0;
203 else
204 {
205 sk->lingertime=ling.l_linger;
206 sk->linger=1;
207 }
208 return 0;
209
210
211 default:
212 return(-ENOPROTOOPT);
213 }
214 }
215
216
217 int sock_getsockopt(struct sock *sk, int level, int optname,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
218 char *optval, int *optlen)
219 {
220 int val;
221 int err;
222 struct linger ling;
223
224 switch(optname)
225 {
226 case SO_DEBUG:
227 val = sk->debug;
228 break;
229
230 case SO_DONTROUTE:
231 val = sk->localroute;
232 break;
233
234 case SO_BROADCAST:
235 val= sk->broadcast;
236 break;
237
238 case SO_SNDBUF:
239 val=sk->sndbuf;
240 break;
241
242 case SO_RCVBUF:
243 val =sk->rcvbuf;
244 break;
245
246 case SO_REUSEADDR:
247 val = sk->reuse;
248 break;
249
250 case SO_KEEPALIVE:
251 val = sk->keepopen;
252 break;
253
254 case SO_TYPE:
255 val = sk->type;
256 break;
257
258 case SO_ERROR:
259 val = sk->err;
260 sk->err = 0;
261 break;
262
263 case SO_OOBINLINE:
264 val = sk->urginline;
265 break;
266
267 case SO_NO_CHECK:
268 val = sk->no_check;
269 break;
270
271 case SO_PRIORITY:
272 val = sk->priority;
273 break;
274
275 case SO_LINGER:
276 err=verify_area(VERIFY_WRITE,optval,sizeof(ling));
277 if(err)
278 return err;
279 err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
280 if(err)
281 return err;
282 put_fs_long(sizeof(ling),(unsigned long *)optlen);
283 ling.l_onoff=sk->linger;
284 ling.l_linger=sk->lingertime;
285 memcpy_tofs(optval,&ling,sizeof(ling));
286 return 0;
287
288
289
290 default:
291 return(-ENOPROTOOPT);
292 }
293 err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
294 if(err)
295 return err;
296 put_fs_long(sizeof(int),(unsigned long *) optlen);
297
298 err=verify_area(VERIFY_WRITE, optval, sizeof(int));
299 if(err)
300 return err;
301 put_fs_long(val,(unsigned long *)optval);
302
303 return(0);
304 }
305
306
307 struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
308 {
309 if (sk)
310 {
311 if (sk->wmem_alloc + size < sk->sndbuf || force)
312 {
313 struct sk_buff * c = alloc_skb(size, priority);
314 if (c)
315 {
316 unsigned long flags;
317 save_flags(flags);
318 cli();
319 sk->wmem_alloc+= c->truesize;
320 restore_flags(flags); /* was sti(); */
321 }
322 return c;
323 }
324 return(NULL);
325 }
326 return(alloc_skb(size, priority));
327 }
328
329
330 struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
331 {
332 if (sk)
333 {
334 if (sk->rmem_alloc + size < sk->rcvbuf || force)
335 {
336 struct sk_buff *c = alloc_skb(size, priority);
337 if (c)
338 {
339 unsigned long flags;
340 save_flags(flags);
341 cli();
342 sk->rmem_alloc += c->truesize;
343 restore_flags(flags); /* was sti(); */
344 }
345 return(c);
346 }
347 return(NULL);
348 }
349 return(alloc_skb(size, priority));
350 }
351
352
353 unsigned long sock_rspace(struct sock *sk)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
354 {
355 int amt;
356
357 if (sk != NULL)
358 {
359 if (sk->rmem_alloc >= sk->rcvbuf-2*MIN_WINDOW)
360 return(0);
361 amt = min((sk->rcvbuf-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW);
362 if (amt < 0)
363 return(0);
364 return(amt);
365 }
366 return(0);
367 }
368
369
370 unsigned long sock_wspace(struct sock *sk)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
371 {
372 if (sk != NULL)
373 {
374 if (sk->shutdown & SEND_SHUTDOWN)
375 return(0);
376 if (sk->wmem_alloc >= sk->sndbuf)
377 return(0);
378 return(sk->sndbuf-sk->wmem_alloc );
379 }
380 return(0);
381 }
382
383
384 void sock_wfree(struct sock *sk, struct sk_buff *skb)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
385 {
386 int s=skb->truesize;
387 #if CONFIG_SKB_CHECK
388 IS_SKB(skb);
389 #endif
390 kfree_skbmem(skb);
391 if (sk)
392 {
393 unsigned long flags;
394 save_flags(flags);
395 cli();
396 sk->wmem_alloc -= s;
397 restore_flags(flags);
398 /* In case it might be waiting for more memory. */
399 sk->write_space(sk);
400 return;
401 }
402 }
403
404
405 void sock_rfree(struct sock *sk, struct sk_buff *skb)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
406 {
407 int s=skb->truesize;
408 #if CONFIG_SKB_CHECK
409 IS_SKB(skb);
410 #endif
411 kfree_skbmem(skb);
412 if (sk)
413 {
414 unsigned long flags;
415 save_flags(flags);
416 cli();
417 sk->rmem_alloc -= s;
418 restore_flags(flags);
419 }
420 }
421
422 /*
423 * Generic send/receive buffer handlers
424 */
425
426 struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, unsigned long fallback, int noblock, int *errcode)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
427 {
428 struct sk_buff *skb;
429 int err;
430
431 sk->inuse=1;
432
433 do
434 {
435 if(sk->err!=0)
436 {
437 cli();
438 err= -sk->err;
439 sk->err=0;
440 sti();
441 *errcode=err;
442 return NULL;
443 }
444
445 if(sk->shutdown&SEND_SHUTDOWN)
446 {
447 *errcode=-EPIPE;
448 return NULL;
449 }
450
451 if(!fallback)
452 skb = sock_wmalloc(sk, size, 0, sk->allocation);
453 else
454 {
455 /* The buffer get won't block, or use the atomic queue. It does
456 produce annoying no free page messages still.... */
457 skb = sock_wmalloc(sk, size, 0 , GFP_BUFFER);
458 if(!skb)
459 skb=sock_wmalloc(sk, fallback, 0, GFP_KERNEL);
460 }
461
462 /*
463 * This means we have too many buffers for this socket already.
464 */
465
466 if(skb==NULL)
467 {
468 unsigned long tmp;
469
470 sk->socket->flags |= SO_NOSPACE;
471 if(noblock)
472 {
473 *errcode=-EAGAIN;
474 return NULL;
475 }
476 if(sk->shutdown&SEND_SHUTDOWN)
477 {
478 *errcode=-EPIPE;
479 return NULL;
480 }
481 tmp = sk->wmem_alloc;
482 cli();
483 if(sk->shutdown&SEND_SHUTDOWN)
484 {
485 sti();
486 *errcode=-EPIPE;
487 return NULL;
488 }
489
490 #if 1
491 if( tmp <= sk->wmem_alloc)
492 #else
493 /* ANK: Line above seems either incorrect
494 * or useless. sk->wmem_alloc has a tiny chance to change
495 * between tmp = sk->w... and cli(),
496 * but it might(?) change earlier. In real life
497 * it does not (I never seen the message).
498 * In any case I'd delete this check at all, or
499 * change it to:
500 */
501 if (sk->wmem_alloc + size >= sk->sndbuf)
502 #endif
503 {
504 if (sk->wmem_alloc <= 0)
505 printk("sock.c: Look where I am %ld<%ld\n", tmp, sk->wmem_alloc);
506 sk->socket->flags &= ~SO_NOSPACE;
507 interruptible_sleep_on(sk->sleep);
508 if (current->signal & ~current->blocked)
509 {
510 sti();
511 *errcode = -ERESTARTSYS;
512 return NULL;
513 }
514 }
515 sti();
516 }
517 }
518 while(skb==NULL);
519
520 return skb;
521 }
522
523
524 void release_sock(struct sock *sk)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
525 {
526 unsigned long flags;
527 #ifdef CONFIG_INET
528 struct sk_buff *skb;
529 #endif
530
531 if (!sk->prot)
532 return;
533 /*
534 * Make the backlog atomic. If we don't do this there is a tiny
535 * window where a packet may arrive between the sk->blog being
536 * tested and then set with sk->inuse still 0 causing an extra
537 * unwanted re-entry into release_sock().
538 */
539
540 save_flags(flags);
541 cli();
542 if (sk->blog)
543 {
544 restore_flags(flags);
545 return;
546 }
547 sk->blog=1;
548 sk->inuse = 1;
549 restore_flags(flags);
550 #ifdef CONFIG_INET
551 /* See if we have any packets built up. */
552 while((skb = skb_dequeue(&sk->back_log)) != NULL)
553 {
554 sk->blog = 1;
555 if (sk->prot->rcv)
556 sk->prot->rcv(skb, skb->dev, (struct options*)skb->proto_priv,
557 skb->saddr, skb->len, skb->daddr, 1,
558 /* Only used for/by raw sockets. */
559 (struct inet_protocol *)sk->pair);
560 }
561 #endif
562 sk->blog = 0;
563 sk->inuse = 0;
564 #ifdef CONFIG_INET
565 if (sk->dead && sk->state == TCP_CLOSE)
566 {
567 /* Should be about 2 rtt's */
568 reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
569 }
570 #endif
571 }
572
573