lessfs  1.7.0
About: Lessfs is a inline data deduplicating file system for Linux (implemented in user space with FUSE; especially useful for backup purposes).
  Fossies Dox: lessfs-1.7.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

lib_net.c
Go to the documentation of this file.
1 /*
2  * Lessfs: A data deduplicating filesystem.
3  * Copyright (C) 2008 Mark Ruijter <mruijter@lessfs.com>
4  *
5  * This program is free software.
6  * You can redistribute lessfs and/or modify it under the terms of either
7  * (1) the GNU General Public License; either version 3 of the License,
8  * or (at your option) any later version as published by
9  * the Free Software Foundation; or (2) obtain a commercial license
10  * by contacting the Author.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15  * the GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netdb.h>
31 #include <arpa/inet.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <malloc.h>
36 #include <errno.h>
37 #include "lib_log.h"
38 #include "lib_safe.h"
39 #include "lib_net.h"
40 #include "retcodes.h"
41 
42 extern pid_t mypid;
43 extern char *logname;
44 extern char *function;
45 
46 void die_nomem()
47 {
48  LFATAL("Out of memory\n");
49  exit(EXIT_SYSTEM);
50 }
51 
53 {
54  LFATAL("writeLine failed in writeHeader.\n");
55  exit(EXIT_SYSTEM);
56 }
57 
58 /* Reads a string with an arbitrary ending delimiter. */
59 
60 int readdelimstring(int sec, int sockid, char *buf, int maxlen, char delim)
61 {
62  int count = 0, status;
63 
64  while (count <= maxlen) {
65  status =
66  fulltimRead(sec, sockid, (unsigned char *) buf + count, 1);
67  if (status < 0)
68  return status;
69  if (status < 1) {
70  return status;
71  }
72  if (buf[count] == delim) { /* Found the delimiter */
73  buf[count] = 0;
74  return 0;
75  }
76  count++;
77  }
78  return 0;
79 }
80 
81 /* Reads a string from the network, terminated by a null. */
82 
83 int readstring(int sec, int sockid, char *buf, int maxlen)
84 {
85  return readdelimstring(sec, sockid, buf, maxlen, 0);
86 }
87 
88 /* Reads a string terminated by a newline */
89 
90 int readnlstring(int sec, int sockid, char *buf, int maxlen)
91 {
92  return readdelimstring(sec, sockid, buf, maxlen, '\n');
93 }
94 
95 int timeoutRead(int t, int fd, char *b, int l)
96 {
97  int rc = TIMEOUT;
98  fd_set fds;
99  struct timeval tv;
100 
101  FD_ZERO(&fds);
102  FD_SET(fd, &fds);
103  tv.tv_sec = t;
104  tv.tv_usec = 0;
105 
106  if (select(fd + 1, &fds, NULL, NULL, &tv)) {
107  again:
108  if ((rc = read(fd, b, l)) < 0) {
109  if (errno == EINTR || EAGAIN == errno)
110  goto again;
111  }
112  }
113  return (rc);
114 }
115 
116 int timeoutWrite(int t, int fd, char *b, int l)
117 {
118  int rc = TIMEOUT;
119  fd_set fds;
120  struct timeval tv;
121 
122  if (fd < 0)
123  return (fd);
124 
125  FD_ZERO(&fds);
126  FD_SET(fd, &fds);
127  tv.tv_sec = t;
128  tv.tv_usec = 0;
129 
130  if (select(fd + 1, NULL, &fds, NULL, &tv)) {
131  again:
132  if ((rc = write(fd, b, l)) < 0) {
133  if (errno == EINTR || EAGAIN == errno)
134  goto again;
135  }
136  }
137  return (rc);
138 }
139 
140 char *readMsg(int fd)
141 {
142  int bufcount = BUFSIZE;
143  int bytes = 0;
144  int rc = -1;
145  static char *mg_msg, *mg_msg2;
146 
147  mg_msg = s_malloc(bufcount);
148  mg_msg2 = mg_msg;
149  while (1) {
150  rc = timeoutRead(30, fd, mg_msg2, 1);
151  if (rc < 0)
152  return NULL;
153  if (rc == 0)
154  break;
155  bytes = bytes + rc;
156  bufcount = bufcount + rc;
157  if (NULL == (mg_msg = realloc(mg_msg, bufcount)))
158  die_nomem();
159  mg_msg2 = mg_msg + bytes;
160  }
161  mg_msg[bytes] = 0;
162  return mg_msg;
163 }
164 
165 int resolveproto(const char *proto)
166 {
167  struct protoent *protocol;
168  protocol = getprotobyname(proto);
169  if (!protocol) {
170  LFATAL("resolveproto : getprotobyname failed for %s", proto);
171  return -1;
172  }
173 
174  return protocol->p_proto;
175 }
176 
177 static int checkstring(const char *string);
178 
179 /* checkstring() is a private function used only by this library. It checks
180  the passed string. It returns false if there are no nonnumeric
181  characters in the string, or true if there are such characters. */
182 
183 static int checkstring(const char *string)
184 {
185  int counter;
186  for (counter = 0; counter < strlen(string); counter++)
187  if (!(isdigit(string[counter])))
188  return 1;
189  return 0;
190 }
191 
192 int prototype(const char *proto)
193 {
194  if (strcmp(proto, "tcp") == 0)
195  return SOCK_STREAM;
196  if (strcmp(proto, "udp") == 0)
197  return SOCK_DGRAM;
198  return -1;
199 }
200 
201 int socketaddr_host(struct sockaddr_in *socketaddr, const char *host)
202 {
203  struct hostent *hostaddr;
204  hostaddr = gethostbyname(host);
205  if (!hostaddr) {
206  LFATAL("socketaddr_host: gethostbyname failed for %s", host);
207  return -1;
208  }
209 
210  memcpy(&socketaddr->sin_addr, hostaddr->h_addr, hostaddr->h_length);
211  return 0;
212 }
213 
214 int
215 socketaddr_service(struct sockaddr_in *socketaddr,
216  const char *service, const char *proto)
217 {
218  struct servent *serviceaddr;
219 
220  /* Need to allow numeric as well as textual data. */
221 
222  /* 0: pass right through. */
223 
224  if (strcmp(service, "0") == 0)
225  socketaddr->sin_port = 0;
226  else { /* nonzero port */
227  serviceaddr = getservbyname(service, proto);
228  if (serviceaddr) {
229  socketaddr->sin_port = serviceaddr->s_port;
230  } else { /* name did not resolve, try number */
231  if (checkstring(service)) { /* and it's a text name, fail. */
232  LFATAL("socketaddr_service no lookup for %s/%s", service,
233  proto);
234  return -1;
235  }
236  if ((socketaddr->sin_port =
237  htons((u_short) atoi(service))) == 0) {
238  LFATAL("socketaddr_service : numeric conversion failed");
239  return -1;
240  }
241  }
242  }
243  return 0;
244 }
245 
246 
247 void socketaddr_init(struct sockaddr_in *socketaddr)
248 {
249  bzero((char *) socketaddr, sizeof(*socketaddr));
250  socketaddr->sin_family = AF_INET;
251 }
252 
253 int clientconnect(const char *host, const char *port, const char *proto)
254 {
255  struct sockaddr_in socketaddr;
256  int sockid;
257  int trueval = 1;
258 
259  socketaddr_init(&socketaddr);
260  socketaddr_service(&socketaddr, port, proto);
261  socketaddr_host(&socketaddr, host);
262 
263  sockid = socket(PF_INET, prototype(proto), resolveproto(proto));
264  if (sockid < 0) {
265  return -1;
266  }
267 
268  setsockopt(sockid, SOL_SOCKET, SO_REUSEADDR, &trueval,
269  sizeof(trueval));
270  if (connect
271  (sockid, (struct sockaddr *) &socketaddr,
272  sizeof(socketaddr)) < 0) {
273  return -1;
274  }
275  return sockid;
276 }
277 
278 int scanaddr(const char *s, unsigned long *ip, unsigned long *mask)
279 {
280  unsigned d1, d2, d3, d4, m;
281  int res;
282  if ((res =
283  sscanf((char *) s, "%u.%u.%u.%u/%u", &d1, &d2, &d3, &d4, &m)) < 4)
284  return 0;
285  if (mask && res == 4)
286  *mask = 0xFFFFFFFF;
287  else if (mask)
288  *mask = htonl(0xFFFFFFFF << (32 - m));
289  *ip = htonl((d1 << 24) ^ (d2 << 16) ^ (d3 << 8) ^ d4);
290  return res;
291 }
292 
293 int serverinit(const char *addr, const char *port, const char *proto)
294 {
295  struct sockaddr_in socketaddr;
296  int mastersock;
297  int trueval = 1;
298  struct hostent *hostinfo;
299  unsigned long ip;
300  struct linger slinger;
301 
302  socketaddr_init(&socketaddr);
303 
304  if (NULL == addr) {
305  socketaddr.sin_addr.s_addr = INADDR_ANY;
306  } else {
307  if (scanaddr(addr, &ip, NULL) != 4) {
308  LFATAL("Invalid address : %s provided", addr);
309  return -1;
310  }
311  hostinfo = gethostbyaddr((char *) &ip, 4, AF_INET);
312  if (NULL == hostinfo) {
313  LFATAL("gethostbyaddr : %s failed", addr);
314  return -1;
315  }
316  socketaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
317  }
318  socketaddr_service(&socketaddr, port, proto);
319 
320  mastersock = socket(PF_INET, prototype(proto), resolveproto(proto));
321  if (mastersock < 0) {
322  LFATAL("couldn't create socket");
323  return -1;
324  }
325 
326  if (bind
327  (mastersock, (struct sockaddr *) &socketaddr,
328  sizeof(socketaddr)) < 0) {
329  return -1;
330  }
331 
332  setsockopt(mastersock, SOL_SOCKET, SO_REUSEADDR, &trueval,
333  sizeof(trueval));
334  slinger.l_onoff = 1;
335  slinger.l_linger = 0;
336  setsockopt(mastersock, SOL_SOCKET, SO_LINGER, (char *) &slinger,
337  sizeof(slinger));
338 
339  if (prototype(proto) == SOCK_STREAM) {
340  if (listen(mastersock, 5) < 0) {
341  LFATAL("listen on port %d failed", socketaddr.sin_port);
342  return -1;
343  }
344  }
345  return mastersock;
346 }
347 
348 int fulltimRead(int sec, int fd, unsigned char *buf, int len)
349 {
350  int total;
351  int thistime;
352 
353  for (total = 0; total < len;) {
354  thistime = timeoutRead(sec, fd, (char *) buf + total, len - total);
355  if (thistime == TIMEOUT)
356  return (thistime);
357  if (thistime < 0) {
358  if (EINTR == errno || EAGAIN == errno)
359  continue;
360  return -1;
361  } else if (thistime == 0) {
362  /* EOF, but we didn't read the minimum. return what we've read
363  * so far and next read (if there is one) will return 0. */
364  return total;
365  }
366  total += thistime;
367  }
368  return total;
369 }
370 
371 int fulltimWrite(int sec, int fd, unsigned char *buf, int len)
372 {
373  int total;
374  int thistime;
375 
376  for (total = 0; total < len;) {
377  thistime =
378  timeoutWrite(sec, fd, (char *) buf + total, len - total);
379  if (thistime == TIMEOUT)
380  return (thistime);
381  if (thistime < 0) {
382  if (EINTR == errno || EAGAIN == errno)
383  continue;
384  return -1;
385  } else if (thistime == 0) {
386  /* EOF, but we didn't read the minimum. return what we've read
387  * so far and next read (if there is one) will return 0. */
388  return total;
389  }
390  total += thistime;
391  }
392  return total;
393 }
394 
395 
396 
397 int fullRead(int fd, unsigned char *buf, int len)
398 {
399  int total;
400  int thistime;
401 
402  for (total = 0; total < len;) {
403  thistime = read(fd, buf + total, len - total);
404 
405  if (thistime < 0) {
406  if (EINTR == errno || EAGAIN == errno)
407  continue;
408  return -1;
409  } else if (thistime == 0) {
410  /* EOF, but we didn't read the minimum. return what we've read
411  * so far and next read (if there is one) will return 0. */
412  return total;
413  }
414  total += thistime;
415  }
416  return total;
417 }
418 
419 int fullWrite(int fd, unsigned char *buf, int len)
420 {
421  int total;
422  int thistime;
423 
424  for (total = 0; total < len;) {
425  thistime = write(fd, buf + total, len - total);
426 
427  if (thistime < 0) {
428  if (EINTR == errno || EAGAIN == errno)
429  continue;
430  return thistime; /* always an error for writes */
431  }
432  total += thistime;
433  }
434  return total;
435 }
timeoutRead
int timeoutRead(int t, int fd, char *b, int l)
Definition: lib_net.c:95
lib_safe.h
TIMEOUT
#define TIMEOUT
Definition: lib_net.h:21
timeoutWrite
int timeoutWrite(int t, int fd, char *b, int l)
Definition: lib_net.c:116
socketaddr_init
void socketaddr_init(struct sockaddr_in *socketaddr)
Definition: lib_net.c:247
readdelimstring
int readdelimstring(int sec, int sockid, char *buf, int maxlen, char delim)
Definition: lib_net.c:60
readstring
int readstring(int sec, int sockid, char *buf, int maxlen)
Definition: lib_net.c:83
prototype
int prototype(const char *proto)
Definition: lib_net.c:192
lib_log.h
resolveproto
int resolveproto(const char *proto)
Definition: lib_net.c:165
fullWrite
int fullWrite(int fd, unsigned char *buf, int len)
Definition: lib_net.c:419
serverinit
int serverinit(const char *addr, const char *port, const char *proto)
Definition: lib_net.c:293
socketaddr_host
int socketaddr_host(struct sockaddr_in *socketaddr, const char *host)
Definition: lib_net.c:201
logname
char * logname
Definition: commons.h:5
die_nomem
void die_nomem()
Definition: lib_net.c:46
checkstring
static int checkstring(const char *string)
Definition: lib_net.c:183
BUFSIZE
#define BUFSIZE
Definition: lib_log.h:39
LFATAL
#define LFATAL(f...)
Definition: lib_log.h:68
lib_net.h
fulltimWrite
int fulltimWrite(int sec, int fd, unsigned char *buf, int len)
Definition: lib_net.c:371
socketaddr_service
int socketaddr_service(struct sockaddr_in *socketaddr, const char *service, const char *proto)
Definition: lib_net.c:215
EXIT_SYSTEM
#define EXIT_SYSTEM
Definition: retcodes.h:22
s_malloc
#define s_malloc(size)
Definition: lib_safe.h:23
readnlstring
int readnlstring(int sec, int sockid, char *buf, int maxlen)
Definition: lib_net.c:90
clientconnect
int clientconnect(const char *host, const char *port, const char *proto)
Definition: lib_net.c:253
fulltimRead
int fulltimRead(int sec, int fd, unsigned char *buf, int len)
Definition: lib_net.c:348
retcodes.h
scanaddr
int scanaddr(const char *s, unsigned long *ip, unsigned long *mask)
Definition: lib_net.c:278
exitWriteLine
void exitWriteLine()
Definition: lib_net.c:52
mypid
pid_t mypid
fullRead
int fullRead(int fd, unsigned char *buf, int len)
Definition: lib_net.c:397
readMsg
char * readMsg(int fd)
Definition: lib_net.c:140