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_copyrights
  25. unix_returnrights
  26. unix_fd_copy
  27. unix_fd_free
  28. unix_files_free
  29. unix_detach_fds
  30. unix_destruct_fds
  31. unix_attach_fds
  32. unix_sendmsg
  33. unix_data_wait
  34. unix_recvmsg
  35. unix_shutdown
  36. unix_select
  37. unix_ioctl
  38. unix_get_info
  39. unix_proto_init

   1 /*
   2  * NET3:        Implementation of BSD Unix domain sockets.
   3  *
   4  * Authors:     Alan Cox, <alan@cymru.net>
   5  *
   6  *              Currently this contains all but the file descriptor passing code.
   7  *              Before that goes in the odd bugs in the iovec handlers need 
   8  *              fixing, and this bit testing. BSD fd passing is not a trivial part
   9  *              of the exercise it turns out. Anyone like writing garbage collectors.
  10  *
  11  *              This program is free software; you can redistribute it and/or
  12  *              modify it under the terms of the GNU General Public License
  13  *              as published by the Free Software Foundation; either version
  14  *              2 of the License, or (at your option) any later version.
  15  *
  16  * Fixes:
  17  *              Linus Torvalds  :       Assorted bug cures.
  18  *              Niibe Yutaka    :       async I/O support.
  19  *              Carsten Paeth   :       PF_UNIX check, address fixes.
  20  *              Alan Cox        :       Limit size of allocated blocks.
  21  *              Alan Cox        :       Fixed the stupid socketpair bug.
  22  *              Alan Cox        :       BSD compatibility fine tuning.
  23  *              Alan Cox        :       Fixed a bug in connect when interrupted.
  24  *              Alan Cox        :       Sorted out a proper draft version of
  25  *                                      file descriptor passing hacked up from
  26  *                                      Mike Shaver's work.
  27  *              Marty Leisner   :       Fixes to fd passing
  28  *              Nick Nevin      :       recvmsg bugfix.
  29  *              Alan Cox        :       Started proper garbage collector
  30  *
  31  * Known differences from reference BSD that was tested:
  32  *
  33  *      [TO FIX]
  34  *      ECONNREFUSED is not returned from one end of a connected() socket to the
  35  *              other the moment one end closes.
  36  *      fstat() doesn't return st_dev=NODEV, and give the blksize as high water mark
  37  *              and a fake inode identifier (nor the BSD first socket fstat twice bug).
  38  *      [NOT TO FIX]
  39  *      accept() returns a path name even if the connecting socket has closed
  40  *              in the meantime (BSD loses the path and gives up).
  41  *      accept() returns 0 length path for an unbound connector. BSD returns 16
  42  *              and a null first byte in the path (but not for gethost/peername - BSD bug ??)
  43  *      socketpair(...SOCK_RAW..) doesnt panic the kernel.
  44  *      BSD af_unix apprently has connect forgetting to block properly.
  45  */
  46 
  47 #include <linux/config.h>
  48 #include <linux/kernel.h>
  49 #include <linux/major.h>
  50 #include <linux/signal.h>
  51 #include <linux/sched.h>
  52 #include <linux/errno.h>
  53 #include <linux/string.h>
  54 #include <linux/stat.h>
  55 #include <linux/socket.h>
  56 #include <linux/un.h>
  57 #include <linux/fcntl.h>
  58 #include <linux/termios.h>
  59 #include <linux/socket.h>
  60 #include <linux/sockios.h>
  61 #include <linux/net.h>
  62 #include <linux/in.h>
  63 #include <linux/fs.h>
  64 #include <linux/malloc.h>
  65 #include <asm/segment.h>
  66 #include <linux/skbuff.h>
  67 #include <linux/netdevice.h>
  68 #include <net/sock.h>
  69 #include <net/tcp.h>
  70 #include <net/af_unix.h>
  71 #include <linux/proc_fs.h>
  72 
  73 unix_socket *unix_socket_list=NULL;
  74 
  75 #define min(a,b)        (((a)<(b))?(a):(b))
  76 
  77 /*
  78  *      Make sure the unix name is null-terminated.
  79  */
  80  
  81 static inline void unix_mkname(struct sockaddr_un * sunaddr, unsigned long len)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         if (len >= sizeof(*sunaddr))
  84                 len = sizeof(*sunaddr)-1;
  85         ((char *)sunaddr)[len]=0;
  86 }
  87 
  88 /*
  89  *      Note: Sockets may not be removed _during_ an interrupt or net_bh
  90  *      handler using this technique. They can be added although we do not
  91  *      use this facility.
  92  */
  93  
  94 static void unix_remove_socket(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96         unix_socket **s;
  97         
  98         cli();
  99         s=&unix_socket_list;
 100 
 101         while(*s!=NULL)
 102         {
 103                 if(*s==sk)
 104                 {
 105                         *s=sk->next;
 106                         sti();
 107                         return;
 108                 }
 109                 s=&((*s)->next);
 110         }
 111         sti();
 112 }
 113 
 114 static void unix_insert_socket(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         cli();
 117         sk->next=unix_socket_list;
 118         unix_socket_list=sk;
 119         sti();
 120 }
 121 
 122 static unix_socket *unix_find_socket(struct inode *i)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         unix_socket *s;
 125         cli();
 126         s=unix_socket_list;
 127         while(s)
 128         {
 129                 if(s->protinfo.af_unix.inode==i)
 130                 {
 131                         sti();
 132                         return(s);
 133                 }
 134                 s=s->next;
 135         }
 136         sti();
 137         return(NULL);
 138 }
 139 
 140 /*
 141  *      Delete a unix socket. We have to allow for deferring this on a timer.
 142  */
 143 
 144 static void unix_destroy_timer(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         unix_socket *sk=(unix_socket *)data;
 147         if(sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
 148         {
 149                 if(sk->protinfo.af_unix.name)
 150                         kfree(sk->protinfo.af_unix.name);
 151                 sk_free(sk);
 152                 return;
 153         }
 154         
 155         /*
 156          *      Retry;
 157          */
 158          
 159         sk->timer.expires=jiffies+10*HZ;        /* No real hurry try it every 10 seconds or so */
 160         add_timer(&sk->timer);
 161 }
 162          
 163          
 164 static void unix_delayed_delete(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166         sk->timer.data=(unsigned long)sk;
 167         sk->timer.expires=jiffies+HZ;           /* Normally 1 second after will clean up. After that we try every 10 */
 168         sk->timer.function=unix_destroy_timer;
 169         add_timer(&sk->timer);
 170 }
 171         
 172 static void unix_destroy_socket(unix_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         struct sk_buff *skb;
 175 
 176         unix_remove_socket(sk);
 177         
 178         while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 179         {
 180                 if(sk->state==TCP_LISTEN)
 181                 {
 182                         unix_socket *osk=skb->sk;
 183                         osk->state=TCP_CLOSE;
 184                         kfree_skb(skb, FREE_WRITE);     /* Now surplus - free the skb first before the socket */
 185                         osk->state_change(osk);         /* So the connect wakes and cleans up (if any) */
 186                         /* osk will be destroyed when it gets to close or the timer fires */                    
 187                 }
 188                 else
 189                 {
 190                         /* passed fds are erased where?? */
 191                         kfree_skb(skb,FREE_WRITE);
 192                 }
 193         }
 194         
 195         if(sk->protinfo.af_unix.inode!=NULL)
 196         {
 197                 iput(sk->protinfo.af_unix.inode);
 198                 sk->protinfo.af_unix.inode=NULL;
 199         }
 200         
 201         if(--sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
 202         {
 203                 if(sk->protinfo.af_unix.name)
 204                         kfree(sk->protinfo.af_unix.name);
 205                 sk_free(sk);
 206         }
 207         else
 208         {
 209                 sk->dead=1;
 210                 unix_delayed_delete(sk);        /* Try every so often until buffers are all freed */
 211         }
 212 }
 213 
 214 /*
 215  *      Fixme: We need async I/O on AF_UNIX doing next.
 216  */
 217  
 218 static int unix_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220         return -EINVAL;
 221 }
 222 
 223 /*
 224  *      Yes socket options work with the new unix domain socketry!!!!!!!
 225  */
 226  
 227 static int unix_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         unix_socket *sk=sock->data;
 230         if(level!=SOL_SOCKET)
 231                 return -EOPNOTSUPP;
 232         return sock_setsockopt(sk,level,optname,optval,optlen); 
 233 }
 234 
 235 static int unix_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         unix_socket *sk=sock->data;
 238         if(level!=SOL_SOCKET)
 239                 return -EOPNOTSUPP;
 240         return sock_getsockopt(sk,level,optname,optval,optlen);
 241 }
 242 
 243 static int unix_listen(struct socket *sock, int backlog)
     /* [previous][next][first][last][top][bottom][index][help] */
 244 {
 245         unix_socket *sk=sock->data;
 246         if(sk->type!=SOCK_STREAM)
 247                 return -EOPNOTSUPP;             /* Only stream sockets accept */
 248         if(sk->protinfo.af_unix.name==NULL)
 249                 return -EINVAL;                 /* No listens on an unbound socket */
 250         sk->max_ack_backlog=backlog;
 251         sk->state=TCP_LISTEN;
 252         return 0;
 253 }
 254 
 255 static void def_callback1(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257         if(!sk->dead)
 258                 wake_up_interruptible(sk->sleep);
 259 }
 260 
 261 static void def_callback2(struct sock *sk, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263         if(!sk->dead)
 264         {
 265                 wake_up_interruptible(sk->sleep);
 266                 sock_wake_async(sk->socket, 1);
 267         }
 268 }
 269 
 270 static void def_callback3(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272         if(!sk->dead)
 273         {
 274                 wake_up_interruptible(sk->sleep);
 275                 sock_wake_async(sk->socket, 2);
 276         }
 277 }
 278 
 279 static int unix_create(struct socket *sock, int protocol)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281         unix_socket *sk;
 282         if(protocol && protocol != PF_UNIX)
 283                 return -EPROTONOSUPPORT;
 284         sk=(unix_socket *)sk_alloc(GFP_KERNEL);
 285         if(sk==NULL)
 286                 return -ENOMEM;
 287         switch(sock->type)
 288         {
 289                 case SOCK_STREAM:
 290                         break;
 291                 /*
 292                  *      Believe it or not BSD has AF_UNIX, SOCK_RAW though
 293                  *      nothing uses it.
 294                  */
 295                 case SOCK_RAW:
 296                         sock->type=SOCK_DGRAM;
 297                 case SOCK_DGRAM:
 298                         break;
 299                 default:
 300                         sk_free(sk);
 301                         return -ESOCKTNOSUPPORT;
 302         }
 303         sk->type=sock->type;
 304         init_timer(&sk->timer);
 305         skb_queue_head_init(&sk->write_queue);
 306         skb_queue_head_init(&sk->receive_queue);
 307         skb_queue_head_init(&sk->back_log);
 308         sk->protinfo.af_unix.family=AF_UNIX;
 309         sk->protinfo.af_unix.inode=NULL;
 310         sk->protinfo.af_unix.locks=1;           /* Us */
 311         sk->protinfo.af_unix.readsem=MUTEX;     /* single task reading lock */
 312         sk->protinfo.af_unix.name=NULL;
 313         sk->protinfo.af_unix.other=NULL;
 314         sk->protocol=0;
 315         sk->rmem_alloc=0;
 316         sk->wmem_alloc=0;
 317         sk->dead=0;
 318         sk->next=NULL;
 319         sk->broadcast=0;
 320         sk->rcvbuf=SK_RMEM_MAX;
 321         sk->sndbuf=SK_WMEM_MAX;
 322         sk->allocation=GFP_KERNEL;
 323         sk->users=0;
 324         sk->bsdism=0;
 325         sk->debug=0;
 326         sk->prot=NULL;
 327         sk->err=0;
 328         sk->localroute=0;
 329         sk->send_head=NULL;
 330         sk->state=TCP_CLOSE;
 331         sk->priority=SOPRI_NORMAL;
 332         sk->ack_backlog=0;
 333         sk->shutdown=0;
 334         sk->state_change=def_callback1;
 335         sk->data_ready=def_callback2;
 336         sk->write_space=def_callback3;
 337         sk->error_report=def_callback1;
 338         sk->mtu=4096;
 339         sk->socket=sock;
 340         sock->data=(void *)sk;
 341         sk->sleep=sock->wait;
 342         sk->zapped=0;
 343         unix_insert_socket(sk);
 344         return 0;
 345 }
 346 
 347 static int unix_dup(struct socket *newsock, struct socket *oldsock)
     /* [previous][next][first][last][top][bottom][index][help] */
 348 {
 349         return unix_create(newsock,0);
 350 }
 351 
 352 static int unix_release(struct socket *sock, struct socket *peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 353 {
 354         unix_socket *sk=sock->data;
 355         unix_socket *skpair;
 356         
 357         /* May not have data attached */
 358         
 359         if(sk==NULL)
 360                 return 0;
 361                 
 362         sk->state_change(sk);
 363         sk->dead=1;
 364         skpair=(unix_socket *)sk->protinfo.af_unix.other;       /* Person we send to (default) */
 365         if(sk->type==SOCK_STREAM && skpair!=NULL && skpair->state!=TCP_LISTEN)
 366         {
 367                 skpair->shutdown=SHUTDOWN_MASK;         /* No more writes */
 368                 skpair->state_change(skpair);           /* Wake any blocked writes */
 369         }
 370         if(skpair!=NULL)
 371                 skpair->protinfo.af_unix.locks--;       /* It may now die */
 372         sk->protinfo.af_unix.other=NULL;                /* No pair */
 373         unix_destroy_socket(sk);                        /* Try and flush out this socket. Throw our buffers at least */
 374         
 375         /*
 376          *      FIXME: BSD difference: In BSD all sockets connected to use get ECONNRESET and we die on the spot. In
 377          *      Linux we behave like files and pipes do and wait for the last dereference.
 378          */
 379          
 380         return 0;
 381 }
 382 
 383 
 384 static unix_socket *unix_find_other(char *path, int *error)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386         int old_fs;
 387         int err;
 388         struct inode *inode;
 389         unix_socket *u;
 390         
 391         old_fs=get_fs();
 392         set_fs(get_ds());
 393         err = open_namei(path, 2, S_IFSOCK, &inode, NULL);
 394         set_fs(old_fs);
 395         if(err<0)
 396         {
 397                 *error=err;
 398                 return NULL;
 399         }
 400         u=unix_find_socket(inode);
 401         iput(inode);
 402         if(u==NULL)
 403         {
 404                 *error=-ECONNREFUSED;
 405                 return NULL;
 406         }
 407         return u;
 408 }
 409 
 410 
 411 static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413         struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
 414         unix_socket *sk=sock->data;
 415         int old_fs;
 416         int err;
 417         
 418         if(sk->protinfo.af_unix.name)
 419                 return -EINVAL;         /* Already bound */
 420         
 421         if(addr_len>sizeof(struct sockaddr_un) || addr_len<3 || sunaddr->sun_family!=AF_UNIX)
 422                 return -EINVAL;
 423         unix_mkname(sunaddr, addr_len);
 424         /*
 425          *      Put ourselves in the filesystem
 426          */
 427         if(sk->protinfo.af_unix.inode!=NULL)
 428                 return -EINVAL;
 429         
 430         sk->protinfo.af_unix.name=kmalloc(addr_len+1, GFP_KERNEL);
 431         if(sk->protinfo.af_unix.name==NULL)
 432                 return -ENOMEM;
 433         memcpy(sk->protinfo.af_unix.name, sunaddr->sun_path, addr_len+1);
 434         
 435         old_fs=get_fs();
 436         set_fs(get_ds());
 437         
 438         err=do_mknod(sk->protinfo.af_unix.name,S_IFSOCK|S_IRWXUGO,0);
 439         if(err==0)
 440                 err=open_namei(sk->protinfo.af_unix.name, 2, S_IFSOCK, &sk->protinfo.af_unix.inode, NULL);
 441         
 442         set_fs(old_fs);
 443         
 444         if(err<0)
 445         {
 446                 kfree_s(sk->protinfo.af_unix.name,addr_len+1);
 447                 sk->protinfo.af_unix.name=NULL;
 448                 if(err==-EEXIST)
 449                         return -EADDRINUSE;
 450                 else
 451                         return err;
 452         }
 453         
 454         return 0;
 455         
 456 }
 457 
 458 static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460         unix_socket *sk=sock->data;
 461         struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
 462         unix_socket *other;
 463         struct sk_buff *skb;
 464         int err;
 465 
 466         if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
 467         {
 468                 if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
 469                 {
 470                         sock->state=SS_CONNECTED;
 471                         return 0;
 472                 }
 473                 if(sock->state==SS_CONNECTING && sk->state == TCP_CLOSE)
 474                 {
 475                         sock->state=SS_UNCONNECTED;
 476                         return -ECONNREFUSED;
 477                 }
 478                 if(sock->state!=SS_CONNECTING)
 479                         return -EISCONN;
 480                 if(flags&O_NONBLOCK)
 481                         return -EALREADY;
 482                 /*
 483                  *      Drop through the connect up logic to the wait.
 484                  */
 485         }
 486         
 487         if(addr_len < sizeof(sunaddr->sun_family)+1 || sunaddr->sun_family!=AF_UNIX)
 488                 return -EINVAL;
 489                 
 490         unix_mkname(sunaddr, addr_len);
 491                 
 492         if(sk->type==SOCK_DGRAM)
 493         {
 494                 if(sk->protinfo.af_unix.other)
 495                 {
 496                         sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
 497                         sk->protinfo.af_unix.other=NULL;
 498                         sock->state=SS_UNCONNECTED;
 499                 }
 500                 other=unix_find_other(sunaddr->sun_path, &err);
 501                 if(other==NULL)
 502                         return err;
 503                 if(other->type!=sk->type)
 504                         return -EPROTOTYPE;
 505                 other->protinfo.af_unix.locks++;
 506                 sk->protinfo.af_unix.other=other;
 507                 sock->state=SS_CONNECTED;
 508                 sk->state=TCP_ESTABLISHED;
 509                 return 0;                       /* Done */
 510         }
 511         
 512 
 513         if(sock->state==SS_UNCONNECTED)
 514         {
 515                 /*
 516                  *      Now ready to connect
 517                  */
 518          
 519                 skb=sock_alloc_send_skb(sk, 0, 0, 0, &err); /* Marker object */
 520                 if(skb==NULL)
 521                         return err;
 522                 skb->sk=sk;                             /* So they know it is us */
 523                 skb->free=1;
 524                 sk->state=TCP_CLOSE;
 525                 unix_mkname(sunaddr, addr_len);
 526                 other=unix_find_other(sunaddr->sun_path, &err);
 527                 if(other==NULL)
 528                 {
 529                         kfree_skb(skb, FREE_WRITE);
 530                         return err;
 531                 }
 532                 if(other->type!=sk->type)
 533                 {
 534                         kfree_skb(skb, FREE_WRITE);
 535                         return -EPROTOTYPE;
 536                 }
 537                 other->protinfo.af_unix.locks++;                /* Lock the other socket so it doesn't run off for a moment */
 538                 other->ack_backlog++;
 539                 sk->protinfo.af_unix.other=other;
 540                 skb_queue_tail(&other->receive_queue,skb);
 541                 sk->state=TCP_SYN_SENT;
 542                 sock->state=SS_CONNECTING;
 543                 sti();
 544                 other->data_ready(other,0);             /* Wake up ! */         
 545         }
 546                         
 547         
 548         /* Wait for an accept */
 549         
 550         cli();
 551         while(sk->state==TCP_SYN_SENT)
 552         {
 553                 if(flags&O_NONBLOCK)
 554                 {
 555                         sti();
 556                         return -EINPROGRESS;
 557                 }
 558                 interruptible_sleep_on(sk->sleep);
 559                 if(current->signal & ~current->blocked)
 560                 {
 561                         sti();
 562                         return -ERESTARTSYS;
 563                 }
 564         }
 565         
 566         /*
 567          *      Has the other end closed on us ?
 568          */
 569          
 570         if(sk->state==TCP_CLOSE)
 571         {
 572                 sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
 573                 sk->protinfo.af_unix.other=NULL;
 574                 sock->state=SS_UNCONNECTED;
 575                 sti();
 576                 return -ECONNREFUSED;
 577         }
 578         
 579         /*
 580          *      Amazingly it has worked
 581          */
 582          
 583         sock->state=SS_CONNECTED;
 584         sti();
 585         return 0;
 586         
 587 }
 588 
 589 static int unix_socketpair(struct socket *a, struct socket *b)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591         unix_socket *ska,*skb;  
 592         
 593         ska=a->data;
 594         skb=b->data;
 595 
 596         /* Join our sockets back to back */
 597         ska->protinfo.af_unix.locks++;
 598         skb->protinfo.af_unix.locks++;
 599         ska->protinfo.af_unix.other=skb;
 600         skb->protinfo.af_unix.other=ska;
 601         ska->state=TCP_ESTABLISHED;
 602         skb->state=TCP_ESTABLISHED;
 603         return 0;
 604 }
 605 
 606 static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 607 {
 608         unix_socket *sk=sock->data;
 609         unix_socket *newsk, *tsk;
 610         struct sk_buff *skb;
 611         
 612         if(sk->type!=SOCK_STREAM)
 613         {
 614                 return -EOPNOTSUPP;
 615         }
 616         if(sk->state!=TCP_LISTEN)
 617         {
 618                 return -EINVAL;
 619         }
 620                 
 621         newsk=newsock->data;
 622         if(sk->protinfo.af_unix.name!=NULL)
 623         {
 624                 newsk->protinfo.af_unix.name=kmalloc(strlen(sk->protinfo.af_unix.name)+1, GFP_KERNEL);
 625                 if(newsk->protinfo.af_unix.name==NULL)
 626                         return -ENOMEM;
 627                 strcpy(newsk->protinfo.af_unix.name, sk->protinfo.af_unix.name);
 628         }
 629                 
 630         do
 631         {
 632                 cli();
 633                 skb=skb_dequeue(&sk->receive_queue);
 634                 if(skb==NULL)
 635                 {
 636                         if(flags&O_NONBLOCK)
 637                         {
 638                                 sti();
 639                                 return -EAGAIN;
 640                         }
 641                         interruptible_sleep_on(sk->sleep);
 642                         if(current->signal & ~current->blocked)
 643                         {
 644                                 sti();
 645                                 return -ERESTARTSYS;
 646                         }
 647                         sti();
 648                 }
 649         }
 650         while(skb==NULL);
 651         tsk=skb->sk;
 652         kfree_skb(skb, FREE_WRITE);     /* The buffer is just used as a tag */
 653         sk->ack_backlog--;
 654         newsk->protinfo.af_unix.other=tsk;
 655         tsk->protinfo.af_unix.other=newsk;
 656         tsk->state=TCP_ESTABLISHED;
 657         newsk->state=TCP_ESTABLISHED;
 658         newsk->protinfo.af_unix.locks++;        /* Swap lock over */
 659         sk->protinfo.af_unix.locks--;   /* Locked to child socket not master */
 660         tsk->protinfo.af_unix.locks++;  /* Back lock */
 661         sti();
 662         tsk->state_change(tsk);         /* Wake up any sleeping connect */
 663         sock_wake_async(tsk->socket, 0);
 664         return 0;
 665 }
 666 
 667 static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669         unix_socket *sk=sock->data;
 670         struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
 671         
 672         if(peer)
 673         {
 674                 if(sk->protinfo.af_unix.other==NULL)
 675                         return -ENOTCONN;
 676                 sk=sk->protinfo.af_unix.other;
 677         }
 678         sunaddr->sun_family=AF_UNIX;
 679         if(sk->protinfo.af_unix.name==NULL)
 680         {
 681                 *sunaddr->sun_path=0;
 682                 *uaddr_len=sizeof(sunaddr->sun_family)+1;
 683                 return 0;               /* Not bound */
 684         }
 685         *uaddr_len=sizeof(sunaddr->sun_family)+strlen(sk->protinfo.af_unix.name)+1;
 686         strcpy(sunaddr->sun_path,sk->protinfo.af_unix.name);            /* 108 byte limited */
 687         return 0;
 688 }
 689 
 690 /*
 691  *      Support routines for struct cmsghdr handling
 692  */
 693  
 694 static struct cmsghdr *unix_copyrights(void *userp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 695 {
 696         struct cmsghdr *cm;
 697 
 698         if(len>256|| len <=0)
 699                 return NULL;
 700         cm=kmalloc(len, GFP_KERNEL);
 701         memcpy_fromfs(cm, userp, len);
 702         return cm;
 703 }
 704 
 705 /*
 706  *      Return a header block
 707  */
 708  
 709 static void unix_returnrights(void *userp, int len, struct cmsghdr *cm)
     /* [previous][next][first][last][top][bottom][index][help] */
 710 {
 711         memcpy_tofs(userp, cm, len);
 712         kfree(cm);
 713 }
 714 
 715 /*
 716  *      Copy file descriptors into system space.
 717  *      Return number copied or negative error code
 718  */
 719  
 720 static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 721 {
 722         int num=cmsg->cmsg_len-sizeof(struct cmsghdr);
 723         int i;
 724         int *fdp=(int *)cmsg->cmsg_data;
 725         num/=4; /* Odd bytes are forgotten in BSD not errored */
 726         
 727 
 728         if(num>=UNIX_MAX_FD)
 729                 return -EINVAL;
 730         
 731         /*
 732          *      Verify the descriptors.
 733          */
 734          
 735         for(i=0; i< num; i++)
 736         {
 737                 int fd;
 738                 
 739                 fd = fdp[i];    
 740 #if 0
 741                 printk("testing  fd %d\n", fd);
 742 #endif
 743                 if(fd < 0|| fd >=NR_OPEN)
 744                         return -EBADF;
 745                 if(current->files->fd[fd]==NULL)
 746                         return -EBADF;
 747         }
 748         
 749         /* add another reference to these files */
 750         for(i=0; i< num; i++)
 751         {
 752                 fp[i]=current->files->fd[fdp[i]];
 753                 fp[i]->f_count++;
 754                 unix_inflight(fp[i]);
 755         }
 756         
 757         return num;
 758 }
 759 
 760 /*
 761  *      Free the descriptors in the array
 762  */
 763 
 764 static void unix_fd_free(struct sock *sk, struct file **fp, int num)
     /* [previous][next][first][last][top][bottom][index][help] */
 765 {
 766         int i;
 767         for(i=0;i<num;i++)
 768         {
 769                 close_fp(fp[i]);
 770                 unix_notinflight(fp[i]);
 771         }
 772 }
 773 
 774 /*
 775  *      Count the free descriptors available to a process. 
 776  *      Interpretation issue: Is the limit the highest descriptor (buggy
 777  *      allowing passed fd's higher up to cause a limit to be exceeded) -
 778  *      but how the old code did it - or like this...
 779  */
 780 
 781 static int unix_files_free(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 782 {
 783         int i;
 784         int n=0;
 785         for (i=0;i<NR_OPEN;i++)
 786         {
 787                 if(current->files->fd[i])
 788                         n++;
 789         }
 790         
 791         i=NR_OPEN;
 792         if(i>current->rlim[RLIMIT_NOFILE].rlim_cur)
 793                 i=current->rlim[RLIMIT_NOFILE].rlim_cur;
 794         if(n>=i)
 795                 return 0;
 796         return i-n;
 797 }
 798 
 799 /*
 800  *      Perform the AF_UNIX file descriptor pass out functionality. This
 801  *      is nasty and messy as is the whole design of BSD file passing.
 802  */
 803 
 804 static void unix_detach_fds(struct sk_buff *skb, struct cmsghdr *cmsg)
     /* [previous][next][first][last][top][bottom][index][help] */
 805 {
 806         int i;
 807         /* count of space in parent for fds */
 808         int cmnum;
 809         struct file **fp;
 810         struct file **ufp;
 811         int *cmfptr=NULL;       /* =NULL To keep gcc happy */
 812         /* number of fds actually passed */
 813         int fdnum;
 814         int ffree;
 815         int ufn=0;
 816 
 817         if(cmsg==NULL)
 818                 cmnum=0;
 819         else
 820         {
 821                 cmnum=cmsg->cmsg_len-sizeof(struct cmsghdr);
 822                 cmnum/=sizeof(int);
 823                 cmfptr=(int *)&cmsg->cmsg_data;
 824         }
 825         
 826         memcpy(&fdnum,skb->h.filp,sizeof(int));
 827         fp=(struct file **)(skb->h.filp+sizeof(int));
 828         if(cmnum>fdnum)
 829                 cmnum=fdnum;
 830         ffree=unix_files_free();
 831         if(cmnum>ffree)
 832                 cmnum=ffree;
 833         ufp=&current->files->fd[0];
 834         
 835         /*
 836          *      Copy those that fit
 837          */
 838         for(i=0;i<cmnum;i++)
 839         {
 840                 /*
 841                  *      Insert the fd
 842                  */
 843                 while(ufp[ufn]!=NULL)
 844                         ufn++;
 845                 ufp[ufn]=fp[i];
 846                 *cmfptr++=ufn;
 847                 FD_CLR(ufn,&current->files->close_on_exec);
 848                 unix_notinflight(fp[i]);
 849         }
 850         /*
 851          *      Dump those that don't
 852          */
 853         for(;i<fdnum;i++)
 854         {
 855                 close_fp(fp[i]);
 856                 unix_notinflight(fp[i]);
 857         }
 858         kfree(skb->h.filp);
 859         skb->h.filp=NULL;
 860 
 861         /* no need to use destructor */
 862         skb->destructor = NULL;
 863 }
 864 
 865 static void unix_destruct_fds(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 866 {
 867         unix_detach_fds(skb,NULL);
 868 }
 869         
 870 /*
 871  *      Attach the file descriptor array to an sk_buff
 872  */
 873 static void unix_attach_fds(int fpnum,struct file **fp,struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 874 {
 875 
 876         skb->h.filp=kmalloc(sizeof(int)+fpnum*sizeof(struct file *), 
 877                                                         GFP_KERNEL);
 878         /* number of descriptors starts block */
 879         memcpy(skb->h.filp,&fpnum,sizeof(int));
 880         /* actual  descriptors */
 881         memcpy(skb->h.filp+sizeof(int),fp,fpnum*sizeof(struct file *));
 882         skb->destructor = unix_destruct_fds;
 883 }
 884 
 885 /*
 886  *      Send AF_UNIX data.
 887  */
 888                 
 889 static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 890 {
 891         unix_socket *sk=sock->data;
 892         unix_socket *other;
 893         struct sockaddr_un *sunaddr=msg->msg_name;
 894         int err,size;
 895         struct sk_buff *skb;
 896         int limit=0;
 897         int sent=0;
 898         struct file *fp[UNIX_MAX_FD];
 899         /* number of fds waiting to be passed, 0 means either
 900          * no fds to pass or they've already been passed 
 901          */
 902         int fpnum=0;
 903 
 904         if(sk->err)
 905                 return sock_error(sk);
 906 
 907         if(flags&MSG_OOB)
 908                 return -EOPNOTSUPP;
 909                         
 910         if(flags)       /* For now */ {
 911                 return -EINVAL;
 912         }
 913                 
 914         if(sunaddr!=NULL)
 915         {
 916                 if(sock->type==SOCK_STREAM)
 917                 {
 918                         if(sk->state==TCP_ESTABLISHED)
 919                                 return -EISCONN;
 920                         else
 921                                 return -EOPNOTSUPP;
 922                 }
 923         }
 924 
 925         if(sunaddr==NULL)
 926         {
 927                 if(sk->protinfo.af_unix.other==NULL)
 928                         return -ENOTCONN;
 929         }
 930 
 931         /*
 932          *      A control message has been attached.
 933          */
 934         if(msg->msg_accrights) 
 935         {
 936                 struct cmsghdr *cm=unix_copyrights(msg->msg_accrights, 
 937                                                 msg->msg_accrightslen);
 938                 if(cm==NULL || msg->msg_accrightslen<sizeof(struct cmsghdr) ||
 939                    cm->cmsg_type!=SCM_RIGHTS ||
 940                    cm->cmsg_level!=SOL_SOCKET ||
 941                    msg->msg_accrightslen!=cm->cmsg_len)
 942                 {
 943                         kfree(cm);
 944                         return -EINVAL;
 945                 }
 946                 fpnum=unix_fd_copy(sk,cm,fp);
 947                 kfree(cm);
 948                 if(fpnum<0) {
 949                         return fpnum;
 950                 }
 951         }
 952 
 953         while(sent < len)
 954         {
 955                 /*
 956                  *      Optimisation for the fact that under 0.01% of X messages typically
 957                  *      need breaking up.
 958                  */
 959                  
 960                 size=len-sent;
 961 
 962                 if(size>(sk->sndbuf-sizeof(struct sk_buff))/2)  /* Keep two messages in the pipe so it schedules better */
 963                 {
 964                         if(sock->type==SOCK_DGRAM)
 965                         {
 966                                 unix_fd_free(sk,fp,fpnum);
 967                                 return -EMSGSIZE;
 968                         }
 969                         size=(sk->sndbuf-sizeof(struct sk_buff))/2;
 970                 }
 971                 /*
 972                  *      Keep to page sized kmalloc()'s as various people
 973                  *      have suggested. Big mallocs stress the vm too
 974                  *      much.
 975                  */
 976 
 977                 if(size > 4000 && sock->type!=SOCK_DGRAM)
 978                         limit = 4000;   /* Fall back to 4K if we can't grab a big buffer this instant */
 979                 else
 980                         limit = 0;      /* Otherwise just grab and wait */
 981 
 982                 /*
 983                  *      Grab a buffer
 984                  */
 985                  
 986                 skb=sock_alloc_send_skb(sk,size,limit,nonblock, &err);
 987                 
 988                 if(skb==NULL)
 989                 {
 990                         unix_fd_free(sk,fp,fpnum);
 991                         if(sent)
 992                         {
 993                                 sk->err=-err;
 994                                 return sent;
 995                         }
 996                         return err;
 997                 }
 998                 size=skb_tailroom(skb);         /* If we dropped back on a limit then our skb is smaller */
 999 
1000                 skb->sk=sk;
1001                 skb->free=1;
1002                 
1003                 if(fpnum)
1004                 {
1005                         unix_attach_fds(fpnum,fp,skb);
1006                         fpnum=0;
1007                 }
1008                 else
1009                         skb->h.filp=NULL;
1010 
1011                 memcpy_fromiovec(skb_put(skb,size),msg->msg_iov, size);
1012 
1013                 cli();
1014                 if(sunaddr==NULL)
1015                 {
1016                         other=sk->protinfo.af_unix.other;
1017                         if(sock->type==SOCK_DGRAM && other->dead)
1018                         {
1019                                 other->protinfo.af_unix.locks--;
1020                                 sk->protinfo.af_unix.other=NULL;
1021                                 sock->state=SS_UNCONNECTED;
1022                                 sti();
1023                                 kfree_skb(skb, FREE_WRITE);
1024                                 if(!sent)
1025                                         return -ECONNRESET;
1026                                 else
1027                                         return sent;
1028                         }
1029                 }
1030                 else
1031                 {
1032                         unix_mkname(sunaddr, msg->msg_namelen);
1033                         other=unix_find_other(sunaddr->sun_path, &err);
1034                         if(other==NULL)
1035                         {
1036                                 sti();
1037                                 kfree_skb(skb, FREE_WRITE);
1038                                 if(sent)
1039                                         return sent;
1040                                 else
1041                                         return err;
1042                         }
1043                 }
1044                 skb_queue_tail(&other->receive_queue, skb);
1045                 sti();
1046                 /* if we sent an fd, only do it once */
1047                 other->data_ready(other,size);
1048                 sent+=size;
1049         }
1050         return sent;
1051 }
1052 
1053 /*
1054  *      Sleep until data has arrive. But check for races..
1055  */
1056  
1057 static void unix_data_wait(unix_socket * sk)
     /* [previous][next][first][last][top][bottom][index][help] */
1058 {
1059         cli();
1060         if (!skb_peek(&sk->receive_queue)) {
1061                 sk->socket->flags |= SO_WAITDATA;
1062                 interruptible_sleep_on(sk->sleep);
1063                 sk->socket->flags &= ~SO_WAITDATA;
1064         }
1065         sti();
1066 }
1067 
1068 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] */
1069 {
1070         unix_socket *sk=sock->data;
1071         struct sockaddr_un *sunaddr=msg->msg_name;
1072         struct sk_buff *skb;
1073         int copied=0;
1074         unsigned char *sp;
1075         int len;
1076         int num;
1077         struct iovec *iov=msg->msg_iov;
1078         struct cmsghdr *cm=NULL;
1079         int ct=msg->msg_iovlen;
1080 
1081         if(flags&MSG_OOB)
1082                 return -EOPNOTSUPP;
1083                 
1084         if(addr_len)
1085                 *addr_len=0;
1086                 
1087         if(sk->err)
1088                 return sock_error(sk);
1089 
1090         if(msg->msg_accrights) 
1091         {
1092                 cm=unix_copyrights(msg->msg_accrights, 
1093                         msg->msg_accrightslen);
1094                 if(msg->msg_accrightslen<sizeof(struct cmsghdr)
1095 #if 0 
1096 /*              investigate this furthur -- Stevens example doen't seem to care */
1097                 ||
1098                    cm->cmsg_type!=SCM_RIGHTS ||
1099                    cm->cmsg_level!=SOL_SOCKET ||
1100                    msg->msg_accrightslen!=cm->cmsg_len
1101 #endif
1102                 )
1103                 {
1104                         kfree(cm);
1105                         printk("recvmsg: Bad msg_accrights\n");
1106                         return -EINVAL;
1107                 }
1108         }
1109         
1110         down(&sk->protinfo.af_unix.readsem);            /* Lock the socket */
1111         while(ct--)
1112         {
1113                 int done=0;
1114                 sp=iov->iov_base;
1115                 len=iov->iov_len;
1116                 iov++;
1117                 
1118                 while(done<len)
1119                 {
1120                         if (copied && (flags & MSG_PEEK))
1121                                 goto out;
1122                         if (copied == size)
1123                                 goto out;
1124                         skb=skb_dequeue(&sk->receive_queue);
1125                         if(skb==NULL)
1126                         {
1127                                 up(&sk->protinfo.af_unix.readsem);
1128                                 if(sk->shutdown & RCV_SHUTDOWN)
1129                                         return copied;
1130                                 if(copied)
1131                                         return copied;
1132                                 if(noblock)
1133                                         return -EAGAIN;
1134                                 if(current->signal & ~current->blocked)
1135                                         return -ERESTARTSYS;
1136                                 unix_data_wait(sk);
1137                                 down(&sk->protinfo.af_unix.readsem);
1138                                 continue;
1139                         }
1140                         if(msg->msg_name!=NULL)
1141                         {
1142                                 sunaddr->sun_family=AF_UNIX;
1143                                 if(skb->sk->protinfo.af_unix.name)
1144                                 {
1145                                         memcpy(sunaddr->sun_path, skb->sk->protinfo.af_unix.name, 108);
1146                                         if(addr_len)
1147                                                 *addr_len=strlen(sunaddr->sun_path)+sizeof(short);
1148                                 }
1149                                 else
1150                                         if(addr_len)
1151                                                 *addr_len=sizeof(short);
1152                         }
1153 
1154                         num=min(skb->len,len-done);
1155                         memcpy_tofs(sp, skb->data, num);
1156 
1157                         if (skb->h.filp!=NULL)
1158                                 unix_detach_fds(skb,cm);
1159 
1160                         copied+=num;
1161                         done+=num;
1162                         sp+=num;
1163                         if (!(flags & MSG_PEEK))
1164                                 skb_pull(skb, num);
1165                         /* put the skb back if we didn't use it up.. */
1166                         if (skb->len) {
1167                                 skb_queue_head(&sk->receive_queue, skb);
1168                                 continue;
1169                         }
1170                         kfree_skb(skb, FREE_WRITE);
1171                         if(sock->type==SOCK_DGRAM || cm)
1172                                 goto out;
1173                 }
1174         }
1175 out:
1176         up(&sk->protinfo.af_unix.readsem);
1177         if(cm)
1178                 unix_returnrights(msg->msg_accrights,msg->msg_accrightslen,cm);
1179         return copied;
1180 }
1181 
1182 static int unix_shutdown(struct socket *sock, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
1183 {
1184         unix_socket *sk=(unix_socket *)sock->data;
1185         unix_socket *other=sk->protinfo.af_unix.other;
1186         if(mode&SEND_SHUTDOWN)
1187         {
1188                 sk->shutdown|=SEND_SHUTDOWN;
1189                 sk->state_change(sk);
1190                 if(other)
1191                 {
1192                         other->shutdown|=RCV_SHUTDOWN;
1193                         other->state_change(other);
1194                 }
1195         }
1196         other=sk->protinfo.af_unix.other;
1197         if(mode&RCV_SHUTDOWN)
1198         {
1199                 sk->shutdown|=RCV_SHUTDOWN;
1200                 sk->state_change(sk);
1201                 if(other)
1202                 {
1203                         other->shutdown|=SEND_SHUTDOWN;
1204                         other->state_change(other);
1205                 }
1206         }
1207         return 0;
1208 }
1209 
1210                 
1211 static int unix_select(struct socket *sock,  int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
1212 {
1213         return datagram_select(sock->data,sel_type,wait);
1214 }
1215 
1216 static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1217 {
1218         unix_socket *sk=sock->data;
1219         int err;
1220         long amount=0;
1221                         
1222         switch(cmd)
1223         {
1224         
1225                 case TIOCOUTQ:
1226                         err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
1227                         if(err)
1228                                 return err;
1229                         amount=sk->sndbuf-sk->wmem_alloc;
1230                         if(amount<0)
1231                                 amount=0;
1232                         put_fs_long(amount,(unsigned long *)arg);
1233                         return 0;
1234                 case TIOCINQ:
1235                 {
1236                         struct sk_buff *skb;
1237                         if(sk->state==TCP_LISTEN)
1238                                 return -EINVAL;
1239                         /* These two are safe on a single CPU system as only user tasks fiddle here */
1240                         if((skb=skb_peek(&sk->receive_queue))!=NULL)
1241                                 amount=skb->len;
1242                         err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
1243                         put_fs_long(amount,(unsigned long *)arg);
1244                         return 0;
1245                 }
1246 
1247                 default:
1248                         return -EINVAL;
1249         }
1250         /*NOTREACHED*/
1251         return(0);
1252 }
1253 
1254 #ifdef CONFIG_PROC_FS
1255 static int unix_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
1256 {
1257         off_t pos=0;
1258         off_t begin=0;
1259         int len=0;
1260         unix_socket *s=unix_socket_list;
1261         
1262         len+= sprintf(buffer,"Num       RefCount Protocol Flags    Type St "
1263             "Inode Path\n");
1264         
1265         while(s!=NULL)
1266         {
1267                 len+=sprintf(buffer+len,"%p: %08X %08X %08lX %04X %02X %5ld",
1268                         s,
1269                         s->protinfo.af_unix.locks,
1270                         0,
1271                         s->socket->flags,
1272                         s->socket->type,
1273                         s->socket->state,
1274                         s->socket->inode ? s->socket->inode->i_ino : 0);
1275                 if(s->protinfo.af_unix.name!=NULL)
1276                         len+=sprintf(buffer+len, " %s\n", s->protinfo.af_unix.name);
1277                 else
1278                         buffer[len++]='\n';
1279                 
1280                 pos=begin+len;
1281                 if(pos<offset)
1282                 {
1283                         len=0;
1284                         begin=pos;
1285                 }
1286                 if(pos>offset+length)
1287                         break;
1288                 s=s->next;
1289         }
1290         *start=buffer+(offset-begin);
1291         len-=(offset-begin);
1292         if(len>length)
1293                 len=length;
1294         return len;
1295 }
1296 #endif
1297 
1298 struct proto_ops unix_proto_ops = {
1299         AF_UNIX,
1300         
1301         unix_create,
1302         unix_dup,
1303         unix_release,
1304         unix_bind,
1305         unix_connect,
1306         unix_socketpair,
1307         unix_accept,
1308         unix_getname,
1309         unix_select,
1310         unix_ioctl,
1311         unix_listen,
1312         unix_shutdown,
1313         unix_setsockopt,
1314         unix_getsockopt,
1315         unix_fcntl,
1316         unix_sendmsg,
1317         unix_recvmsg
1318 };
1319 
1320 
1321 void unix_proto_init(struct net_proto *pro)
     /* [previous][next][first][last][top][bottom][index][help] */
1322 {
1323         printk("NET3: Unix domain sockets 0.12 for Linux NET3.033.\n");
1324         sock_register(unix_proto_ops.family, &unix_proto_ops);
1325 #ifdef CONFIG_PROC_FS
1326         proc_net_register(&(struct proc_dir_entry) {
1327                 PROC_NET_UNIX,  4, "unix",
1328                 S_IFREG | S_IRUGO, 1, 0, 0,
1329                 0, &proc_net_inode_operations,
1330                 unix_get_info
1331         });
1332 #endif
1333 }
1334 /*
1335  * Local variables:
1336  *  compile-command: "gcc -g -D__KERNEL__ -Wall -O6 -I/usr/src/linux/include -c af_unix.c"
1337  * End:
1338  */

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