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

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