OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [unix/] [af_unix.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * NET3:        Implementation of BSD Unix domain sockets.
3
 *
4
 * Authors:     Alan Cox, <alan@cymru.net>
5
 *
6
 *              Currently this contains all but the file descriptor passing code.
7
 *              Before that goes in the odd bugs in the iovec handlers need
8
 *              fixing, and this bit testing. BSD fd passing is not a trivial part
9
 *              of the exercise it turns out. Anyone like writing garbage collectors.
10
 *
11
 *              This program is free software; you can redistribute it and/or
12
 *              modify it under the terms of the GNU General Public License
13
 *              as published by the Free Software Foundation; either version
14
 *              2 of the License, or (at your option) any later version.
15
 *
16
 * Fixes:
17
 *              Linus Torvalds  :       Assorted bug cures.
18
 *              Niibe Yutaka    :       async I/O support.
19
 *              Carsten Paeth   :       PF_UNIX check, address fixes.
20
 *              Alan Cox        :       Limit size of allocated blocks.
21
 *              Alan Cox        :       Fixed the stupid socketpair bug.
22
 *              Alan Cox        :       BSD compatibility fine tuning.
23
 *              Alan Cox        :       Fixed a bug in connect when interrupted.
24
 *              Alan Cox        :       Sorted out a proper draft version of
25
 *                                      file descriptor passing hacked up from
26
 *                                      Mike Shaver's work.
27
 *              Marty Leisner   :       Fixes to fd passing
28
 *              Nick Nevin      :       recvmsg bugfix.
29
 *              Alan Cox        :       Started proper garbage collector
30
 *              Heiko EiBfeldt  :       Missing verify_area check
31
 *              Alan Cox        :       Shutdown() bug
32
 *
33
 * Known differences from reference BSD that was tested:
34
 *
35
 *      [TO FIX]
36
 *      ECONNREFUSED is not returned from one end of a connected() socket to the
37
 *              other the moment one end closes.
38
 *      fstat() doesn't return st_dev=NODEV, and give the blksize as high water mark
39
 *              and a fake inode identifier (nor the BSD first socket fstat twice bug).
40
 *      [NOT TO FIX]
41
 *      accept() returns a path name even if the connecting socket has closed
42
 *              in the meantime (BSD loses the path and gives up).
43
 *      accept() returns 0 length path for an unbound connector. BSD returns 16
44
 *              and a null first byte in the path (but not for gethost/peername - BSD bug ??)
45
 *      socketpair(...SOCK_RAW..) doesn't panic the kernel.
46
 *      BSD af_unix apparently has connect forgetting to block properly.
47
 */
48
 
49
#include <linux/config.h>
50
#include <linux/kernel.h>
51
#include <linux/major.h>
52
#include <linux/signal.h>
53
#include <linux/sched.h>
54
#include <linux/errno.h>
55
#include <linux/string.h>
56
#include <linux/stat.h>
57
#include <linux/socket.h>
58
#include <linux/un.h>
59
#include <linux/fcntl.h>
60
#include <linux/termios.h>
61
#include <linux/socket.h>
62
#include <linux/sockios.h>
63
#include <linux/net.h>
64
#include <linux/in.h>
65
#include <linux/fs.h>
66
#include <linux/malloc.h>
67
#include <asm/segment.h>
68
#include <linux/skbuff.h>
69
#include <linux/netdevice.h>
70
#include <net/sock.h>
71
#include <net/tcp.h>
72
#include <net/af_unix.h>
73
#include <linux/proc_fs.h>
74
 
75
unix_socket *unix_socket_list=NULL;
76
 
77
#define min(a,b)        (((a)<(b))?(a):(b))
78
 
79
/*
80
 *      Make sure the unix name is null-terminated.
81
 */
82
 
83
static inline void unix_mkname(struct sockaddr_un * sunaddr, unsigned long len)
84
{
85
        if (len >= sizeof(*sunaddr))
86
                len = sizeof(*sunaddr)-1;
87
        ((char *)sunaddr)[len]=0;
88
}
89
 
90
/*
91
 *      Note: Sockets may not be removed _during_ an interrupt or net_bh
92
 *      handler using this technique. They can be added although we do not
93
 *      use this facility.
94
 */
95
 
96
static void unix_remove_socket(unix_socket *sk)
97
{
98
        unix_socket **s;
99
 
100
        cli();
101
        s=&unix_socket_list;
102
 
103
        while(*s!=NULL)
104
        {
105
                if(*s==sk)
106
                {
107
                        *s=sk->next;
108
                        sti();
109
                        return;
110
                }
111
                s=&((*s)->next);
112
        }
113
        sti();
114
}
115
 
116
static void unix_insert_socket(unix_socket *sk)
117
{
118
        cli();
119
        sk->next=unix_socket_list;
120
        unix_socket_list=sk;
121
        sti();
122
}
123
 
124
static unix_socket *unix_find_socket(struct inode *i)
125
{
126
        unix_socket *s;
127
        cli();
128
        s=unix_socket_list;
129
        while(s)
130
        {
131
                if(s->protinfo.af_unix.inode==i)
132
                {
133
                        sti();
134
                        return(s);
135
                }
136
                s=s->next;
137
        }
138
        sti();
139
        return(NULL);
140
}
141
 
142
/*
143
 *      Delete a unix socket. We have to allow for deferring this on a timer.
144
 */
145
 
146
static void unix_destroy_timer(unsigned long data)
147
{
148
        unix_socket *sk=(unix_socket *)data;
149
        if(sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
150
        {
151
                if(sk->protinfo.af_unix.name)
152
                        kfree(sk->protinfo.af_unix.name);
153
                sk_free(sk);
154
                return;
155
        }
156
 
157
        /*
158
         *      Retry;
159
         */
160
 
161
        sk->timer.expires=jiffies+10*HZ;        /* No real hurry try it every 10 seconds or so */
162
        add_timer(&sk->timer);
163
}
164
 
165
 
166
static void unix_delayed_delete(unix_socket *sk)
167
{
168
        sk->timer.data=(unsigned long)sk;
169
        sk->timer.expires=jiffies+HZ;           /* Normally 1 second after will clean up. After that we try every 10 */
170
        sk->timer.function=unix_destroy_timer;
171
        add_timer(&sk->timer);
172
}
173
 
174
static void unix_destroy_socket(unix_socket *sk)
175
{
176
        struct sk_buff *skb;
177
 
178
        unix_remove_socket(sk);
179
 
180
        while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
181
        {
182
                if(sk->state==TCP_LISTEN)
183
                {
184
                        unix_socket *osk=skb->sk;
185
                        osk->state=TCP_CLOSE;
186
                        kfree_skb(skb, FREE_WRITE);     /* Now surplus - free the skb first before the socket */
187
                        osk->state_change(osk);         /* So the connect wakes and cleans up (if any) */
188
                        /* osk will be destroyed when it gets to close or the timer fires */
189
                }
190
                else
191
                {
192
                        /* passed fds are erased in the kfree_skb hook */
193
                        kfree_skb(skb,FREE_WRITE);
194
                }
195
        }
196
 
197
        if(sk->protinfo.af_unix.inode!=NULL)
198
        {
199
                iput(sk->protinfo.af_unix.inode);
200
                sk->protinfo.af_unix.inode=NULL;
201
        }
202
 
203
        if(--sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
204
        {
205
                if(sk->protinfo.af_unix.name)
206
                        kfree(sk->protinfo.af_unix.name);
207
                sk_free(sk);
208
        }
209
        else
210
        {
211
                sk->dead=1;
212
                unix_delayed_delete(sk);        /* Try every so often until buffers are all freed */
213
        }
214
}
215
 
216
/*
217
 *      Fixme: We need async I/O on AF_UNIX doing next.
218
 */
219
 
220
static int unix_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
221
{
222
        return -EINVAL;
223
}
224
 
225
/*
226
 *      Yes socket options work with the new unix domain socketry!!!!!!!
227
 */
228
 
229
static int unix_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
230
{
231
        unix_socket *sk=sock->data;
232
        if(level!=SOL_SOCKET)
233
                return -EOPNOTSUPP;
234
        return sock_setsockopt(sk,level,optname,optval,optlen);
235
}
236
 
237
static int unix_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
238
{
239
        unix_socket *sk=sock->data;
240
        if(level!=SOL_SOCKET)
241
                return -EOPNOTSUPP;
242
        return sock_getsockopt(sk,level,optname,optval,optlen);
243
}
244
 
245
static int unix_listen(struct socket *sock, int backlog)
246
{
247
        unix_socket *sk=sock->data;
248
        if(sk->type!=SOCK_STREAM)
249
                return -EOPNOTSUPP;             /* Only stream sockets accept */
250
        if(sk->protinfo.af_unix.name==NULL)
251
                return -EINVAL;                 /* No listens on an unbound socket */
252
        sk->max_ack_backlog=backlog;
253
        sk->state=TCP_LISTEN;
254
        return 0;
255
}
256
 
257
static void def_callback1(struct sock *sk)
258
{
259
        if(!sk->dead)
260
                wake_up_interruptible(sk->sleep);
261
}
262
 
263
static void def_callback2(struct sock *sk, int len)
264
{
265
        if(!sk->dead)
266
        {
267
                wake_up_interruptible(sk->sleep);
268
                sock_wake_async(sk->socket, 1);
269
        }
270
}
271
 
272
static void def_callback3(struct sock *sk)
273
{
274
        if(!sk->dead)
275
        {
276
                wake_up_interruptible(sk->sleep);
277
                sock_wake_async(sk->socket, 2);
278
        }
279
}
280
 
281
static int unix_create(struct socket *sock, int protocol)
282
{
283
        unix_socket *sk;
284
        if(protocol && protocol != PF_UNIX)
285
                return -EPROTONOSUPPORT;
286
        sk=(unix_socket *)sk_alloc(GFP_KERNEL);
287
        if(sk==NULL)
288
                return -ENOMEM;
289
        switch(sock->type)
290
        {
291
                case SOCK_STREAM:
292
                        break;
293
                /*
294
                 *      Believe it or not BSD has AF_UNIX, SOCK_RAW though
295
                 *      nothing uses it.
296
                 */
297
                case SOCK_RAW:
298
                        sock->type=SOCK_DGRAM;
299
                case SOCK_DGRAM:
300
                        break;
301
                default:
302
                        sk_free(sk);
303
                        return -ESOCKTNOSUPPORT;
304
        }
305
        sk->type=sock->type;
306
        init_timer(&sk->timer);
307
        skb_queue_head_init(&sk->write_queue);
308
        skb_queue_head_init(&sk->receive_queue);
309
        skb_queue_head_init(&sk->back_log);
310
        sk->protinfo.af_unix.family=AF_UNIX;
311
        sk->protinfo.af_unix.inode=NULL;
312
        sk->protinfo.af_unix.locks=1;           /* Us */
313
        sk->protinfo.af_unix.readsem=MUTEX;     /* single task reading lock */
314
        sk->rcvbuf=SK_RMEM_MAX;
315
        sk->sndbuf=SK_WMEM_MAX;
316
        sk->allocation=GFP_KERNEL;
317
        sk->state=TCP_CLOSE;
318
        sk->priority=SOPRI_NORMAL;
319
        sk->state_change=def_callback1;
320
        sk->data_ready=def_callback2;
321
        sk->write_space=def_callback3;
322
        sk->error_report=def_callback1;
323
        sk->mtu=4096;
324
        sk->socket=sock;
325
        sock->data=(void *)sk;
326
        sk->sleep=sock->wait;
327
        unix_insert_socket(sk);
328
        return 0;
329
}
330
 
331
static int unix_dup(struct socket *newsock, struct socket *oldsock)
332
{
333
        return unix_create(newsock,0);
334
}
335
 
336
static int unix_release(struct socket *sock, struct socket *peer)
337
{
338
        unix_socket *sk=sock->data;
339
        unix_socket *skpair;
340
 
341
        /* May not have data attached */
342
 
343
        if(sk==NULL)
344
                return 0;
345
 
346
        sk->state_change(sk);
347
        sk->dead=1;
348
        skpair=(unix_socket *)sk->protinfo.af_unix.other;       /* Person we send to (default) */
349
        if(sk->type==SOCK_STREAM && skpair!=NULL && skpair->state!=TCP_LISTEN)
350
        {
351
                skpair->shutdown=SHUTDOWN_MASK;         /* No more writes */
352
                skpair->state_change(skpair);           /* Wake any blocked writes */
353
        }
354
        if(skpair!=NULL)
355
                skpair->protinfo.af_unix.locks--;       /* It may now die */
356
        sk->protinfo.af_unix.other=NULL;                /* No pair */
357
        unix_destroy_socket(sk);                        /* Try to flush out this socket. Throw out buffers at least */
358
        unix_gc();                                      /* Garbage collect fds */
359
 
360
        /*
361
         *      FIXME: BSD difference: In BSD all sockets connected to use get ECONNRESET and we die on the spot. In
362
         *      Linux we behave like files and pipes do and wait for the last dereference.
363
         */
364
 
365
        sock->data = NULL;
366
        sk->socket = NULL;
367
 
368
        return 0;
369
}
370
 
371
 
372
static unix_socket *unix_find_other(char *path, int *error)
373
{
374
        int old_fs;
375
        int err;
376
        struct inode *inode;
377
        unix_socket *u;
378
 
379
        old_fs=get_fs();
380
        set_fs(get_ds());
381
        err = open_namei(path, 2, S_IFSOCK, &inode, NULL);
382
        set_fs(old_fs);
383
        if(err<0)
384
        {
385
                *error=err;
386
                return NULL;
387
        }
388
        u=unix_find_socket(inode);
389
        iput(inode);
390
        if(u==NULL)
391
        {
392
                *error=-ECONNREFUSED;
393
                return NULL;
394
        }
395
        return u;
396
}
397
 
398
 
399
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
400
{
401
        struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
402
        unix_socket *sk=sock->data;
403
        int old_fs;
404
        int err;
405
 
406
        if(sk->protinfo.af_unix.name)
407
                return -EINVAL;         /* Already bound */
408
 
409
        if(addr_len>sizeof(struct sockaddr_un) || addr_len<3 || sunaddr->sun_family!=AF_UNIX)
410
                return -EINVAL;
411
        unix_mkname(sunaddr, addr_len);
412
        /*
413
         *      Put ourselves in the filesystem
414
         */
415
        if(sk->protinfo.af_unix.inode!=NULL)
416
                return -EINVAL;
417
 
418
        sk->protinfo.af_unix.name=kmalloc(addr_len+1, GFP_KERNEL);
419
        if(sk->protinfo.af_unix.name==NULL)
420
                return -ENOMEM;
421
        memcpy(sk->protinfo.af_unix.name, sunaddr->sun_path, addr_len+1);
422
 
423
        old_fs=get_fs();
424
        set_fs(get_ds());
425
 
426
        err=do_mknod(sk->protinfo.af_unix.name,S_IFSOCK|S_IRWXUGO,0);
427
        if(err==0)
428
                err=open_namei(sk->protinfo.af_unix.name, 2, S_IFSOCK, &sk->protinfo.af_unix.inode, NULL);
429
 
430
        set_fs(old_fs);
431
 
432
        if(err<0)
433
        {
434
                kfree_s(sk->protinfo.af_unix.name,addr_len+1);
435
                sk->protinfo.af_unix.name=NULL;
436
                if(err==-EEXIST)
437
                        return -EADDRINUSE;
438
                else
439
                        return err;
440
        }
441
 
442
        return 0;
443
 
444
}
445
 
446
static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
447
{
448
        unix_socket *sk=sock->data;
449
        struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
450
        unix_socket *other;
451
        struct sk_buff *skb;
452
        int err;
453
 
454
        if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
455
        {
456
                if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
457
                {
458
                        sock->state=SS_CONNECTED;
459
                        return 0;
460
                }
461
                if(sock->state==SS_CONNECTING && sk->state == TCP_CLOSE)
462
                {
463
                        sock->state=SS_UNCONNECTED;
464
                        return -ECONNREFUSED;
465
                }
466
                if(sock->state!=SS_CONNECTING)
467
                        return -EISCONN;
468
                if(flags&O_NONBLOCK)
469
                        return -EALREADY;
470
                /*
471
                 *      Drop through the connect up logic to the wait.
472
                 */
473
        }
474
 
475
        if(addr_len < sizeof(sunaddr->sun_family)+1 || sunaddr->sun_family!=AF_UNIX)
476
                return -EINVAL;
477
 
478
        unix_mkname(sunaddr, addr_len);
479
 
480
        if(sk->type==SOCK_DGRAM)
481
        {
482
                if(sk->protinfo.af_unix.other)
483
                {
484
                        sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
485
                        sk->protinfo.af_unix.other=NULL;
486
                        sock->state=SS_UNCONNECTED;
487
                }
488
                other=unix_find_other(sunaddr->sun_path, &err);
489
                if(other==NULL)
490
                        return err;
491
                if(other->type!=sk->type)
492
                        return -EPROTOTYPE;
493
                other->protinfo.af_unix.locks++;
494
                sk->protinfo.af_unix.other=other;
495
                sock->state=SS_CONNECTED;
496
                sk->state=TCP_ESTABLISHED;
497
                return 0;                        /* Done */
498
        }
499
 
500
 
501
        if(sock->state==SS_UNCONNECTED)
502
        {
503
                /*
504
                 *      Now ready to connect
505
                 */
506
 
507
                skb=sock_alloc_send_skb(sk, 0, 0, 0, &err); /* Marker object */
508
                if(skb==NULL)
509
                        return err;
510
                skb->sk=sk;                             /* So they know it is us */
511
                skb->free=1;
512
                skb->h.filp=NULL;
513
                sk->state=TCP_CLOSE;
514
                unix_mkname(sunaddr, addr_len);
515
                other=unix_find_other(sunaddr->sun_path, &err);
516
                if(other==NULL)
517
                {
518
                        kfree_skb(skb, FREE_WRITE);
519
                        return err;
520
                }
521
                if(other->type!=sk->type)
522
                {
523
                        kfree_skb(skb, FREE_WRITE);
524
                        return -EPROTOTYPE;
525
                }
526
                other->protinfo.af_unix.locks++;                /* Lock the other socket so it doesn't run off for a moment */
527
                other->ack_backlog++;
528
                sk->protinfo.af_unix.other=other;
529
                skb_queue_tail(&other->receive_queue,skb);
530
                sk->state=TCP_SYN_SENT;
531
                sock->state=SS_CONNECTING;
532
                sti();
533
                other->data_ready(other,0);              /* Wake up ! */
534
        }
535
 
536
 
537
        /* Wait for an accept */
538
 
539
        cli();
540
        while(sk->state==TCP_SYN_SENT)
541
        {
542
                if(flags&O_NONBLOCK)
543
                {
544
                        sti();
545
                        return -EINPROGRESS;
546
                }
547
                interruptible_sleep_on(sk->sleep);
548
                if(current->signal & ~current->blocked)
549
                {
550
                        sti();
551
                        return -ERESTARTSYS;
552
                }
553
        }
554
 
555
        /*
556
         *      Has the other end closed on us ?
557
         */
558
 
559
        if(sk->state==TCP_CLOSE)
560
        {
561
                sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
562
                sk->protinfo.af_unix.other=NULL;
563
                sock->state=SS_UNCONNECTED;
564
                sti();
565
                return -ECONNREFUSED;
566
        }
567
 
568
        /*
569
         *      Amazingly it has worked
570
         */
571
 
572
        sock->state=SS_CONNECTED;
573
        sti();
574
        return 0;
575
 
576
}
577
 
578
static int unix_socketpair(struct socket *a, struct socket *b)
579
{
580
        unix_socket *ska,*skb;
581
 
582
        ska=a->data;
583
        skb=b->data;
584
 
585
        /* Join our sockets back to back */
586
        ska->protinfo.af_unix.locks++;
587
        skb->protinfo.af_unix.locks++;
588
        ska->protinfo.af_unix.other=skb;
589
        skb->protinfo.af_unix.other=ska;
590
        ska->state=TCP_ESTABLISHED;
591
        skb->state=TCP_ESTABLISHED;
592
        return 0;
593
}
594
 
595
static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
596
{
597
        unix_socket *sk=sock->data;
598
        unix_socket *newsk, *tsk;
599
        struct sk_buff *skb;
600
 
601
        if(sk->type!=SOCK_STREAM)
602
        {
603
                return -EOPNOTSUPP;
604
        }
605
        if(sk->state!=TCP_LISTEN)
606
        {
607
                return -EINVAL;
608
        }
609
 
610
        newsk=newsock->data;
611
        if(sk->protinfo.af_unix.name!=NULL)
612
        {
613
                newsk->protinfo.af_unix.name=kmalloc(strlen(sk->protinfo.af_unix.name)+1, GFP_KERNEL);
614
                if(newsk->protinfo.af_unix.name==NULL)
615
                        return -ENOMEM;
616
                strcpy(newsk->protinfo.af_unix.name, sk->protinfo.af_unix.name);
617
        }
618
 
619
        do
620
        {
621
                cli();
622
                skb=skb_dequeue(&sk->receive_queue);
623
                if(skb==NULL)
624
                {
625
                        if(flags&O_NONBLOCK)
626
                        {
627
                                sti();
628
                                return -EAGAIN;
629
                        }
630
                        interruptible_sleep_on(sk->sleep);
631
                        if(current->signal & ~current->blocked)
632
                        {
633
                                sti();
634
                                return -ERESTARTSYS;
635
                        }
636
                        sti();
637
                }
638
        }
639
        while(skb==NULL);
640
        tsk=skb->sk;
641
        kfree_skb(skb, FREE_WRITE);     /* The buffer is just used as a tag */
642
        sk->ack_backlog--;
643
        newsk->protinfo.af_unix.other=tsk;
644
        tsk->protinfo.af_unix.other=newsk;
645
        tsk->state=TCP_ESTABLISHED;
646
        newsk->state=TCP_ESTABLISHED;
647
        newsk->protinfo.af_unix.locks++;        /* Swap lock over */
648
        sk->protinfo.af_unix.locks--;   /* Locked to child socket not master */
649
        tsk->protinfo.af_unix.locks++;  /* Back lock */
650
        sti();
651
        tsk->state_change(tsk);         /* Wake up any sleeping connect */
652
        sock_wake_async(tsk->socket, 0);
653
        return 0;
654
}
655
 
656
static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
657
{
658
        unix_socket *sk=sock->data;
659
        struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
660
 
661
        if(peer)
662
        {
663
                if(sk->protinfo.af_unix.other==NULL)
664
                        return -ENOTCONN;
665
                sk=sk->protinfo.af_unix.other;
666
        }
667
        sunaddr->sun_family=AF_UNIX;
668
        if(sk->protinfo.af_unix.name==NULL)
669
        {
670
                *sunaddr->sun_path=0;
671
                *uaddr_len=sizeof(sunaddr->sun_family)+1;
672
                return 0;                /* Not bound */
673
        }
674
        *uaddr_len=sizeof(sunaddr->sun_family)+strlen(sk->protinfo.af_unix.name)+1;
675
        strcpy(sunaddr->sun_path,sk->protinfo.af_unix.name);            /* 108 byte limited */
676
        return 0;
677
}
678
 
679
/*
680
 *      Support routines for struct cmsghdr handling
681
 */
682
 
683
static struct cmsghdr *unix_copyrights(void *userp, int len) /* AT&T ? */
684
{
685
        struct cmsghdr *cm;
686
 
687
        if(len>256|| len <=0)
688
                return NULL;
689
        cm=kmalloc(len, GFP_KERNEL);
690
        memcpy_fromfs(cm, userp, len);
691
        return cm;
692
}
693
 
694
/*
695
 *      Return a header block
696
 */
697
 
698
static void unix_returnrights(void *userp, int len, struct cmsghdr *cm)
699
{
700
        memcpy_tofs(userp, cm, len);
701
        kfree(cm);
702
}
703
 
704
/*
705
 *      Copy file descriptors into system space.
706
 *      Return number copied or negative error code
707
 */
708
 
709
static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
710
{
711
        int num=cmsg->cmsg_len-sizeof(struct cmsghdr);
712
        int i;
713
        int *fdp=(int *)cmsg->cmsg_data;
714
 
715
        num /= sizeof(int);     /* Odd bytes are forgotten in BSD not errored */
716
        if (num >= UNIX_MAX_FD)
717
                return -EINVAL;
718
 
719
        /*
720
         *      Verify the descriptors.
721
         */
722
 
723
        for(i=0; i< num; i++)
724
        {
725
                int fd;
726
 
727
                fd = fdp[i];
728
                if (fd < 0 || fd >= NR_OPEN)
729
                        return -EBADF;
730
                if (current->files->fd[fd]==NULL)
731
                        return -EBADF;
732
        }
733
 
734
        /* add another reference to these files */
735
        for(i=0; i< num; i++)
736
        {
737
                fp[i]=current->files->fd[fdp[i]];
738
                fp[i]->f_count++;
739
                unix_inflight(fp[i]);
740
        }
741
 
742
        return num;
743
}
744
 
745
/*
746
 *      Free the descriptors in the array
747
 */
748
 
749
static void unix_fd_free(struct sock *sk, struct file **fp, int num)
750
{
751
        int i;
752
        for(i=0;i<num;i++)
753
        {
754
                close_fp(fp[i]);
755
                unix_notinflight(fp[i]);
756
        }
757
}
758
 
759
 
760
/*
761
 *      Perform the AF_UNIX file descriptor pass out functionality. This
762
 *      is nasty and messy as is the whole design of BSD file passing.
763
 */
764
 
765
static void unix_detach_fds(struct sk_buff *skb, struct cmsghdr *cmsg)
766
{
767
        int i;
768
        /* count of space in parent for fds */
769
        int cmnum;
770
        struct file **fp;
771
        int *cmfptr;
772
        int fdnum;
773
 
774
        cmfptr = NULL;
775
        cmnum = 0;
776
        if (cmsg)
777
        {
778
                cmnum = (cmsg->cmsg_len-sizeof(struct cmsghdr)) / sizeof(int);
779
                cmfptr = (int *)&cmsg->cmsg_data;
780
        }
781
 
782
        fdnum = *(int *)skb->h.filp;
783
        fp = (struct file **)(skb->h.filp+sizeof(long));
784
 
785
        if (cmnum > fdnum)
786
                cmnum = fdnum;
787
 
788
        /*
789
         *      Copy those that fit
790
         */
791
        for (i = 0 ; i < cmnum ; i++)
792
        {
793
                int new_fd = get_unused_fd();
794
                if (new_fd < 0)
795
                        break;
796
                current->files->fd[new_fd]=fp[i];
797
                *cmfptr++ = new_fd;
798
                unix_notinflight(fp[i]);
799
        }
800
        /*
801
         *      Dump those that don't
802
         */
803
        for( ; i < fdnum ; i++)
804
        {
805
                close_fp(fp[i]);
806
                unix_notinflight(fp[i]);
807
        }
808
        kfree(skb->h.filp);
809
        skb->h.filp=NULL;
810
 
811
        /* no need to use destructor */
812
        skb->destructor = NULL;
813
}
814
 
815
static void unix_destruct_fds(struct sk_buff *skb)
816
{
817
        unix_detach_fds(skb,NULL);
818
}
819
 
820
/*
821
 *      Attach the file descriptor array to an sk_buff
822
 */
823
static void unix_attach_fds(int fpnum,struct file **fp,struct sk_buff *skb)
824
{
825
 
826
        skb->h.filp = kmalloc(sizeof(long)+fpnum*sizeof(struct file *),
827
                                                        GFP_KERNEL);
828
        /* number of descriptors starts block */
829
        *(int *)skb->h.filp = fpnum;
830
        /* actual  descriptors */
831
        memcpy(skb->h.filp+sizeof(long),fp,fpnum*sizeof(struct file *));
832
        skb->destructor = unix_destruct_fds;
833
}
834
 
835
/*
836
 *      Send AF_UNIX data.
837
 */
838
 
839
static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
840
{
841
        unix_socket *sk=sock->data;
842
        unix_socket *other;
843
        struct sockaddr_un *sunaddr=msg->msg_name;
844
        int err,size;
845
        struct sk_buff *skb;
846
        int limit=0;
847
        int sent=0;
848
        struct file *fp[UNIX_MAX_FD];
849
        /* number of fds waiting to be passed, 0 means either
850
         * no fds to pass or they've already been passed
851
         */
852
        int fpnum=0;
853
 
854
        if(sk->err)
855
                return sock_error(sk);
856
 
857
        if(flags&MSG_OOB)
858
                return -EOPNOTSUPP;
859
 
860
        if(flags)       /* For now */ {
861
                return -EINVAL;
862
        }
863
 
864
        if(sk->shutdown&SEND_SHUTDOWN)
865
        {
866
                send_sig(SIGPIPE,current,0);
867
                return -EPIPE;
868
        }
869
 
870
        if(sunaddr!=NULL)
871
        {
872
                if(sock->type==SOCK_STREAM)
873
                {
874
                        if(sk->state==TCP_ESTABLISHED)
875
                                return -EISCONN;
876
                        else
877
                                return -EOPNOTSUPP;
878
                }
879
        }
880
 
881
        if(sunaddr==NULL)
882
        {
883
                if(sk->protinfo.af_unix.other==NULL)
884
                        return -ENOTCONN;
885
        }
886
 
887
        /*
888
         *      A control message has been attached.
889
         */
890
        if(msg->msg_control)
891
        {
892
                struct cmsghdr *cm=unix_copyrights(msg->msg_control,
893
                                                msg->msg_controllen);
894
                if(cm==NULL || msg->msg_controllen<sizeof(struct cmsghdr) ||
895
                   cm->cmsg_type!=SCM_RIGHTS ||
896
                   cm->cmsg_level!=SOL_SOCKET ||
897
                   msg->msg_controllen!=cm->cmsg_len)
898
                {
899
                        kfree(cm);
900
                        return -EINVAL;
901
                }
902
                fpnum=unix_fd_copy(sk,cm,fp);
903
                kfree(cm);
904
                if(fpnum<0) {
905
                        return fpnum;
906
                }
907
        }
908
 
909
        while(sent < len)
910
        {
911
                /*
912
                 *      Optimisation for the fact that under 0.01% of X messages typically
913
                 *      need breaking up.
914
                 */
915
 
916
                size=len-sent;
917
 
918
                if(size>(sk->sndbuf-sizeof(struct sk_buff))/2)  /* Keep two messages in the pipe so it schedules better */
919
                {
920
                        if(sock->type==SOCK_DGRAM)
921
                        {
922
                                unix_fd_free(sk,fp,fpnum);
923
                                return -EMSGSIZE;
924
                        }
925
                        size=(sk->sndbuf-sizeof(struct sk_buff))/2;
926
                }
927
                /*
928
                 *      Keep to page sized kmalloc()'s as various people
929
                 *      have suggested. Big mallocs stress the vm too
930
                 *      much.
931
                 */
932
#define MAX_ALLOC (PAGE_SIZE*7/8)
933
                if(size > MAX_ALLOC && sock->type!=SOCK_DGRAM)
934
                        limit = MAX_ALLOC;      /* Fall back to 4K if we can't grab a big buffer this instant */
935
                else
936
                        limit = 0;       /* Otherwise just grab and wait */
937
 
938
                /*
939
                 *      Grab a buffer
940
                 */
941
 
942
                skb=sock_alloc_send_skb(sk,size,limit,nonblock, &err);
943
 
944
                if(skb==NULL)
945
                {
946
                        unix_fd_free(sk,fp,fpnum);
947
                        if(sent)
948
                        {
949
                                sk->err=-err;
950
                                return sent;
951
                        }
952
                        return err;
953
                }
954
                size=skb_tailroom(skb);         /* If we dropped back on a limit then our skb is smaller */
955
 
956
                skb->sk=sk;
957
                skb->free=1;
958
 
959
                if(fpnum)
960
                {
961
                        unix_attach_fds(fpnum,fp,skb);
962
                        fpnum=0;
963
                }
964
                else
965
                        skb->h.filp=NULL;
966
 
967
                memcpy_fromiovec(skb_put(skb,size),msg->msg_iov, size);
968
 
969
                cli();
970
                if(sunaddr==NULL)
971
                {
972
                        other=sk->protinfo.af_unix.other;
973
                        if(sock->type==SOCK_DGRAM && other->dead)
974
                        {
975
                                other->protinfo.af_unix.locks--;
976
                                sk->protinfo.af_unix.other=NULL;
977
                                sock->state=SS_UNCONNECTED;
978
                                sti();
979
                                kfree_skb(skb, FREE_WRITE);
980
                                /*
981
                                 *      Check with 1003.1g - what should
982
                                 *      datagram error
983
                                 */
984
                                if (!sent)
985
                                        sent = -ECONNRESET;
986
                                return sent;
987
                        }
988
                        /*
989
                         *      Stream sockets SIGPIPE
990
                         */
991
                        if(sock->type==SOCK_STREAM && other->dead)
992
                        {
993
                                kfree_skb(skb, FREE_WRITE);
994
                                sti();
995
                                if(!sent)
996
                                {
997
                                        send_sig(SIGPIPE,current,0);
998
                                        sent = -EPIPE;
999
                                }
1000
                                return sent;
1001
                        }
1002
                }
1003
                else
1004
                {
1005
                        unix_mkname(sunaddr, msg->msg_namelen);
1006
                        other=unix_find_other(sunaddr->sun_path, &err);
1007
                        if(other==NULL)
1008
                        {
1009
                                sti();
1010
                                kfree_skb(skb, FREE_WRITE);
1011
                                if(sent)
1012
                                        return sent;
1013
                                else
1014
                                        return err;
1015
                        }
1016
                }
1017
                skb_queue_tail(&other->receive_queue, skb);
1018
                sti();
1019
                /* if we sent an fd, only do it once */
1020
                other->data_ready(other,size);
1021
                sent+=size;
1022
        }
1023
        return sent;
1024
}
1025
 
1026
/*
1027
 *      Sleep until data has arrive. But check for races..
1028
 */
1029
 
1030
static void unix_data_wait(unix_socket * sk)
1031
{
1032
        cli();
1033
        if (!skb_peek(&sk->receive_queue)) {
1034
                sk->socket->flags |= SO_WAITDATA;
1035
                interruptible_sleep_on(sk->sleep);
1036
                sk->socket->flags &= ~SO_WAITDATA;
1037
        }
1038
        sti();
1039
}
1040
 
1041
static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
1042
{
1043
        unix_socket *sk=sock->data;
1044
        struct sockaddr_un *sunaddr=msg->msg_name;
1045
        struct sk_buff *skb;
1046
        int copied=0;
1047
        unsigned char *sp;
1048
        int len;
1049
        int num;
1050
        struct iovec *iov=msg->msg_iov;
1051
        struct cmsghdr *cm=NULL;
1052
        int ct=msg->msg_iovlen;
1053
 
1054
        if(flags&MSG_OOB)
1055
                return -EOPNOTSUPP;
1056
 
1057
        if(addr_len)
1058
                *addr_len=0;
1059
 
1060
        if(sk->err)
1061
                return sock_error(sk);
1062
 
1063
        if(msg->msg_control)
1064
        {
1065
                cm=unix_copyrights(msg->msg_control,
1066
                        msg->msg_controllen);
1067
                if(msg->msg_controllen<sizeof(struct cmsghdr)
1068
#if 0 
1069
/*              investigate this further -- Stevens example doesn't seem to care */
1070
                ||
1071
                   cm->cmsg_type!=SCM_RIGHTS ||
1072
                   cm->cmsg_level!=SOL_SOCKET ||
1073
                   msg->msg_controllen!=cm->cmsg_len
1074
#endif
1075
                )
1076
                {
1077
                        kfree(cm);
1078
/*                      printk("recvmsg: Bad msg_control\n");*/
1079
                        return -EINVAL;
1080
                }
1081
        }
1082
 
1083
        down(&sk->protinfo.af_unix.readsem);            /* Lock the socket */
1084
        while(ct--)
1085
        {
1086
                int done=0;
1087
                sp=iov->iov_base;
1088
                len=iov->iov_len;
1089
                iov++;
1090
 
1091
                while(done<len)
1092
                {
1093
                        if (copied && (flags & MSG_PEEK))
1094
                                goto out;
1095
                        if (copied == size)
1096
                                goto out;
1097
                        skb=skb_dequeue(&sk->receive_queue);
1098
                        if(skb==NULL)
1099
                        {
1100
                                up(&sk->protinfo.af_unix.readsem);
1101
                                if(sk->shutdown & RCV_SHUTDOWN)
1102
                                        return copied;
1103
                                if(copied)
1104
                                        return copied;
1105
                                if(noblock)
1106
                                        return -EAGAIN;
1107
                                unix_data_wait(sk);
1108
                                if(current->signal & ~current->blocked)
1109
                                        return -ERESTARTSYS;
1110
                                down(&sk->protinfo.af_unix.readsem);
1111
                                continue;
1112
                        }
1113
                        if(msg->msg_name!=NULL)
1114
                        {
1115
                                sunaddr->sun_family=AF_UNIX;
1116
                                if(skb->sk->protinfo.af_unix.name)
1117
                                {
1118
                                        memcpy(sunaddr->sun_path, skb->sk->protinfo.af_unix.name, 108);
1119
                                        if(addr_len)
1120
                                                *addr_len=strlen(sunaddr->sun_path)+sizeof(short);
1121
                                }
1122
                                else
1123
                                        if(addr_len)
1124
                                                *addr_len=sizeof(short);
1125
                        }
1126
 
1127
                        num=min(skb->len,len-done);
1128
                        memcpy_tofs(sp, skb->data, num);
1129
 
1130
                        if (skb->h.filp!=NULL)
1131
                                unix_detach_fds(skb,cm);
1132
 
1133
                        copied+=num;
1134
                        done+=num;
1135
                        sp+=num;
1136
                        if (!(flags & MSG_PEEK))
1137
                                skb_pull(skb, num);
1138
                        /* put the skb back if we didn't use it up.. */
1139
                        if (skb->len) {
1140
                                skb_queue_head(&sk->receive_queue, skb);
1141
                                continue;
1142
                        }
1143
                        kfree_skb(skb, FREE_WRITE);
1144
                        if(sock->type==SOCK_DGRAM || cm)
1145
                                goto out;
1146
                }
1147
        }
1148
out:
1149
        up(&sk->protinfo.af_unix.readsem);
1150
        if(cm)
1151
                unix_returnrights(msg->msg_control,msg->msg_controllen,cm);
1152
        return copied;
1153
}
1154
 
1155
static int unix_shutdown(struct socket *sock, int mode)
1156
{
1157
        unix_socket *sk=(unix_socket *)sock->data;
1158
        unix_socket *other=sk->protinfo.af_unix.other;
1159
 
1160
        mode++;
1161
 
1162
        if(mode&SEND_SHUTDOWN)
1163
        {
1164
                sk->shutdown|=SEND_SHUTDOWN;
1165
                sk->state_change(sk);
1166
                if(other)
1167
                {
1168
                        other->shutdown|=RCV_SHUTDOWN;
1169
                        other->state_change(other);
1170
                }
1171
        }
1172
        other=sk->protinfo.af_unix.other;
1173
        if(mode&RCV_SHUTDOWN)
1174
        {
1175
                sk->shutdown|=RCV_SHUTDOWN;
1176
                sk->state_change(sk);
1177
                if(other)
1178
                {
1179
                        other->shutdown|=SEND_SHUTDOWN;
1180
                        other->state_change(other);
1181
                }
1182
        }
1183
        return 0;
1184
}
1185
 
1186
 
1187
static int unix_select(struct socket *sock,  int sel_type, select_table *wait)
1188
{
1189
        return datagram_select(sock->data,sel_type,wait);
1190
}
1191
 
1192
static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1193
{
1194
        unix_socket *sk=sock->data;
1195
        int err;
1196
        long amount=0;
1197
 
1198
        switch(cmd)
1199
        {
1200
 
1201
                case TIOCOUTQ:
1202
                        err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
1203
                        if(err)
1204
                                return err;
1205
                        amount=sk->sndbuf-sk->wmem_alloc;
1206
                        if(amount<0)
1207
                                amount=0;
1208
                        put_fs_long(amount,(unsigned long *)arg);
1209
                        return 0;
1210
                case TIOCINQ:
1211
                {
1212
                        struct sk_buff *skb;
1213
                        if(sk->state==TCP_LISTEN)
1214
                                return -EINVAL;
1215
                        /* These two are safe on a single CPU system as only user tasks fiddle here */
1216
                        if((skb=skb_peek(&sk->receive_queue))!=NULL)
1217
                                amount=skb->len;
1218
                        err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
1219
                        if(err)
1220
                                return err;
1221
                        put_fs_long(amount,(unsigned long *)arg);
1222
                        return 0;
1223
                }
1224
 
1225
                default:
1226
                        return -EINVAL;
1227
        }
1228
        /*NOTREACHED*/
1229
        return(0);
1230
}
1231
 
1232
#ifdef CONFIG_PROC_FS
1233
static int unix_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
1234
{
1235
        off_t pos=0;
1236
        off_t begin=0;
1237
        int len=0;
1238
        unix_socket *s=unix_socket_list;
1239
 
1240
        len+= sprintf(buffer,"Num       RefCount Protocol Flags    Type St "
1241
            "Inode Path\n");
1242
 
1243
        while(s!=NULL)
1244
        {
1245
                len+=sprintf(buffer+len,"%p: %08X %08X %08lX %04X %02X %5ld",
1246
                        s,
1247
                        s->protinfo.af_unix.locks,
1248
                        0,
1249
                        s->socket->flags,
1250
                        s->socket->type,
1251
                        s->socket->state,
1252
                        s->socket->inode ? s->socket->inode->i_ino : 0);
1253
                if(s->protinfo.af_unix.name!=NULL)
1254
                        len+=sprintf(buffer+len, " %s\n", s->protinfo.af_unix.name);
1255
                else
1256
                        buffer[len++]='\n';
1257
 
1258
                pos=begin+len;
1259
                if(pos<offset)
1260
                {
1261
                        len=0;
1262
                        begin=pos;
1263
                }
1264
                if(pos>offset+length)
1265
                        break;
1266
                s=s->next;
1267
        }
1268
        *start=buffer+(offset-begin);
1269
        len-=(offset-begin);
1270
        if(len>length)
1271
                len=length;
1272
        return len;
1273
}
1274
#endif
1275
 
1276
struct proto_ops unix_proto_ops = {
1277
        AF_UNIX,
1278
 
1279
        unix_create,
1280
        unix_dup,
1281
        unix_release,
1282
        unix_bind,
1283
        unix_connect,
1284
        unix_socketpair,
1285
        unix_accept,
1286
        unix_getname,
1287
        unix_select,
1288
        unix_ioctl,
1289
        unix_listen,
1290
        unix_shutdown,
1291
        unix_setsockopt,
1292
        unix_getsockopt,
1293
        unix_fcntl,
1294
        unix_sendmsg,
1295
        unix_recvmsg
1296
};
1297
 
1298
#ifdef CONFIG_PROC_FS
1299
static struct proc_dir_entry proc_net_unix = {
1300
        PROC_NET_UNIX,  4, "unix",
1301
        S_IFREG | S_IRUGO, 1, 0, 0,
1302
        0, &proc_net_inode_operations,
1303
        unix_get_info
1304
};
1305
#endif
1306
 
1307
 
1308
void unix_proto_init(struct net_proto *pro)
1309
{
1310
        printk(KERN_INFO "NET3: Unix domain sockets 0.13 for Linux NET3.035.\n");
1311
        sock_register(unix_proto_ops.family, &unix_proto_ops);
1312
#ifdef CONFIG_PROC_FS
1313
        proc_net_register(&proc_net_unix);
1314
#endif
1315
}
1316
/*
1317
 * Local variables:
1318
 *  compile-command: "gcc -g -D__KERNEL__ -Wall -O6 -I/usr/src/linux/include -c af_unix.c"
1319
 * End:
1320
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.