root/net/unix/af_unix.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unix_mkname
  2. unix_remove_socket
  3. unix_insert_socket
  4. unix_find_socket
  5. unix_destroy_timer
  6. unix_delayed_delete
  7. unix_destroy_socket
  8. unix_fcntl
  9. unix_setsockopt
  10. unix_getsockopt
  11. unix_listen
  12. def_callback1
  13. def_callback2
  14. def_callback3
  15. unix_create
  16. unix_dup
  17. unix_release
  18. unix_find_other
  19. unix_bind
  20. unix_connect
  21. unix_socketpair
  22. unix_accept
  23. unix_getname
  24. unix_sendmsg
  25. unix_recvmsg
  26. unix_shutdown
  27. unix_select
  28. unix_ioctl
  29. unix_get_info
  30. unix_recvfrom
  31. unix_read
  32. unix_recv
  33. unix_sendto
  34. unix_write
  35. unix_send
  36. unix_proto_init

   1 /*
   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 a trivial part
   9  *              of the exercise.
  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  */
  21 
  22 #include <linux/config.h>
  23 #include <linux/kernel.h>
  24 #include <linux/major.h>
  25 #include <linux/signal.h>
  26 #include <linux/sched.h>
  27 #include <linux/errno.h>
  28 #include <linux/string.h>
  29 #include <linux/stat.h>
  30 #include <linux/socket.h>
  31 #include <linux/un.h>
  32 #include <linux/fcntl.h>
  33 #include <linux/termios.h>
  34 #include <linux/socket.h>
  35 #include <linux/sockios.h>
  36 #include <linux/net.h>
  37 #include <linux/in.h>
  38 #include <linux/fs.h>
  39 #include <linux/malloc.h>
  40 #include <asm/segment.h>
  41 #include <linux/skbuff.h>
  42 #include <linux/netdevice.h>
  43 #include <net/sock.h>
  44 #include <net/tcp.h>
  45 #include <net/af_unix.h>
  46 #include <linux/proc_fs.h>
  47 
  48 static unix_socket *volatile unix_socket_list=NULL;
  49 
  50 #define min(a,b)        (((a)<(b))?(a):(b))
  51 
  52 /*
  53  * Make sure the unix name is null-terminated.
  54  */
  55 static inline void unix_mkname(struct sockaddr_un * sun, unsigned long len)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         if (len >= sizeof(*sun))
  58                 len = sizeof(*sun)-1;
  59         ((char *)sun)[len]=0;
  60 }
  61 
  62 /*
  63  *      Note: Sockets may not be removed _during_ an interrupt or net_bh
  64  *      handler using this technique. They can be added although we do not
  65  *      use this facility.
  66  */
  67  
  68 static void unix_remove_socket(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         unix_socket *s;
  71         
  72         cli();
  73         s=unix_socket_list;
  74         if(s==sk)
  75         {
  76                 unix_socket_list=s->next;
  77                 sti();
  78                 return;
  79         }
  80         while(s && s->next)
  81         {
  82                 if(s->next==sk)
  83                 {
  84                         s->next=sk->next;
  85                         sti();
  86                         return;
  87                 }
  88                 s=s->next;
  89         }
  90         sti();
  91 }
  92 
  93 static void unix_insert_socket(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  94 {
  95         cli();
  96         sk->next=unix_socket_list;
  97         unix_socket_list=sk;
  98         sti();
  99 }
 100 
 101 static unix_socket *unix_find_socket(struct inode *i)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         unix_socket *s;
 104         cli();
 105         s=unix_socket_list;
 106         while(s)
 107         {
 108                 if(s->protinfo.af_unix.inode==i)
 109                 {
 110                         sti();
 111                         return(s);
 112                 }
 113                 s=s->next;
 114         }
 115         sti();
 116         return(NULL);
 117 }
 118 
 119 /*
 120  *      Delete a unix socket. We have to allow for deferring this on a timer.
 121  */
 122 
 123 static void unix_destroy_timer(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         unix_socket *sk=(unix_socket *)data;
 126         if(sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
 127         {
 128                 if(sk->protinfo.af_unix.name)
 129                         kfree(sk->protinfo.af_unix.name);
 130                 kfree_s(sk,sizeof(*sk));
 131                 return;
 132         }
 133         
 134         /*
 135          *      Retry;
 136          */
 137          
 138         init_timer(&sk->timer);
 139         sk->timer.expires=jiffies+10*HZ;        /* No real hurry try it every 10 seconds or so */
 140         add_timer(&sk->timer);
 141 }
 142          
 143          
 144 static void unix_delayed_delete(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         init_timer(&sk->timer);
 147         sk->timer.data=(unsigned long)sk;
 148         sk->timer.expires=jiffies+HZ;           /* Normally 1 second after will clean up. After that we try every 10 */
 149         sk->timer.function=unix_destroy_timer;
 150         add_timer(&sk->timer);
 151 }
 152         
 153 static void unix_destroy_socket(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155         struct sk_buff *skb;
 156         unix_remove_socket(sk);
 157         
 158         while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 159         {
 160                 if(sk->state==TCP_LISTEN)
 161                 {
 162                         unix_socket *osk=skb->sk;
 163                         osk->state=TCP_CLOSE;
 164                         kfree_skb(skb, FREE_WRITE);     /* Now surplus - free the skb first before the socket */
 165                         osk->state_change(osk);         /* So the connect wakes and cleans up (if any) */
 166                         /* osk will be destroyed when it gets to close or the timer fires */                    
 167                 }
 168                 else
 169                 {
 170 /*                      unix_kill_credentials(skb);     *//* Throw out any passed fd's */
 171                         kfree_skb(skb,FREE_WRITE);
 172                 }
 173         }
 174         
 175         if(sk->protinfo.af_unix.inode!=NULL)
 176         {
 177                 iput(sk->protinfo.af_unix.inode);
 178                 sk->protinfo.af_unix.inode=NULL;
 179         }
 180         
 181         if(--sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
 182         {
 183                 if(sk->protinfo.af_unix.name)
 184                         kfree(sk->protinfo.af_unix.name);
 185                 kfree_s(sk,sizeof(*sk));
 186         }
 187         else
 188         {
 189                 sk->dead=1;
 190                 unix_delayed_delete(sk);        /* Try every so often until buffers are all freed */
 191         }
 192 }
 193 
 194 /*
 195  *      Fixme: We need async I/O on AF_UNIX doing next.
 196  */
 197  
 198 static int unix_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 199 {
 200         return -EINVAL;
 201 }
 202 
 203 /*
 204  *      Yes socket options work with the new unix domain socketry!!!!!!!
 205  */
 206  
 207 static int unix_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         unix_socket *sk=sock->data;
 210         if(level!=SOL_SOCKET)
 211                 return -EOPNOTSUPP;
 212         return sock_setsockopt(sk,level,optname,optval,optlen); 
 213 }
 214 
 215 static int unix_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217         unix_socket *sk=sock->data;
 218         if(level!=SOL_SOCKET)
 219                 return -EOPNOTSUPP;
 220         return sock_getsockopt(sk,level,optname,optval,optlen);
 221 }
 222 
 223 static int unix_listen(struct socket *sock, int backlog)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         unix_socket *sk=sock->data;
 226         if(sk->type!=SOCK_STREAM)
 227                 return -EOPNOTSUPP;             /* Only stream sockets accept */
 228         sk->max_ack_backlog=backlog;
 229         sk->state=TCP_LISTEN;
 230         return 0;
 231 }
 232 
 233 static void def_callback1(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         if(!sk->dead)
 236                 wake_up_interruptible(sk->sleep);
 237 }
 238 
 239 static void def_callback2(struct sock *sk, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 240 {
 241         if(!sk->dead)
 242         {
 243                 wake_up_interruptible(sk->sleep);
 244                 sock_wake_async(sk->socket, 1);
 245         }
 246 }
 247 
 248 static void def_callback3(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 249 {
 250         if(!sk->dead)
 251         {
 252                 wake_up_interruptible(sk->sleep);
 253                 sock_wake_async(sk->socket, 2);
 254         }
 255 }
 256 
 257 static int unix_create(struct socket *sock, int protocol)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         unix_socket *sk;
 260 /*      printk("Unix create\n");*/
 261         if(protocol && protocol != PF_UNIX)
 262                 return -EPROTONOSUPPORT;
 263         sk=(unix_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
 264         if(sk==NULL)
 265                 return -ENOMEM;
 266         sk->type=sock->type;
 267         switch(sock->type)
 268         {
 269                 case SOCK_STREAM:
 270                         break;
 271                 case SOCK_DGRAM:
 272                         break;
 273                 default:
 274                         kfree_s(sk,sizeof(*sk));
 275                         return -ESOCKTNOSUPPORT;
 276         }
 277         skb_queue_head_init(&sk->write_queue);
 278         skb_queue_head_init(&sk->receive_queue);
 279         skb_queue_head_init(&sk->back_log);
 280         sk->protinfo.af_unix.family=AF_UNIX;
 281         sk->protinfo.af_unix.inode=NULL;
 282         sk->protinfo.af_unix.locks=1;   /* Us */
 283         sk->protinfo.af_unix.readsem=MUTEX;     /* single task reading lock */
 284         sk->protinfo.af_unix.name=NULL;
 285         sk->protinfo.af_unix.other=NULL;
 286         sk->protocol=0;
 287         sk->rmem_alloc=0;
 288         sk->wmem_alloc=0;
 289         sk->dead=0;
 290         sk->next=NULL;
 291         sk->broadcast=0;
 292         sk->rcvbuf=SK_RMEM_MAX;
 293         sk->sndbuf=SK_WMEM_MAX;
 294         sk->inuse=0;
 295         sk->debug=0;
 296         sk->prot=NULL;
 297         sk->err=0;
 298         sk->localroute=0;
 299         sk->send_head=NULL;
 300         sk->state=TCP_CLOSE;
 301         sk->priority=SOPRI_NORMAL;
 302         sk->ack_backlog=0;
 303         sk->shutdown=0;
 304         sk->state_change=def_callback1;
 305         sk->data_ready=def_callback2;
 306         sk->write_space=def_callback3;
 307         sk->error_report=def_callback1;
 308         sk->mtu=4096;
 309         sk->socket=sock;
 310         sock->data=(void *)sk;
 311         sk->sleep=sock->wait;
 312         sk->zapped=0;
 313         unix_insert_socket(sk);
 314         return 0;
 315 }
 316 
 317 static int unix_dup(struct socket *newsock, struct socket *oldsock)
     /* [previous][next][first][last][top][bottom][index][help] */
 318 {
 319         return unix_create(newsock,0);
 320 }
 321 
 322 static int unix_release(struct socket *sock, struct socket *peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324         unix_socket *sk=sock->data;
 325         unix_socket *skpair;
 326         
 327         /* May not have data attached */
 328         
 329         if(sk==NULL)
 330                 return 0;
 331                 
 332         sk->state_change(sk);
 333         sk->dead=1;
 334         skpair=(unix_socket *)sk->protinfo.af_unix.other;       /* Person we send to (default) */
 335         if(sk->type==SOCK_STREAM && skpair!=NULL && skpair->state!=TCP_LISTEN)
 336         {
 337                 skpair->shutdown=SHUTDOWN_MASK;         /* No more writes */
 338                 skpair->state_change(skpair);           /* Wake any blocked writes */
 339         }
 340         if(skpair!=NULL)
 341                 skpair->protinfo.af_unix.locks--;               /* It may now die */
 342         sk->protinfo.af_unix.other=NULL;                        /* No pair */
 343         unix_destroy_socket(sk);                        /* Try and flush out this socket. Throw our buffers at least */
 344         return 0;
 345 }
 346 
 347 
 348 static unix_socket *unix_find_other(char *path, int *error)
     /* [previous][next][first][last][top][bottom][index][help] */
 349 {
 350         int old_fs;
 351         int err;
 352         struct inode *inode;
 353         unix_socket *u;
 354         
 355         old_fs=get_fs();
 356         set_fs(get_ds());
 357         err = open_namei(path, 2, S_IFSOCK, &inode, NULL);
 358         set_fs(old_fs);
 359         if(err<0)
 360         {
 361                 *error=err;
 362                 return NULL;
 363         }
 364         u=unix_find_socket(inode);
 365         iput(inode);
 366         if(u==NULL)
 367         {
 368                 *error=-ECONNREFUSED;
 369                 return NULL;
 370         }
 371         return u;
 372 }
 373 
 374 
 375 static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 376 {
 377         struct sockaddr_un *sun=(struct sockaddr_un *)uaddr;
 378         unix_socket *sk=sock->data;
 379         int old_fs;
 380         int err;
 381         
 382         if(addr_len>sizeof(struct sockaddr_un) || addr_len<3 || sun->sun_family!=AF_UNIX)
 383                 return -EINVAL;
 384         unix_mkname(sun, addr_len);
 385         /*
 386          *      Put ourselves in the filesystem
 387          */
 388         if(sk->protinfo.af_unix.inode!=NULL)
 389                 return -EINVAL;
 390         
 391         sk->protinfo.af_unix.name=kmalloc(addr_len+1, GFP_KERNEL);
 392         if(sk->protinfo.af_unix.name==NULL)
 393                 return -ENOMEM;
 394         memcpy(sk->protinfo.af_unix.name, sun->sun_path, addr_len+1);
 395         
 396         old_fs=get_fs();
 397         set_fs(get_ds());
 398         
 399         err=do_mknod(sk->protinfo.af_unix.name,S_IFSOCK|S_IRWXUGO,0);
 400         if(err==0)
 401                 err=open_namei(sk->protinfo.af_unix.name, 2, S_IFSOCK, &sk->protinfo.af_unix.inode, NULL);
 402         
 403         set_fs(old_fs);
 404         
 405         if(err<0)
 406         {
 407                 kfree_s(sk->protinfo.af_unix.name,addr_len+1);
 408                 sk->protinfo.af_unix.name=NULL;
 409                 if(err==-EEXIST)
 410                         return -EADDRINUSE;
 411                 else
 412                         return err;
 413         }
 414         
 415         return 0;
 416         
 417 }
 418 
 419 static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421         unix_socket *sk=sock->data;
 422         struct sockaddr_un *sun=(struct sockaddr_un *)uaddr;
 423         unix_socket *other;
 424         struct sk_buff *skb;
 425         int err;
 426 
 427         if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
 428         {
 429                 if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
 430                 {
 431                         sock->state=SS_CONNECTED;
 432                         return 0;
 433                 }
 434                 if(sock->state==SS_CONNECTING && sk->state == TCP_CLOSE)
 435                 {
 436                         sock->state=SS_UNCONNECTED;
 437                         return -ECONNREFUSED;
 438                 }
 439                 if(sock->state==SS_CONNECTING)
 440                         return -EALREADY;
 441                 return -EISCONN;
 442         }
 443         
 444         if(addr_len < sizeof(sun->sun_family)+1 || sun->sun_family!=AF_UNIX)
 445                 return -EINVAL;
 446                 
 447         unix_mkname(sun, addr_len);
 448                 
 449         if(sk->type==SOCK_DGRAM && sk->protinfo.af_unix.other)
 450         {
 451                 sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
 452                 sk->protinfo.af_unix.other=NULL;
 453                 sock->state=SS_UNCONNECTED;
 454         }
 455 
 456         if(sock->type==SOCK_DGRAM)
 457         {
 458                 other=unix_find_other(sun->sun_path, &err);
 459                 if(other==NULL)
 460                         return err;
 461                 other->protinfo.af_unix.locks++;
 462                 sk->protinfo.af_unix.other=other;
 463                 sock->state=SS_CONNECTED;
 464                 sk->state=TCP_ESTABLISHED;
 465                 return 0;                       /* Done */
 466         }
 467         
 468 
 469         if(sock->state==SS_UNCONNECTED)
 470         {
 471                 /*
 472                  *      Now ready to connect
 473                  */
 474          
 475                 skb=sock_alloc_send_skb(sk, 0, 0, &err); /* Marker object */
 476                 if(skb==NULL)
 477                         return err;
 478                 skb->sk=sk;                             /* So they know it is us */
 479                 skb->free=1;
 480                 sk->state=TCP_CLOSE;
 481                 unix_mkname(sun, addr_len);
 482                 other=unix_find_other(sun->sun_path, &err);
 483                 if(other==NULL)
 484                 {
 485                         kfree_skb(skb, FREE_WRITE);
 486                         return err;
 487                 }
 488                 other->protinfo.af_unix.locks++;                /* Lock the other socket so it doesn't run off for a moment */
 489                 other->ack_backlog++;
 490                 sk->protinfo.af_unix.other=other;
 491                 skb_queue_tail(&other->receive_queue,skb);
 492                 sk->state=TCP_SYN_SENT;
 493                 sock->state=SS_CONNECTING;
 494                 sti();
 495                 other->data_ready(other,0);             /* Wake up ! */         
 496         }
 497                         
 498         
 499         /* Wait for an accept */
 500         
 501         cli();
 502         while(sk->state==TCP_SYN_SENT)
 503         {
 504                 if(flags&O_NONBLOCK)
 505                 {
 506                         sti();
 507                         return -EINPROGRESS;
 508                 }
 509                 interruptible_sleep_on(sk->sleep);
 510                 if(current->signal & ~current->blocked)
 511                 {
 512                         sti();
 513                         return -ERESTARTSYS;
 514                 }
 515         }
 516         
 517         /*
 518          *      Has the other end closed on us ?
 519          */
 520          
 521         if(sk->state==TCP_CLOSE)
 522         {
 523                 sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
 524                 sk->protinfo.af_unix.other=NULL;
 525                 sock->state=SS_UNCONNECTED;
 526                 return -ECONNREFUSED;
 527         }
 528         
 529         /*
 530          *      Amazingly it has worked
 531          */
 532          
 533         sock->state=SS_CONNECTED;
 534         return 0;
 535         
 536 }
 537 
 538 static int unix_socketpair(struct socket *a, struct socket *b)
     /* [previous][next][first][last][top][bottom][index][help] */
 539 {
 540         int err;
 541         unix_socket *ska,*skb;  
 542         
 543         err=unix_create(a, 0);
 544         if(err)
 545                 return err;
 546         err=unix_create(b, 0);
 547         if(err)
 548         {
 549                 unix_release(a, NULL);
 550                 a->data=NULL;
 551                 return err;
 552         }
 553 
 554         ska=a->data;
 555         skb=b->data;
 556 
 557         /* Join our sockets back to back */
 558         ska->protinfo.af_unix.locks++;
 559         skb->protinfo.af_unix.locks++;
 560         ska->protinfo.af_unix.other=skb;
 561         skb->protinfo.af_unix.other=ska;
 562         ska->state=TCP_ESTABLISHED;
 563         skb->state=TCP_ESTABLISHED;
 564         return 0;
 565 }
 566 
 567 static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 568 {
 569         unix_socket *sk=sock->data;
 570         unix_socket *newsk, *tsk;
 571         struct sk_buff *skb;
 572         
 573         if(sk->type!=SOCK_STREAM)
 574         {
 575                 return -EOPNOTSUPP;
 576         }
 577         if(sk->state!=TCP_LISTEN)
 578         {
 579                 return -EINVAL;
 580         }
 581                 
 582         newsk=newsock->data;
 583         if(sk->protinfo.af_unix.name!=NULL)
 584         {
 585                 newsk->protinfo.af_unix.name=kmalloc(strlen(sk->protinfo.af_unix.name)+1, GFP_KERNEL);
 586                 if(newsk->protinfo.af_unix.name==NULL)
 587                         return -ENOMEM;
 588                 strcpy(newsk->protinfo.af_unix.name, sk->protinfo.af_unix.name);
 589         }
 590                 
 591         do
 592         {
 593                 cli();
 594                 skb=skb_dequeue(&sk->receive_queue);
 595                 if(skb==NULL)
 596                 {
 597                         if(flags&O_NONBLOCK)
 598                         {
 599                                 sti();
 600                                 return -EAGAIN;
 601                         }
 602                         interruptible_sleep_on(sk->sleep);
 603                         if(current->signal & ~current->blocked)
 604                         {
 605                                 sti();
 606                                 return -ERESTARTSYS;
 607                         }
 608                         sti();
 609                 }
 610         }
 611         while(skb==NULL);
 612         tsk=skb->sk;
 613         kfree_skb(skb, FREE_WRITE);     /* The buffer is just used as a tag */
 614         sk->ack_backlog--;
 615         newsk->protinfo.af_unix.other=tsk;
 616         tsk->protinfo.af_unix.other=newsk;
 617         tsk->state=TCP_ESTABLISHED;
 618         newsk->state=TCP_ESTABLISHED;
 619         newsk->protinfo.af_unix.locks++;        /* Swap lock over */
 620         sk->protinfo.af_unix.locks--;   /* Locked to child socket not master */
 621         tsk->protinfo.af_unix.locks++;  /* Back lock */
 622         sti();
 623         tsk->state_change(tsk);         /* Wake up any sleeping connect */
 624         sock_wake_async(tsk->socket, 0);
 625         return 0;
 626 }
 627 
 628 static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 629 {
 630         unix_socket *sk=sock->data;
 631         struct sockaddr_un *sun=(struct sockaddr_un *)uaddr;
 632         
 633         if(peer)
 634         {
 635                 if(sk->protinfo.af_unix.other==NULL)
 636                         return -ENOTCONN;
 637                 sk=sk->protinfo.af_unix.other;
 638         }
 639         sun->sun_family=AF_UNIX;
 640         if(sk->protinfo.af_unix.name==NULL)
 641         {
 642                 *sun->sun_path=0;
 643                 *uaddr_len=sizeof(sun->sun_family)+1;
 644                 return 0;               /* Not bound */
 645         }
 646         *uaddr_len=sizeof(sun->sun_family)+strlen(sk->protinfo.af_unix.name)+1;
 647         strcpy(sun->sun_path,sk->protinfo.af_unix.name);                /* 108 byte limited */
 648         return 0;
 649 }
 650 
 651 static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653         unix_socket *sk=sock->data;
 654         unix_socket *other;
 655         struct sockaddr_un *sun=msg->msg_name;
 656         int err,size;
 657         struct sk_buff *skb;
 658 
 659         if(sk->err)
 660         {
 661                 cli();
 662                 err=sk->err;
 663                 sk->err=0;
 664                 sti();
 665                 return -err;
 666         }
 667         
 668         if(flags || msg->msg_accrights) /* For now */
 669                 return -EINVAL;
 670                 
 671         if(sun!=NULL)
 672         {
 673                 if(sock->type==SOCK_STREAM)
 674                 {
 675                         if(sk->state==TCP_ESTABLISHED)
 676                                 return -EISCONN;
 677                         else
 678                                 return -EOPNOTSUPP;
 679                 }
 680         }
 681         if(sun==NULL)
 682         {
 683                 if(sk->protinfo.af_unix.other==NULL)
 684                         return -EINVAL;
 685         }
 686 
 687         /*
 688          *      Optimisation for the fact that under 0.01% of X messages typically
 689          *      need breaking up.
 690          */
 691 
 692         if(len>(sk->sndbuf-sizeof(struct sk_buff))/2)   /* Keep two messages in the pipe so it schedules better */
 693         {
 694                 if(sock->type==SOCK_DGRAM)
 695                         return -EMSGSIZE;
 696                 len=(sk->sndbuf-sizeof(struct sk_buff))/2;
 697         }
 698          
 699         size=/*protocol_size(&proto_unix)+*/len;
 700         skb=sock_alloc_send_skb(sk,size,nonblock, &err);
 701         if(skb==NULL)
 702                 return err;
 703 /*      protocol_adjust(skb,&proto_unix);*/
 704         skb->sk=sk;
 705         skb->free=1;
 706         memcpy_fromiovec(skb_put(skb,len),msg->msg_iov, len);
 707 
 708         cli();
 709         if(sun==NULL)
 710         {
 711                 other=sk->protinfo.af_unix.other;
 712                 if(sock->type==SOCK_DGRAM && other->dead)
 713                 {
 714                         other->protinfo.af_unix.locks--;
 715                         sk->protinfo.af_unix.other=NULL;
 716                         sock->state=SS_UNCONNECTED;
 717                         return -ECONNRESET;
 718                 }
 719         }
 720         else
 721         {
 722                 unix_mkname(sun, msg->msg_namelen);
 723                 other=unix_find_other(sun->sun_path, &err);
 724                 if(other==NULL)
 725                 {
 726                         kfree_skb(skb, FREE_WRITE);
 727                         return err;
 728                 }
 729         }
 730         skb_queue_tail(&other->receive_queue, skb);
 731         sti();
 732         other->data_ready(other,len);
 733         return len;
 734 }
 735                 
 736 static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 737 {
 738         unix_socket *sk=sock->data;
 739         struct sockaddr_un *sun=msg->msg_name;
 740         int err;
 741         struct sk_buff *skb;
 742         int copied=0;
 743         unsigned char *sp;
 744         int len;
 745         int num;
 746         struct iovec *iov=msg->msg_iov;
 747         int ct=msg->msg_iovlen;
 748         
 749         if(addr_len)
 750                 *addr_len=0;
 751                 
 752         if(sk->err)
 753         {
 754                 cli();
 755                 err=sk->err;
 756                 sk->err=0;
 757                 sti();
 758                 return -err;
 759         }
 760         
 761 /*      printk("get rcv sem\n");*/
 762         down(&sk->protinfo.af_unix.readsem);            /* Lock the socket */
 763 /*      printk("got rcv sem\n");*/
 764 
 765         while(ct--)
 766         {
 767                 int done=0;
 768                 sp=iov->iov_base;
 769                 len=iov->iov_len;
 770                 iov++;
 771                 
 772                 while(done<len)
 773                 {
 774                         if(copied & (flags&MSG_PEEK))
 775                         {
 776                                 up(&sk->protinfo.af_unix.readsem);
 777                                 return copied;
 778                         }
 779                         cli();
 780                         skb=skb_peek(&sk->receive_queue);
 781                         if(skb==NULL)
 782                         {
 783                                 up(&sk->protinfo.af_unix.readsem);
 784                                 if(sk->shutdown & RCV_SHUTDOWN)
 785                                         return copied;
 786                                 if(copied)
 787                                         return copied;
 788                                 if(noblock)
 789                                 {
 790                                         return -EAGAIN;
 791                                 }
 792                                 sk->socket->flags |= SO_WAITDATA;
 793                                 interruptible_sleep_on(sk->sleep);
 794                                 sk->socket->flags &= ~SO_WAITDATA;
 795                                 if( current->signal & ~current->blocked)
 796                                 {
 797                                         sti();
 798                                         if(copied)
 799                                                 return copied;
 800                                         return -ERESTARTSYS;
 801                                 }
 802                                 sti();
 803                                 down(&sk->protinfo.af_unix.readsem);
 804                                 continue;
 805                         }
 806                         if(msg->msg_name!=NULL)
 807                         {
 808                                 sun->sun_family=AF_UNIX;
 809                                 if(skb->sk->protinfo.af_unix.name)
 810                                 {
 811                                         memcpy(sun->sun_path, skb->sk->protinfo.af_unix.name, 108);
 812                                         if(addr_len)
 813                                                 *addr_len=strlen(sun->sun_path)+sizeof(short);
 814                                 }
 815                                 else
 816                                         if(addr_len)
 817                                                 *addr_len=sizeof(short);
 818                         }
 819                         num=min(skb->len,size-copied);
 820                         copied+=num;
 821                         done+=num;
 822                         if(flags&MSG_PEEK)
 823                         {
 824                                 memcpy_tofs(sp, skb->data, num);
 825                                 break;
 826                         }
 827                         else
 828                         {
 829                                 memcpy_tofs(sp, skb->data,num);
 830                                 skb_pull(skb,num);
 831                                 sp+=num;
 832                                 if(skb->len==0)
 833                                 {
 834                                         skb_unlink(skb);
 835                                         kfree_skb(skb, FREE_WRITE);
 836                                         if(sock->type==SOCK_DGRAM)
 837                                                 break;
 838                                 }
 839                         }
 840                 }       
 841         }       
 842         up(&sk->protinfo.af_unix.readsem);
 843         return copied;
 844 }
 845 
 846 static int unix_shutdown(struct socket *sock, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 847 {
 848         unix_socket *sk=(unix_socket *)sock->data;
 849         unix_socket *other=sk->protinfo.af_unix.other;
 850         if(mode&SEND_SHUTDOWN)
 851         {
 852                 sk->shutdown|=SEND_SHUTDOWN;
 853                 sk->state_change(sk);
 854                 if(other)
 855                 {
 856                         other->shutdown|=RCV_SHUTDOWN;
 857                         other->state_change(other);
 858                 }
 859         }
 860         other=sk->protinfo.af_unix.other;
 861         if(mode&RCV_SHUTDOWN)
 862         {
 863                 sk->shutdown|=RCV_SHUTDOWN;
 864                 sk->state_change(sk);
 865                 if(other)
 866                 {
 867                         other->shutdown|=SEND_SHUTDOWN;
 868                         other->state_change(other);
 869                 }
 870         }
 871         return 0;
 872 }
 873 
 874                 
 875 static int unix_select(struct socket *sock,  int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 876 {
 877         return datagram_select(sock->data,sel_type,wait);
 878 }
 879 
 880 static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 881 {
 882         unix_socket *sk=sock->data;
 883         int err;
 884         long amount=0;
 885                         
 886         switch(cmd)
 887         {
 888         
 889                 case TIOCOUTQ:
 890                         err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
 891                         if(err)
 892                                 return err;
 893                         amount=sk->sndbuf-sk->wmem_alloc;
 894                         if(amount<0)
 895                                 amount=0;
 896                         put_fs_long(amount,(unsigned long *)arg);
 897                         return 0;
 898                 case TIOCINQ:
 899                 {
 900                         struct sk_buff *skb;
 901                         if(sk->state==TCP_LISTEN)
 902                                 return -EINVAL;
 903                         /* These two are safe on a single CPU system as only user tasks fiddle here */
 904                         if((skb=skb_peek(&sk->receive_queue))!=NULL)
 905                                 amount=skb->len;
 906                         err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
 907                         put_fs_long(amount,(unsigned long *)arg);
 908                         return 0;
 909                 }
 910 
 911                 default:
 912                         return -EINVAL;
 913         }
 914         /*NOTREACHED*/
 915         return(0);
 916 }
 917 
 918 static int unix_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 919 {
 920         off_t pos=0;
 921         off_t begin=0;
 922         int len=0;
 923         unix_socket *s=unix_socket_list;
 924         
 925         len+= sprintf(buffer,"Num       RefCount Protocol Flags    Type St Path\n");
 926         
 927         while(s!=NULL)
 928         {
 929                 len+=sprintf(buffer+len,"%p: %08X %08X %08lX %04X %02X",
 930                         s,
 931                         s->protinfo.af_unix.locks,
 932                         0,
 933                         s->socket->flags,
 934                         s->socket->type,
 935                         s->socket->state);
 936                 if(s->protinfo.af_unix.name!=NULL)
 937                         len+=sprintf(buffer+len, " %s\n", s->protinfo.af_unix.name);
 938                 else
 939                         buffer[len++]='\n';
 940                 
 941                 pos=begin+len;
 942                 if(pos<offset)
 943                 {
 944                         len=0;
 945                         begin=pos;
 946                 }
 947                 if(pos>offset+length)
 948                         break;
 949                 s=s->next;
 950         }
 951         *start=buffer+(offset-begin);
 952         len-=(offset-begin);
 953         if(len>length)
 954                 len=length;
 955         return len;
 956 }
 957 
 958 /*
 959  *      For AF_UNIX we flip everything into an iovec. If this doesnt do any speed harm then it will
 960  *      be easier for all the low levels to be totally iovec based.
 961  */
 962  
 963 static int unix_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 964                 struct sockaddr *sa, int *addr_len)
 965 {
 966         struct iovec iov;
 967         struct msghdr msg;
 968         iov.iov_base=ubuf;
 969         iov.iov_len=size;
 970         msg.msg_name=(void *)sa;
 971         msg.msg_namelen=0;
 972         if (addr_len)
 973                 msg.msg_namelen = *addr_len;
 974         msg.msg_accrights=NULL;
 975         msg.msg_iov=&iov;
 976         msg.msg_iovlen=1;
 977         return unix_recvmsg(sock,&msg,size,noblock,flags,addr_len);     
 978 }
 979 
 980 static int unix_read(struct socket *sock, char *ubuf, int size, int noblock)
     /* [previous][next][first][last][top][bottom][index][help] */
 981 {
 982         return unix_recvfrom(sock,ubuf,size,noblock,0,NULL,NULL);
 983 }
 984 
 985 static int unix_recv(struct socket *sock, void *ubuf, int size, int noblock, unsigned int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 986 {
 987         return unix_recvfrom(sock,ubuf,size,noblock,flags,NULL,NULL);
 988 }
 989 
 990 static int unix_sendto(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 991                 struct sockaddr *sa, int addr_len)
 992 {
 993         struct iovec iov;
 994         struct msghdr msg;
 995         iov.iov_base=(void *)ubuf;
 996         iov.iov_len=size;
 997         msg.msg_name=(void *)sa;
 998         msg.msg_namelen=addr_len;
 999         msg.msg_accrights=NULL;
1000         msg.msg_iov=&iov;
1001         msg.msg_iovlen=1;
1002         return unix_sendmsg(sock,&msg,size,noblock,flags);      
1003 }
1004 
1005 static int unix_write(struct socket *sock, const char *ubuf, int size, int noblock)
     /* [previous][next][first][last][top][bottom][index][help] */
1006 {       
1007         return unix_sendto(sock,ubuf,size,noblock, 0, NULL, 0);
1008 }
1009 
1010 static int unix_send(struct socket *sock, const void *ubuf, int size, int noblock, unsigned int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
1011 {
1012         return unix_sendto(sock,ubuf,size,noblock, flags, NULL, 0);
1013 }
1014 
1015 
1016 static struct proto_ops unix_proto_ops = {
1017         AF_UNIX,
1018         
1019         unix_create,
1020         unix_dup,
1021         unix_release,
1022         unix_bind,
1023         unix_connect,
1024         unix_socketpair,
1025         unix_accept,
1026         unix_getname,
1027         unix_read,
1028         unix_write,
1029         unix_select,
1030         unix_ioctl,
1031         unix_listen,
1032         unix_send,
1033         unix_recv,
1034         unix_sendto,
1035         unix_recvfrom,
1036         unix_shutdown,
1037         unix_setsockopt,
1038         unix_getsockopt,
1039         unix_fcntl,
1040         unix_sendmsg,
1041         unix_recvmsg
1042 };
1043 
1044 
1045 void unix_proto_init(struct net_proto *pro)
     /* [previous][next][first][last][top][bottom][index][help] */
1046 {
1047         printk("NET3: Unix domain sockets 0.07 BETA for Linux NET3.030.\n");
1048         sock_register(unix_proto_ops.family, &unix_proto_ops);
1049         proc_net_register(&(struct proc_dir_entry) {
1050                 PROC_NET_UNIX,  4, "unix",
1051                 S_IFREG | S_IRUGO, 1, 0, 0,
1052                 0, &proc_net_inode_operations,
1053                 unix_get_info
1054         });
1055 }
1056 /*
1057  * Local variables:
1058  *  compile-command: "gcc -g -D__KERNEL__ -Wall -O6 -I/usr/src/linux/include -c af_unix.c"
1059  * End:
1060  */

/* [previous][next][first][last][top][bottom][index][help] */