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

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