1 /* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
2 * Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com>
3 * See LICENSE file for license details.
7 #include <netinet/in.h>
13 #include <sys/socket.h>
16 #include "mixp_local.h"
17 #include <9p-mixp/srv_addr.h>
18 #include <9p-mixp/err.h>
20 /* Note: These functions modify the strings that they are passed.
21 * The lookup function duplicates the original string, so it is
25 typedef struct sockaddr sockaddr
;
26 typedef struct sockaddr_un sockaddr_un
;
27 typedef struct sockaddr_in sockaddr_in
;
30 get_port(const char *addr
) {
34 s
= strchr(addr
, '!');
36 mixp_werrstr("no port provided");
41 port
= strtol(s
, &end
, 10);
42 if(*s
== '\0' && *end
!= '\0') {
43 mixp_werrstr("invalid port number");
50 sock_unix(const char *address
, sockaddr_un
*sa
, socklen_t
*salen
) {
53 memset(sa
, 0, sizeof(sa
));
55 sa
->sun_family
= AF_UNIX
;
56 strncpy(sa
->sun_path
, address
, sizeof(sa
->sun_path
));
59 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
66 sock_tcp_2(const char *host
, int port
, sockaddr_in
*sa
) {
73 signal(SIGPIPE
, SIG_IGN
);
74 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
78 memset(sa
, 0, sizeof(sa
));
79 sa
->sin_family
= AF_INET
;
80 sa
->sin_port
= htons(port
);
82 if(strcmp(host
, "*") == 0)
83 sa
->sin_addr
.s_addr
= htonl(INADDR_ANY
);
84 else if((he
= gethostbyname(host
)))
85 memcpy(&sa
->sin_addr
, he
->h_addr
, he
->h_length
);
92 dial_unix(const char *address
) {
97 fd
= sock_unix(address
, &sa
, &salen
);
101 if(connect(fd
, (sockaddr
*) &sa
, salen
)) {
109 announce_unix(const char *file
) {
115 signal(SIGPIPE
, SIG_IGN
);
117 fd
= sock_unix(file
, &sa
, &salen
);
121 if(setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&yes
, sizeof(yes
)) < 0)
125 if(bind(fd
, (sockaddr
*)&sa
, salen
) < 0)
128 chmod(file
, S_IRWXU
);
129 if(listen(fd
, IXP_MAX_CACHE
) < 0)
139 static int dial_tcp_2(const char *host
, int port
)
144 fd
= sock_tcp_2(host
, port
, &sa
);
148 if(connect(fd
, (sockaddr
*)&sa
, sizeof(sa
))) {
156 static int dial_tcp(const char *host
)
158 int port
= get_port(host
);
159 return dial_tcp_2(host
,port
);
163 announce_tcp(const char *host
) {
168 port
= get_port(host
);
170 fd
= sock_tcp_2(host
, port
, &sa
);
174 if(bind(fd
, (sockaddr
*)&sa
, sizeof(sa
)) < 0)
177 if(listen(fd
, IXP_MAX_CACHE
) < 0)
187 typedef struct addrtab addrtab
;
190 int (*fn
)(const char*);
196 {"tcp", announce_tcp
},
197 {"unix", announce_unix
},
202 lookup(const char *address
, addrtab
*tab
) {
207 type
= strdup(address
);
209 addr
= strchr(type
, '!');
211 mixp_werrstr("no address type defined");
214 for(; tab
->type
; tab
++)
215 if(strcmp(tab
->type
, type
) == 0) break;
216 if(tab
->type
== NULL
)
217 mixp_werrstr("unsupported address type");
226 int mixp_dial_addr(MIXP_SERVER_ADDRESS
*addr
)
231 return dial_tcp_2(addr
->hostname
, addr
->port
);
233 return dial_unix(addr
->path
);
235 return dial_tcp_2(addr
->hostname
, addr
->port
);
239 int mixp_dial(const char *address
)
242 MIXP_SERVER_ADDRESS
* addr
= mixp_srv_addr_parse(address
);
245 ret
= mixp_dial_addr(addr
);
246 mixp_srv_addr_free(addr
);
250 int mixp_announce(const char *address
)
252 return lookup(address
, atab
);