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

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