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

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