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

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