2 * NET3: Implementation of BSD Unix domain sockets. 4 * Authors: Alan Cox, <alan@cymru.net> 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. 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. 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. 23 #include <linux/config.h> 24 #include <linux/kernel.h> 25 #include <linux/major.h> 26 #include <linux/signal.h> 27 #include <linux/sched.h> 28 #include <linux/errno.h> 29 #include <linux/string.h> 30 #include <linux/stat.h> 31 #include <linux/socket.h> 33 #include <linux/fcntl.h> 34 #include <linux/termios.h> 35 #include <linux/socket.h> 36 #include <linux/sockios.h> 37 #include <linux/net.h> 40 #include <linux/malloc.h> 41 #include <asm/segment.h> 42 #include <linux/skbuff.h> 43 #include <linux/netdevice.h> 46 #include <net/af_unix.h> 47 #include <linux/proc_fs.h> 49 static unix_socket
*volatile unix_socket_list
=NULL
; 51 #define min(a,b) (((a)<(b))?(a):(b)) 54 * Make sure the unix name is null-terminated. 56 staticinlinevoidunix_mkname(struct sockaddr_un
* sun
,unsigned long len
) 58 if(len
>=sizeof(*sun
)) 64 * Note: Sockets may not be removed _during_ an interrupt or net_bh 65 * handler using this technique. They can be added although we do not 69 static voidunix_remove_socket(unix_socket
*sk
) 77 unix_socket_list
=s
->next
; 94 static voidunix_insert_socket(unix_socket
*sk
) 97 sk
->next
=unix_socket_list
; 102 static unix_socket
*unix_find_socket(struct inode
*i
) 109 if(s
->protinfo
.af_unix
.inode
==i
) 121 * Delete a unix socket. We have to allow for deferring this on a timer. 124 static voidunix_destroy_timer(unsigned long data
) 126 unix_socket
*sk
=(unix_socket
*)data
; 127 if(sk
->protinfo
.af_unix
.locks
==0&& sk
->wmem_alloc
==0) 129 if(sk
->protinfo
.af_unix
.name
) 130 kfree(sk
->protinfo
.af_unix
.name
); 131 kfree_s(sk
,sizeof(*sk
)); 139 init_timer(&sk
->timer
); 140 sk
->timer
.expires
=jiffies
+10*HZ
;/* No real hurry try it every 10 seconds or so */ 141 add_timer(&sk
->timer
); 145 static voidunix_delayed_delete(unix_socket
*sk
) 147 init_timer(&sk
->timer
); 148 sk
->timer
.data
=(unsigned long)sk
; 149 sk
->timer
.expires
=jiffies
+HZ
;/* Normally 1 second after will clean up. After that we try every 10 */ 150 sk
->timer
.function
=unix_destroy_timer
; 151 add_timer(&sk
->timer
); 154 static voidunix_destroy_socket(unix_socket
*sk
) 157 unix_remove_socket(sk
); 159 while((skb
=skb_dequeue(&sk
->receive_queue
))!=NULL
) 161 if(sk
->state
==TCP_LISTEN
) 163 unix_socket
*osk
=skb
->sk
; 164 osk
->state
=TCP_CLOSE
; 165 kfree_skb(skb
, FREE_WRITE
);/* Now surplus - free the skb first before the socket */ 166 osk
->state_change(osk
);/* So the connect wakes and cleans up (if any) */ 167 /* osk will be destroyed when it gets to close or the timer fires */ 171 /* unix_kill_credentials(skb); *//* Throw out any passed fd's */ 172 kfree_skb(skb
,FREE_WRITE
); 176 if(sk
->protinfo
.af_unix
.inode
!=NULL
) 178 iput(sk
->protinfo
.af_unix
.inode
); 179 sk
->protinfo
.af_unix
.inode
=NULL
; 182 if(--sk
->protinfo
.af_unix
.locks
==0&& sk
->wmem_alloc
==0) 184 if(sk
->protinfo
.af_unix
.name
) 185 kfree(sk
->protinfo
.af_unix
.name
); 186 kfree_s(sk
,sizeof(*sk
)); 191 unix_delayed_delete(sk
);/* Try every so often until buffers are all freed */ 196 * Fixme: We need async I/O on AF_UNIX doing next. 199 static intunix_fcntl(struct socket
*sock
,unsigned int cmd
,unsigned long arg
) 205 * Yes socket options work with the new unix domain socketry!!!!!!! 208 static intunix_setsockopt(struct socket
*sock
,int level
,int optname
,char*optval
,int optlen
) 210 unix_socket
*sk
=sock
->data
; 211 if(level
!=SOL_SOCKET
) 213 returnsock_setsockopt(sk
,level
,optname
,optval
,optlen
); 216 static intunix_getsockopt(struct socket
*sock
,int level
,int optname
,char*optval
,int*optlen
) 218 unix_socket
*sk
=sock
->data
; 219 if(level
!=SOL_SOCKET
) 221 returnsock_getsockopt(sk
,level
,optname
,optval
,optlen
); 224 static intunix_listen(struct socket
*sock
,int backlog
) 226 unix_socket
*sk
=sock
->data
; 227 if(sk
->type
!=SOCK_STREAM
) 228 return-EOPNOTSUPP
;/* Only stream sockets accept */ 229 sk
->max_ack_backlog
=backlog
; 230 sk
->state
=TCP_LISTEN
; 234 static voiddef_callback1(struct sock
*sk
) 237 wake_up_interruptible(sk
->sleep
); 240 static voiddef_callback2(struct sock
*sk
,int len
) 244 wake_up_interruptible(sk
->sleep
); 245 sock_wake_async(sk
->socket
,1); 249 static voiddef_callback3(struct sock
*sk
) 253 wake_up_interruptible(sk
->sleep
); 254 sock_wake_async(sk
->socket
,2); 258 static intunix_create(struct socket
*sock
,int protocol
) 261 /* printk("Unix create\n");*/ 262 if(protocol
&& protocol
!= PF_UNIX
) 263 return-EPROTONOSUPPORT
; 264 sk
=(unix_socket
*)kmalloc(sizeof(*sk
),GFP_KERNEL
); 275 kfree_s(sk
,sizeof(*sk
)); 276 return-ESOCKTNOSUPPORT
; 278 skb_queue_head_init(&sk
->write_queue
); 279 skb_queue_head_init(&sk
->receive_queue
); 280 skb_queue_head_init(&sk
->back_log
); 281 sk
->protinfo
.af_unix
.family
=AF_UNIX
; 282 sk
->protinfo
.af_unix
.inode
=NULL
; 283 sk
->protinfo
.af_unix
.locks
=1;/* Us */ 284 sk
->protinfo
.af_unix
.readsem
=MUTEX
;/* single task reading lock */ 285 sk
->protinfo
.af_unix
.name
=NULL
; 286 sk
->protinfo
.af_unix
.other
=NULL
; 293 sk
->rcvbuf
=SK_RMEM_MAX
; 294 sk
->sndbuf
=SK_WMEM_MAX
; 302 sk
->priority
=SOPRI_NORMAL
; 305 sk
->state_change
=def_callback1
; 306 sk
->data_ready
=def_callback2
; 307 sk
->write_space
=def_callback3
; 308 sk
->error_report
=def_callback1
; 311 sock
->data
=(void*)sk
; 312 sk
->sleep
=sock
->wait
; 314 unix_insert_socket(sk
); 318 static intunix_dup(struct socket
*newsock
,struct socket
*oldsock
) 320 returnunix_create(newsock
,0); 323 static intunix_release(struct socket
*sock
,struct socket
*peer
) 325 unix_socket
*sk
=sock
->data
; 328 /* May not have data attached */ 333 sk
->state_change(sk
); 335 skpair
=(unix_socket
*)sk
->protinfo
.af_unix
.other
;/* Person we send to (default) */ 336 if(sk
->type
==SOCK_STREAM
&& skpair
!=NULL
&& skpair
->state
!=TCP_LISTEN
) 338 skpair
->shutdown
=SHUTDOWN_MASK
;/* No more writes */ 339 skpair
->state_change(skpair
);/* Wake any blocked writes */ 342 skpair
->protinfo
.af_unix
.locks
--;/* It may now die */ 343 sk
->protinfo
.af_unix
.other
=NULL
;/* No pair */ 344 unix_destroy_socket(sk
);/* Try and flush out this socket. Throw our buffers at least */ 349 static unix_socket
*unix_find_other(char*path
,int*error
) 358 err
=open_namei(path
,2, S_IFSOCK
, &inode
, NULL
); 365 u
=unix_find_socket(inode
); 369 *error
=-ECONNREFUSED
; 376 static intunix_bind(struct socket
*sock
,struct sockaddr
*uaddr
,int addr_len
) 378 struct sockaddr_un
*sun
=(struct sockaddr_un
*)uaddr
; 379 unix_socket
*sk
=sock
->data
; 383 if(addr_len
>sizeof(struct sockaddr_un
) || addr_len
<3|| sun
->sun_family
!=AF_UNIX
) 385 unix_mkname(sun
, addr_len
); 387 * Put ourselves in the filesystem 389 if(sk
->protinfo
.af_unix
.inode
!=NULL
) 392 sk
->protinfo
.af_unix
.name
=kmalloc(addr_len
+1, GFP_KERNEL
); 393 if(sk
->protinfo
.af_unix
.name
==NULL
) 395 memcpy(sk
->protinfo
.af_unix
.name
, sun
->sun_path
, addr_len
+1); 400 err
=do_mknod(sk
->protinfo
.af_unix
.name
,S_IFSOCK
|S_IRWXUGO
,0); 402 err
=open_namei(sk
->protinfo
.af_unix
.name
,2, S_IFSOCK
, &sk
->protinfo
.af_unix
.inode
, NULL
); 408 kfree_s(sk
->protinfo
.af_unix
.name
,addr_len
+1); 409 sk
->protinfo
.af_unix
.name
=NULL
; 420 static intunix_connect(struct socket
*sock
,struct sockaddr
*uaddr
,int addr_len
,int flags
) 422 unix_socket
*sk
=sock
->data
; 423 struct sockaddr_un
*sun
=(struct sockaddr_un
*)uaddr
; 428 if(sk
->type
==SOCK_STREAM
&& sk
->protinfo
.af_unix
.other
) 430 if(sock
->state
==SS_CONNECTING
&& sk
->state
==TCP_ESTABLISHED
) 432 sock
->state
=SS_CONNECTED
; 435 if(sock
->state
==SS_CONNECTING
&& sk
->state
== TCP_CLOSE
) 437 sock
->state
=SS_UNCONNECTED
; 440 if(sock
->state
==SS_CONNECTING
) 445 if(addr_len
<sizeof(sun
->sun_family
)+1|| sun
->sun_family
!=AF_UNIX
) 448 unix_mkname(sun
, addr_len
); 450 if(sk
->type
==SOCK_DGRAM
&& sk
->protinfo
.af_unix
.other
) 452 sk
->protinfo
.af_unix
.other
->protinfo
.af_unix
.locks
--; 453 sk
->protinfo
.af_unix
.other
=NULL
; 454 sock
->state
=SS_UNCONNECTED
; 457 if(sock
->type
==SOCK_DGRAM
) 459 other
=unix_find_other(sun
->sun_path
, &err
); 462 other
->protinfo
.af_unix
.locks
++; 463 sk
->protinfo
.af_unix
.other
=other
; 464 sock
->state
=SS_CONNECTED
; 465 sk
->state
=TCP_ESTABLISHED
; 470 if(sock
->state
==SS_UNCONNECTED
) 473 * Now ready to connect 476 skb
=sock_alloc_send_skb(sk
,0,0, &err
);/* Marker object */ 479 skb
->sk
=sk
;/* So they know it is us */ 482 unix_mkname(sun
, addr_len
); 483 other
=unix_find_other(sun
->sun_path
, &err
); 486 kfree_skb(skb
, FREE_WRITE
); 489 other
->protinfo
.af_unix
.locks
++;/* Lock the other socket so it doesn't run off for a moment */ 490 other
->ack_backlog
++; 491 sk
->protinfo
.af_unix
.other
=other
; 492 skb_queue_tail(&other
->receive_queue
,skb
); 493 sk
->state
=TCP_SYN_SENT
; 494 sock
->state
=SS_CONNECTING
; 496 other
->data_ready(other
,0);/* Wake up ! */ 500 /* Wait for an accept */ 503 while(sk
->state
==TCP_SYN_SENT
) 510 interruptible_sleep_on(sk
->sleep
); 511 if(current
->signal
& ~current
->blocked
) 519 * Has the other end closed on us ? 522 if(sk
->state
==TCP_CLOSE
) 524 sk
->protinfo
.af_unix
.other
->protinfo
.af_unix
.locks
--; 525 sk
->protinfo
.af_unix
.other
=NULL
; 526 sock
->state
=SS_UNCONNECTED
; 532 * Amazingly it has worked 535 sock
->state
=SS_CONNECTED
; 541 static intunix_socketpair(struct socket
*a
,struct socket
*b
) 544 unix_socket
*ska
,*skb
; 546 err
=unix_create(a
,0); 549 err
=unix_create(b
,0); 552 unix_release(a
, NULL
); 560 /* Join our sockets back to back */ 561 ska
->protinfo
.af_unix
.locks
++; 562 skb
->protinfo
.af_unix
.locks
++; 563 ska
->protinfo
.af_unix
.other
=skb
; 564 skb
->protinfo
.af_unix
.other
=ska
; 565 ska
->state
=TCP_ESTABLISHED
; 566 skb
->state
=TCP_ESTABLISHED
; 570 static intunix_accept(struct socket
*sock
,struct socket
*newsock
,int flags
) 572 unix_socket
*sk
=sock
->data
; 573 unix_socket
*newsk
, *tsk
; 576 if(sk
->type
!=SOCK_STREAM
) 580 if(sk
->state
!=TCP_LISTEN
) 586 if(sk
->protinfo
.af_unix
.name
!=NULL
) 588 newsk
->protinfo
.af_unix
.name
=kmalloc(strlen(sk
->protinfo
.af_unix
.name
)+1, GFP_KERNEL
); 589 if(newsk
->protinfo
.af_unix
.name
==NULL
) 591 strcpy(newsk
->protinfo
.af_unix
.name
, sk
->protinfo
.af_unix
.name
); 597 skb
=skb_dequeue(&sk
->receive_queue
); 605 interruptible_sleep_on(sk
->sleep
); 606 if(current
->signal
& ~current
->blocked
) 616 kfree_skb(skb
, FREE_WRITE
);/* The buffer is just used as a tag */ 618 newsk
->protinfo
.af_unix
.other
=tsk
; 619 tsk
->protinfo
.af_unix
.other
=newsk
; 620 tsk
->state
=TCP_ESTABLISHED
; 621 newsk
->state
=TCP_ESTABLISHED
; 622 newsk
->protinfo
.af_unix
.locks
++;/* Swap lock over */ 623 sk
->protinfo
.af_unix
.locks
--;/* Locked to child socket not master */ 624 tsk
->protinfo
.af_unix
.locks
++;/* Back lock */ 626 tsk
->state_change(tsk
);/* Wake up any sleeping connect */ 627 sock_wake_async(tsk
->socket
,0); 631 static intunix_getname(struct socket
*sock
,struct sockaddr
*uaddr
,int*uaddr_len
,int peer
) 633 unix_socket
*sk
=sock
->data
; 634 struct sockaddr_un
*sun
=(struct sockaddr_un
*)uaddr
; 638 if(sk
->protinfo
.af_unix
.other
==NULL
) 640 sk
=sk
->protinfo
.af_unix
.other
; 642 sun
->sun_family
=AF_UNIX
; 643 if(sk
->protinfo
.af_unix
.name
==NULL
) 646 *uaddr_len
=sizeof(sun
->sun_family
)+1; 647 return0;/* Not bound */ 649 *uaddr_len
=sizeof(sun
->sun_family
)+strlen(sk
->protinfo
.af_unix
.name
)+1; 650 strcpy(sun
->sun_path
,sk
->protinfo
.af_unix
.name
);/* 108 byte limited */ 654 static intunix_sendmsg(struct socket
*sock
,struct msghdr
*msg
,int len
,int nonblock
,int flags
) 656 unix_socket
*sk
=sock
->data
; 658 struct sockaddr_un
*sun
=msg
->msg_name
; 671 if(flags
|| msg
->msg_accrights
)/* For now */ 676 if(sock
->type
==SOCK_STREAM
) 678 if(sk
->state
==TCP_ESTABLISHED
) 686 if(sk
->protinfo
.af_unix
.other
==NULL
) 691 * Optimisation for the fact that under 0.01% of X messages typically 695 if(len
>(sk
->sndbuf
-sizeof(struct sk_buff
))/2)/* Keep two messages in the pipe so it schedules better */ 697 if(sock
->type
==SOCK_DGRAM
) 699 len
=(sk
->sndbuf
-sizeof(struct sk_buff
))/2; 701 * Keep to page sized kmalloc()'s as various people 702 * have suggested. Big mallocs stress the vm too 705 if(len
>4000&& sock
->type
!=SOCK_DGRAM
) 709 size
=/*protocol_size(&proto_unix)+*/len
; 710 skb
=sock_alloc_send_skb(sk
,size
,nonblock
, &err
); 713 /* protocol_adjust(skb,&proto_unix);*/ 716 memcpy_fromiovec(skb_put(skb
,len
),msg
->msg_iov
, len
); 721 other
=sk
->protinfo
.af_unix
.other
; 722 if(sock
->type
==SOCK_DGRAM
&& other
->dead
) 724 other
->protinfo
.af_unix
.locks
--; 725 sk
->protinfo
.af_unix
.other
=NULL
; 726 sock
->state
=SS_UNCONNECTED
; 733 unix_mkname(sun
, msg
->msg_namelen
); 734 other
=unix_find_other(sun
->sun_path
, &err
); 737 kfree_skb(skb
, FREE_WRITE
); 742 skb_queue_tail(&other
->receive_queue
, skb
); 744 other
->data_ready(other
,len
); 748 static intunix_recvmsg(struct socket
*sock
,struct msghdr
*msg
,int size
,int noblock
,int flags
,int*addr_len
) 750 unix_socket
*sk
=sock
->data
; 751 struct sockaddr_un
*sun
=msg
->msg_name
; 758 struct iovec
*iov
=msg
->msg_iov
; 759 int ct
=msg
->msg_iovlen
; 773 /* printk("get rcv sem\n");*/ 774 down(&sk
->protinfo
.af_unix
.readsem
);/* Lock the socket */ 775 /* printk("got rcv sem\n");*/ 786 if(copied
& (flags
&MSG_PEEK
)) 788 up(&sk
->protinfo
.af_unix
.readsem
); 792 skb
=skb_peek(&sk
->receive_queue
); 795 up(&sk
->protinfo
.af_unix
.readsem
); 796 if(sk
->shutdown
& RCV_SHUTDOWN
) 811 sk
->socket
->flags
|= SO_WAITDATA
; 812 interruptible_sleep_on(sk
->sleep
); 813 sk
->socket
->flags
&= ~SO_WAITDATA
; 814 if( current
->signal
& ~current
->blocked
) 822 down(&sk
->protinfo
.af_unix
.readsem
); 825 if(msg
->msg_name
!=NULL
) 827 sun
->sun_family
=AF_UNIX
; 828 if(skb
->sk
->protinfo
.af_unix
.name
) 830 memcpy(sun
->sun_path
, skb
->sk
->protinfo
.af_unix
.name
,108); 832 *addr_len
=strlen(sun
->sun_path
)+sizeof(short); 836 *addr_len
=sizeof(short); 838 num
=min(skb
->len
,size
-copied
); 843 memcpy_tofs(sp
, skb
->data
, num
); 848 memcpy_tofs(sp
, skb
->data
,num
); 854 kfree_skb(skb
, FREE_WRITE
); 855 if(sock
->type
==SOCK_DGRAM
) 862 up(&sk
->protinfo
.af_unix
.readsem
); 866 static intunix_shutdown(struct socket
*sock
,int mode
) 868 unix_socket
*sk
=(unix_socket
*)sock
->data
; 869 unix_socket
*other
=sk
->protinfo
.af_unix
.other
; 870 if(mode
&SEND_SHUTDOWN
) 872 sk
->shutdown
|=SEND_SHUTDOWN
; 873 sk
->state_change(sk
); 876 other
->shutdown
|=RCV_SHUTDOWN
; 877 other
->state_change(other
); 880 other
=sk
->protinfo
.af_unix
.other
; 881 if(mode
&RCV_SHUTDOWN
) 883 sk
->shutdown
|=RCV_SHUTDOWN
; 884 sk
->state_change(sk
); 887 other
->shutdown
|=SEND_SHUTDOWN
; 888 other
->state_change(other
); 895 static intunix_select(struct socket
*sock
,int sel_type
, select_table
*wait
) 897 returndatagram_select(sock
->data
,sel_type
,wait
); 900 static intunix_ioctl(struct socket
*sock
,unsigned int cmd
,unsigned long arg
) 902 unix_socket
*sk
=sock
->data
; 910 err
=verify_area(VERIFY_WRITE
,(void*)arg
,sizeof(unsigned long)); 913 amount
=sk
->sndbuf
-sk
->wmem_alloc
; 916 put_fs_long(amount
,(unsigned long*)arg
); 921 if(sk
->state
==TCP_LISTEN
) 923 /* These two are safe on a single CPU system as only user tasks fiddle here */ 924 if((skb
=skb_peek(&sk
->receive_queue
))!=NULL
) 926 err
=verify_area(VERIFY_WRITE
,(void*)arg
,sizeof(unsigned long)); 927 put_fs_long(amount
,(unsigned long*)arg
); 938 static intunix_get_info(char*buffer
,char**start
, off_t offset
,int length
,int dummy
) 943 unix_socket
*s
=unix_socket_list
; 945 len
+=sprintf(buffer
,"Num RefCount Protocol Flags Type St Path\n"); 949 len
+=sprintf(buffer
+len
,"%p: %08X %08X %08lX %04X %02X", 951 s
->protinfo
.af_unix
.locks
, 956 if(s
->protinfo
.af_unix
.name
!=NULL
) 957 len
+=sprintf(buffer
+len
," %s\n", s
->protinfo
.af_unix
.name
); 967 if(pos
>offset
+length
) 971 *start
=buffer
+(offset
-begin
); 979 * For AF_UNIX we flip everything into an iovec. If this doesnt do any speed harm then it will 980 * be easier for all the low levels to be totally iovec based. 983 static intunix_recvfrom(struct socket
*sock
,void*ubuf
,int size
,int noblock
,unsigned flags
, 984 struct sockaddr
*sa
,int*addr_len
) 990 msg
.msg_name
=(void*)sa
; 993 msg
.msg_namelen
= *addr_len
; 994 msg
.msg_accrights
=NULL
; 997 returnunix_recvmsg(sock
,&msg
,size
,noblock
,flags
,addr_len
); 1000 static intunix_read(struct socket
*sock
,char*ubuf
,int size
,int noblock
) 1002 returnunix_recvfrom(sock
,ubuf
,size
,noblock
,0,NULL
,NULL
); 1005 static intunix_recv(struct socket
*sock
,void*ubuf
,int size
,int noblock
,unsigned int flags
) 1007 returnunix_recvfrom(sock
,ubuf
,size
,noblock
,flags
,NULL
,NULL
); 1010 static intunix_sendto(struct socket
*sock
,const void*ubuf
,int size
,int noblock
,unsigned flags
, 1011 struct sockaddr
*sa
,int addr_len
) 1015 iov
.iov_base
=(void*)ubuf
; 1017 msg
.msg_name
=(void*)sa
; 1018 msg
.msg_namelen
=addr_len
; 1019 msg
.msg_accrights
=NULL
; 1022 returnunix_sendmsg(sock
,&msg
,size
,noblock
,flags
); 1025 static intunix_write(struct socket
*sock
,const char*ubuf
,int size
,int noblock
) 1027 returnunix_sendto(sock
,ubuf
,size
,noblock
,0, NULL
,0); 1030 static intunix_send(struct socket
*sock
,const void*ubuf
,int size
,int noblock
,unsigned int flags
) 1032 returnunix_sendto(sock
,ubuf
,size
,noblock
, flags
, NULL
,0); 1036 static struct proto_ops unix_proto_ops
= { 1065 voidunix_proto_init(struct net_proto
*pro
) 1067 printk("NET3: Unix domain sockets 0.09 BETA for Linux NET3.030.\n"); 1068 sock_register(unix_proto_ops
.family
, &unix_proto_ops
); 1069 proc_net_register(&(struct proc_dir_entry
) { 1070 PROC_NET_UNIX
,4,"unix", 1071 S_IFREG
| S_IRUGO
,1,0,0, 1072 0, &proc_net_inode_operations
, 1078 * compile-command: "gcc -g -D__KERNEL__ -Wall -O6 -I/usr/src/linux/include -c af_unix.c"