8 typedef struct Socket Socket
;
9 typedef struct Connectproc Connectproc
;
10 typedef struct Listenproc Listenproc
;
32 Connectproc
*connectproc
;
33 Listenproc
*listenproc
;
77 srvname(char *npath
, char *path
, int len
)
81 p
= strrchr(path
, '/');
86 snprint(npath
, len
, "/srv/UD.%s", p
);
91 srvunixsock(int fd
, char *path
)
95 char buf
[8+Ctlsize
+1];
101 srvname(buf
, path
, sizeof(buf
));
103 if((sfd
= create(buf
, OWRITE
, 0666)) < 0)
105 sprint(buf
, "%d", fd
);
106 if(write(sfd
, buf
, strlen(buf
)) < 0)
116 unsrvunixsock(char *path
)
118 char buf
[8+Ctlsize
+1];
120 srvname(buf
, path
, sizeof(buf
));
125 allocsock(int family
, int stype
, int protocol
)
129 sock
= kmallocz(sizeof(*sock
), 1);
130 sock
->family
= family
;
132 sock
->protocol
= protocol
;
143 newsock(int family
, int stype
, int protocol
)
153 trace("newsock(%d, %d, %d)", family
, stype
, protocol
);
167 trace("newsock() unknown socket type %d/%d", family
, stype
);
176 trace("newsock() unknown network family %d", family
);
180 sock
= allocsock(family
, stype
, protocol
);
187 sock
->other
= pfd
[1];
190 snprint(buf
, sizeof(buf
), "/net/%s/clone", net
);
191 if((cfd
= open(buf
, ORDWR
)) < 0){
195 n
= read(cfd
, buf
, sizeof(buf
)-1);
202 snprint(buf
, sizeof(buf
), "/net/%s/%d/data", net
, n
);
203 if((dfd
= open(buf
, ORDWR
)) < 0){
209 snprint(sock
->net
, sizeof(sock
->net
), "/net/%s", net
);
210 snprint(sock
->name
, sizeof(sock
->name
), "%s/%d", sock
->net
, n
);
212 return newfd(sock
, FD_CLOEXEC
);
221 freeconnectproc(Connectproc
*cp
)
228 write(cp
->notefd
, "interrupt", 9);
238 freelistenproc(Listenproc
*lp
)
247 write(lp
->notefd
, "interrupt", 9);
261 closesock(Ufile
*file
)
263 Socket
*sock
= (Socket
*)file
;
267 freebufproc(sock
->bufproc
);
268 freeconnectproc(sock
->connectproc
);
269 freelistenproc(sock
->listenproc
);
275 connectproc(void *aux
)
278 char buf
[Ctlsize
], tmp
[8+Ctlsize
+1];
283 cp
= (Connectproc
*)aux
;
285 if((sock
= cp
->sock
) == nil
)
288 snprint(buf
, sizeof(buf
), "connectproc() %s", cp
->str
);
292 switch(sock
->family
){
299 srvname(tmp
, cp
->str
, sizeof(buf
));
300 if((cfd
= open(tmp
, ORDWR
)) < 0)
303 memset(buf
, 0, sizeof(buf
));
304 snprint(buf
, sizeof(buf
), "linuxemu.%d.%lux", getpid(), (ulong
)sock
);
305 if(srvunixsock(other
, buf
) < 0){
311 * write Ctrlsize-1 bytes so concurrent writes will not be merged together as
312 * Ctrlsize-1 is the size used in read(). see /sys/src/ape/lib/bsd/accept.c:87
313 * this should be fixed in ape's connect() as well.
315 if(write(cfd
, buf
, sizeof(buf
)-1) != sizeof(buf
)-1){
321 if((read(fd
, tmp
, strlen(buf
)) != strlen(buf
)) || memcmp(buf
, tmp
, strlen(buf
))){
330 snprint(buf
, sizeof(buf
), "%s/ctl", sock
->name
);
332 if((cfd
= open(buf
, ORDWR
)) < 0){
336 if(fprint(cfd
, "connect %s", cp
->str
) < 0)
342 if((sock
= cp
->sock
) == nil
)
351 wakeq(&cp
->wq
, MAXPROC
);
357 sockaddr2str(Socket
*sock
, uchar
*addr
, int addrlen
, char *buf
, int nbuf
)
362 switch(sock
->family
){
366 err
= snprint(buf
, nbuf
, "%d.%d.%d.%d!%d",
371 (int)(((ulong
)addr
[2]<<8)|(ulong
)addr
[3]));
384 memmove(buf
, addr
+2, addrlen
);
394 connectsock(Socket
*sock
, uchar
*addr
, int addrlen
)
403 if(sock
->connectproc
)
406 if((err
= sockaddr2str(sock
, addr
, addrlen
, buf
, sizeof(buf
))) < 0)
409 cp
= kmallocz(sizeof(*cp
), 1);
412 strncpy(cp
->str
, buf
, sizeof(cp
->str
));
416 if((pid
= procfork(connectproc
, cp
, 0)) < 0){
421 snprint(buf
, sizeof(buf
), "/proc/%d/note", pid
);
422 cp
->notefd
= open(buf
, OWRITE
);
424 if(addrlen
> sizeof(sock
->addr
))
425 addrlen
= sizeof(sock
->addr
);
426 sock
->naddr
= addrlen
;
427 memmove(sock
->addr
, addr
, addrlen
);
429 sock
->connectproc
= cp
;
430 if(sock
->mode
& O_NONBLOCK
){
434 if((err
= sleepq(&cp
->wq
, cp
, 1)) == 0)
439 * crazy shit is going on!
440 * see: http://www.madore.org/~david/computers/connect-intr.html
442 if(err
!= -EINTR
&& err
!= -ERESTART
){
443 sock
->connectproc
= nil
;
450 shutdownsock(Socket
*sock
, int how
)
454 freebufproc(sock
->bufproc
);
456 freeconnectproc(sock
->connectproc
);
457 sock
->connectproc
= nil
;
458 freelistenproc(sock
->listenproc
);
459 sock
->listenproc
= nil
;
468 bindsock(Socket
*sock
, uchar
*addr
, int addrlen
)
475 switch(sock
->family
){
484 port
= (int)(((ulong
)addr
[2]<<8)|(ulong
)addr
[3]);
492 snprint(buf
, sizeof(buf
), "%s/ctl", sock
->name
);
493 if((cfd
= open(buf
, ORDWR
)) < 0)
495 if((fprint(cfd
, "announce %d", port
) < 0) || (fprint(cfd
, "bind %d", port
) < 0)){
502 if(addrlen
> sizeof(sock
->addr
))
503 addrlen
= sizeof(sock
->addr
);
504 sock
->naddr
= addrlen
;
505 memmove(sock
->addr
, addr
, addrlen
);
511 strtoip(char *str
, uchar
*ip
, int iplen
)
518 memset(ip
, 0, iplen
);
519 for(p
= str
; *p
; p
++){
524 for(k
= p
+1; *k
; k
++){
539 } else if(*p
== '.'){
544 for(k
= p
; *k
&& *k
!= '.' && *k
!= ':'; k
++)
548 } else if(*k
== ':'){
552 if(i
< 0 || i
+ v6
+1 > iplen
)
555 if(*p
>= '0' && *p
<= '9'){
557 } else if(v6
&& (*p
>= 'a' && *p
<= 'f')){
559 } else if(v6
&& (*p
>= 'A' && *p
<= 'F')){
566 d
|= ((int)ip
[i
]<<12 | (int)ip
[i
+1]<<4);
567 ip
[i
] = (d
>>8) & 0xFF;
570 ip
[i
] = ip
[i
]*10 + d
;
578 getsockaddr(Socket
*sock
, int remote
, uchar
*addr
, int len
)
587 switch(sock
->family
){
589 if(len
< sock
->naddr
)
591 memmove(a
, sock
->addr
, sock
->naddr
);
595 snprint(buf
, sizeof(buf
), "%s/%s", sock
->name
, remote
?"remote":"local");
596 if((fd
= open(buf
, OREAD
)) < 0)
598 if((n
= read(fd
, buf
, sizeof(buf
)-1)) < 0){
603 if(n
> 0 && buf
[n
-1] == '\n')
611 if((p
= strrchr(buf
, '!')) == nil
)
616 trace("getsockaddr(): ip=%s port=%d", buf
, port
);
618 switch(sock
->family
){
625 a
[0] = sock
->family
& 0xFF;
626 a
[1] = (sock
->family
>>8) & 0xFF;
627 a
[2] = (port
>> 8) & 0xFF;
629 if(strtoip(buf
, &a
[4], 4) < 0)
642 listenproc(void *aux
)
646 char buf
[Ctlsize
], tmp
[8+Ctlsize
+1];
649 lp
= (Listenproc
*)aux
;
651 if((sock
= lp
->sock
) == nil
)
654 snprint(buf
, sizeof(buf
), "listenproc() %s", lp
->str
);
660 switch(sock
->family
){
662 srvunixsock(sock
->other
, lp
->str
);
667 n
= read(fd
, buf
, sizeof(buf
)-1);
672 snprint(buf
, sizeof(buf
), "%s/listen", sock
->name
);
674 if((cfd
= open(buf
, ORDWR
)) >= 0)
675 n
= read(cfd
, buf
, sizeof(buf
)-1);
684 if((sock
= lp
->sock
) == nil
){
689 switch(sock
->family
){
691 srvname(tmp
, buf
, sizeof(tmp
));
692 if((fd
= open(tmp
, ORDWR
)) < 0)
695 if(write(fd
, buf
, strlen(buf
)) != strlen(buf
)){
704 snprint(buf
, sizeof(buf
), "%s/%d", sock
->net
, n
);
705 snprint(tmp
, sizeof(tmp
), "%s/data", buf
);
706 fd
= open(tmp
, ORDWR
);
714 q
= allocsock(sock
->family
, sock
->stype
, sock
->protocol
);
715 strncpy(q
->net
, sock
->net
, sizeof(q
->net
));
716 strncpy(q
->name
, buf
, sizeof(q
->name
));
718 if(sock
->family
== AF_UNIX
){
719 memmove(q
->addr
, sock
->addr
, q
->naddr
= sock
->naddr
);
721 q
->naddr
= getsockaddr(q
, 0, q
->addr
, sizeof(q
->addr
));
728 wakeq(&lp
->wq
, MAXPROC
);
731 if(sock
->family
== AF_UNIX
)
732 unsrvunixsock(lp
->str
);
734 wakeq(&lp
->wq
, MAXPROC
);
741 listensock(Socket
*sock
)
747 trace("listensock()");
751 if((err
= sockaddr2str(sock
, sock
->addr
, sock
->naddr
, buf
, sizeof(buf
))) < 0)
754 lp
= kmallocz(sizeof(*lp
), 1);
757 strncpy(lp
->str
, buf
, sizeof(lp
->str
));
760 if((pid
= procfork(listenproc
, lp
, 0)) < 0){
765 snprint(buf
, sizeof(buf
), "/proc/%d/note", pid
);
766 lp
->notefd
= open(buf
, OWRITE
);
767 sock
->listenproc
= lp
;
774 getsockname(Socket
*sock
, uchar
*addr
, int *paddrlen
)
778 trace("getsockname(%p, %p, %p (%x))", sock
, addr
, paddrlen
, paddrlen
? *paddrlen
: 0);
780 if(addr
== nil
|| paddrlen
== nil
)
784 memmove(addr
, sock
->addr
, ret
);
791 getpeername(Socket
*sock
, uchar
*addr
, int *paddrlen
)
795 trace("getpeername(%p, %p, %p (%x))", sock
, addr
, paddrlen
, paddrlen
? *paddrlen
: 0);
797 if(addr
== nil
|| paddrlen
== nil
)
800 if((ret
= getsockaddr(sock
, 1, addr
, *paddrlen
)) > 0)
806 acceptsock(Socket
*sock
, uchar
*addr
, int *paddrlen
)
812 trace("acceptsock(%p, %p, %p (%x))", sock
, addr
, paddrlen
, paddrlen
? *paddrlen
: 0);
814 if((lp
= sock
->listenproc
) == nil
)
824 if(addr
!= nil
&& paddrlen
!= nil
){
825 err
= getsockaddr(nsock
, 1, addr
, *paddrlen
);
826 *paddrlen
= err
< 0 ? 0 : err
;
828 return newfd(nsock
, FD_CLOEXEC
);
831 if(sock
->mode
& O_NONBLOCK
){
836 if((err
= sleepq(&lp
->wq
, lp
, 1)) < 0)
845 socketpair(int family
, int stype
, int protocol
, int sv
[2])
851 trace("socketpair(%d, %d, %d, %p)", family
, stype
, protocol
, sv
);
853 if(family
!= AF_UNIX
)
854 return -EAFNOSUPPORT
;
858 sock
= allocsock(family
, stype
, protocol
);
861 if((fd
= newfd(sock
, FD_CLOEXEC
)) < 0){
874 bufprocsock(Socket
*sock
)
876 if(sock
->bufproc
== nil
)
877 sock
->bufproc
= newbufproc(sock
->fd
);
878 return sock
->bufproc
;
882 pollsock(Ufile
*file
, void *tab
)
884 Socket
*sock
= (Socket
*)file
;
888 if(!sock
->connected
){
889 if(lp
= sock
->listenproc
){
891 pollwait(file
, &lp
->wq
, tab
);
898 if(cp
= sock
->connectproc
){
900 pollwait(file
, &cp
->wq
, tab
);
910 return pollbufproc(bufprocsock(sock
), sock
, tab
);
914 readsock(Ufile
*file
, void *buf
, int len
, vlong
)
916 Socket
*sock
= (Socket
*)file
;
921 if((sock
->mode
& O_NONBLOCK
) || (sock
->bufproc
!= nil
)){
922 ret
= readbufproc(bufprocsock(sock
), buf
, len
, 0, (sock
->mode
& O_NONBLOCK
));
926 ret
= read(sock
->fd
, buf
, len
);
934 extern int pipewrite(int fd
, void *buf
, int len
);
937 writesock(Ufile
*file
, void *buf
, int len
, vlong
)
939 Socket
*sock
= (Socket
*)file
;
944 if(sock
->family
== AF_UNIX
)
945 return pipewrite(sock
->fd
, buf
, len
);
948 ret
= write(sock
->fd
, buf
, len
);
956 ioctlsock(Ufile
*file
, int cmd
, void *arg
)
958 Socket
*sock
= (Socket
*)file
;
969 if((r
= nreadablebufproc(bufprocsock(sock
))) < 0){
980 sendto(Socket
*sock
, void *data
, int len
, int, uchar
*, int)
982 trace("sendto(%p, %p, %d, ...)", sock
, data
, len
);
984 return writesock(sock
, data
, len
, sock
->off
);
988 recvfrom(Socket
*sock
, void *data
, int len
, int flags
, uchar
*addr
, int addrlen
)
992 trace("recvfrom(%p, %p, %d, %x, %p, %d)", sock
, data
, len
, flags
, addr
, addrlen
);
997 ret
= readbufproc(bufprocsock(sock
), data
, len
, 1, 1);
999 ret
= readsock(sock
, data
, len
, sock
->off
);
1002 memmove(addr
, sock
->addr
, sock
->naddr
);
1017 getoptsock(Socket
*sock
, int lvl
, int opt
, char *ov
, int *ol
)
1019 trace("getoptsock(%p, %d, %d, %p, %p)", sock
, lvl
, opt
, ov
, ol
);
1032 *((int*)ov
) = sock
->error
;
1061 int sys_linux_socketcall(int call
, int *arg
)
1066 trace("sys_linux_socketcall(%d, %p)", call
, arg
);
1068 if(call
== SYS_SOCKET
)
1069 return newsock(arg
[0], arg
[1], arg
[2]);
1071 if(call
== SYS_SOCKETPAIR
)
1072 return socketpair(arg
[0], arg
[1], arg
[2], (int*)arg
[3]);
1074 if((sock
= (Socket
*)fdgetfile(arg
[0])) == nil
)
1077 if(sock
->dev
!= SOCKDEV
){
1085 ret
= connectsock(sock
, (void*)arg
[1], arg
[2]);
1088 ret
= sendto(sock
, (void*)arg
[1], arg
[2], arg
[3], (void*)arg
[4], arg
[5]);
1091 ret
= recvfrom(sock
, (void*)arg
[1], arg
[2], arg
[3], (void*)arg
[4], arg
[5]);
1094 ret
= sendto(sock
, (void*)arg
[1], arg
[2], arg
[3], nil
, 0);
1097 ret
= recvfrom(sock
, (void*)arg
[1], arg
[2], arg
[3], nil
, 0);
1099 case SYS_GETSOCKNAME
:
1100 ret
= getsockname(sock
, (void*)arg
[1], (void*)arg
[2]);
1102 case SYS_GETPEERNAME
:
1103 ret
= getpeername(sock
, (void*)arg
[1], (void*)arg
[2]);
1106 ret
= shutdownsock(sock
, arg
[1]);
1109 ret
= bindsock(sock
, (void*)arg
[1], arg
[2]);
1112 ret
= listensock(sock
);
1115 ret
= acceptsock(sock
, (void*)arg
[1], (void*)arg
[2]);
1117 case SYS_SETSOCKOPT
:
1120 case SYS_GETSOCKOPT
:
1121 ret
= getoptsock(sock
, (int)arg
[1], (int)arg
[2], (char*)arg
[3], (int*)arg
[4]);
1126 trace("socketcall(): call %d not implemented", call
);
1137 s
->mode
= 0666 | S_IFSOCK
;
1138 s
->uid
= current
->uid
;
1139 s
->gid
= current
->gid
;
1144 fstatsock(Ufile
*, Ustat
*s
)
1150 static Udev sockdev
=
1160 void sockdevinit(void)
1162 devtab
[SOCKDEV
] = &sockdev
;