minor libspclient fix. in cases where spc_netmount failed, the same
[spfs.git] / libspclient / netmount.c
bloba6b2d02d2e7c06aaded2a8342bba4fea8adc0bca
1 /*
2 * Copyright (C) 2006 by Latchesar Ionkov <lucho@ionkov.net>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * LATCHESAR IONKOV AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netdb.h>
31 #include "spfs.h"
32 #include "spclient.h"
33 #include "spcimpl.h"
35 /* this should be at least 3 functions. parse an address into
36 * sockaddr. make a socket. Mount a given sockaddr. This needs
37 * rewriting.
38 * oh, hell, let's just do it.
41 /* parse an address in plan 9 format into a sockaddr
42 * NOT a sockaddr_in yet if ever.
43 * if you want defaults, then put them in the string!
45 struct sockaddr *parse9net(const char *address, struct sockaddr *psaddr)
47 int port;
48 char *addr, *name, *p, *s;
49 struct sockaddr_in *saddr = (struct sockaddr_in *)psaddr;
50 struct hostent *hostinfo;
52 addr = strdup(address);
53 if (strncmp(addr, "tcp!", 4) == 0)
54 name = addr + 4;
55 else
56 name = addr;
58 port = 0;
59 p = strrchr(name, '!');
60 if (p) {
61 *p = '\0';
62 p++;
63 port = strtoul(p, &s, 0);
64 if (*s != '\0') {
65 sp_werror("invalid port format", EIO);
66 goto error;
70 hostinfo = gethostbyname(name);
71 if (!hostinfo) {
72 sp_werror("cannot resolve name: %s", EIO, name);
73 goto error;
76 free(addr);
78 saddr->sin_family = AF_INET;
79 saddr->sin_port = htons(port);
80 saddr->sin_addr = *(struct in_addr *) hostinfo->h_addr;
82 return (struct sockaddr *) saddr;
84 error:
85 return NULL;
88 Spcfsys *
89 spc_netmount(char *address, Spuser *user, int dfltport,
90 int (*auth)(Spcfid *afid, Spuser *user, void *aux), void *aux)
92 int fd, port;
93 socklen_t n;
94 char *addr, *name, *p, *s;
95 struct sockaddr_in saddr;
96 struct hostent *hostinfo;
97 unsigned char a[4];
98 char buf[64];
99 Spcfsys *fs;
101 addr = strdup(address);
102 if (strncmp(addr, "tcp!", 4) == 0)
103 name = addr + 4;
104 else
105 name = addr;
107 port = dfltport;
108 p = strrchr(name, '!');
109 if (p) {
110 *p = '\0';
111 p++;
112 port = strtol(p, &s, 10);
113 if (*s != '\0') {
114 sp_werror("invalid port format", EIO);
115 goto error;
119 fd = socket(PF_INET, SOCK_STREAM, 0);
120 if (fd < 0) {
121 sp_uerror(errno);
122 goto error;
125 hostinfo = gethostbyname(name);
126 if (!hostinfo) {
127 sp_werror("cannot resolve name: %s", EIO, name);
128 goto error;
131 saddr.sin_family = AF_INET;
132 saddr.sin_port = htons(port);
133 saddr.sin_addr = *(struct in_addr *) hostinfo->h_addr;
135 if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
136 /* real computers have errstr */
137 static char error[128];
138 /* too bad for f-ing gcc and friends */
139 a[0] = saddr.sin_addr.s_addr >> 24;
140 a[1] = saddr.sin_addr.s_addr >>16;
141 a[2] = saddr.sin_addr.s_addr >>8;
142 a[3] = saddr.sin_addr.s_addr;
143 /* yeah, they broke this too
144 char *i = inet_ntoa(saddr.sin_addr);
147 memset(error, 0, sizeof(error));
148 //strerror_r(errno, error, sizeof(error));
149 strcpy(error, strerror(errno));
150 error[strlen(error)] = ':';
151 sprintf(&error[strlen(error)], "%d.%d.%d.%d", a[3], a[2], a[1], a[0]);
152 // sp_werror("Host :%s:%s", errno, i, error);
153 sp_werror(error, errno);
154 goto error;
157 free(addr);
158 addr = NULL;
159 fs = spc_mount(fd, NULL, user, auth, aux);
160 if (!fs)
161 goto error;
163 n = sizeof(saddr);
164 if (getsockname(fd, (struct sockaddr *) &saddr, &n) >= 0) {
165 a[0] = saddr.sin_addr.s_addr >> 24;
166 a[1] = saddr.sin_addr.s_addr >> 16;
167 a[2] = saddr.sin_addr.s_addr >> 8;
168 a[3] = saddr.sin_addr.s_addr;
169 snprintf(buf, sizeof(buf), "%d.%d.%d.%d", a[3], a[2], a[1], a[0]);
170 fs->laddr = strdup(buf);
173 n = sizeof(saddr);
174 if (getpeername(fd, (struct sockaddr *) &saddr, &n) >= 0) {
175 a[0] = saddr.sin_addr.s_addr >> 24;
176 a[1] = saddr.sin_addr.s_addr >> 16;
177 a[2] = saddr.sin_addr.s_addr >> 8;
178 a[3] = saddr.sin_addr.s_addr;
179 snprintf(buf, sizeof(buf), "%d.%d.%d.%d", a[3], a[2], a[1], a[0]);
180 fs->raddr = strdup(buf);
183 if (spc_chatty)
184 fprintf(stderr, "connection %p to %s opened\n", fs, fs->raddr);
186 return fs;
188 error:
189 free(addr);
190 return NULL;