1 /*
2     OWFS -- One-Wire filesystem
3     OWHTTPD -- One-Wire Web Server
4     Written 2003 Paul H Alfille
5     email: paul.alfille@gmail.com
6     Released under the GPL
7     See the header file: ow.h for full attribution
8     1wire/iButton system from Dallas Semiconductor
9 */
10 
11 /* ow_net holds the network utility routines. Many stolen unashamedly from Steven's Book */
12 /* Much modification by Christian Magnusson especially for Valgrind and embedded */
13 /* non-threaded fixes by Jerry Scharf */
14 
15 #include <config.h>
16 #include "owfs_config.h"
17 #include "ow.h"
18 #include "ow_connection.h"
19 
ClientAddr(char * sname,struct connection_in * in)20 int ClientAddr(char *sname, struct connection_in *in)
21 {
22 	struct addrinfo hint;
23 	char *p;
24 	int ret;
25 
26 	if (sname == NULL || sname[0] == '\0') {
27 		sname = "4304";
28 	}
29 	if ((p = strrchr(sname, ':'))) {	/* : exists */
30 		p[0] = '\0';			/* Separate tokens in the string */
31 		in->tcp.host = strdup(sname);
32 		in->tcp.service = strdup(&p[1]);
33 		p[0] = ':';				/* restore name string */
34 	} else {
35 #if OW_CYGWIN
36 		in->tcp.host = strdup("127.0.0.1");
37 #else
38 		in->tcp.host = NULL;
39 #endif
40 		in->tcp.service = strdup(sname);
41 	}
42 
43 	memset(&hint, 0, sizeof(struct addrinfo));
44 	hint.ai_socktype = SOCK_STREAM;
45 #if OW_CYGWIN
46 	hint.ai_family = AF_INET;
47 #else
48 	hint.ai_family = AF_UNSPEC;
49 #endif
50 
51 //printf("ClientAddr: [%s] [%s]\n", in->connin.tcp.host, in->connin.tcp.service);
52 
53 	if ((ret = getaddrinfo(in->tcp.host, in->tcp.service, &hint, &in->tcp.ai))) {
54 		LEVEL_CONNECT("GetAddrInfo error %s\n", gai_strerror(ret));
55 		return -1;
56 	}
57 	return 0;
58 }
59 
FreeClientAddr(struct connection_in * in)60 void FreeClientAddr(struct connection_in *in)
61 {
62 	if (in->tcp.host) {
63 		free(in->tcp.host);
64 		in->tcp.host = NULL;
65 	}
66 	if (in->tcp.service) {
67 		free(in->tcp.service);
68 		in->tcp.service = NULL;
69 	}
70 	if (in->tcp.ai) {
71 		freeaddrinfo(in->tcp.ai);
72 		in->tcp.ai = NULL;
73 	}
74 }
75 
76 /* Usually called with BUS locked, to protect ai settings */
ClientConnect(struct connection_in * in)77 FILE_DESCRIPTOR_OR_ERROR ClientConnect(struct connection_in *in)
78 {
79 	FILE_DESCRIPTOR_OR_ERROR file_descriptor;
80 	struct addrinfo *ai;
81 
82 	if (in->tcp.ai == NULL) {
83 		LEVEL_DEBUG("Client address not yet parsed\n");
84 		return FILE_DESCRIPTOR_BAD;
85 	}
86 
87 	/* Can't change ai_ok without locking the in-device.
88 	 * First try the last working address info, if it fails lock
89 	 * the in-device and loop through the list until it works.
90 	 * Not a perfect solution, but it should work at least.
91 	 */
92 	ai = in->tcp.ai_ok;
93 	if (ai) {
94 		file_descriptor = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
95 		if (file_descriptor >= 0) {
96 			if (connect(file_descriptor, ai->ai_addr, ai->ai_addrlen) == 0) {
97 				return file_descriptor;
98 			}
99 			close(file_descriptor);
100 		}
101 	}
102 
103 	ai = in->tcp.ai;		// loop from first address info since it failed.
104 	do {
105 		file_descriptor = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
106 		if (file_descriptor >= 0) {
107 			if (connect(file_descriptor, ai->ai_addr, ai->ai_addrlen) == 0) {
108 				in->tcp.ai_ok = ai;
109 				return file_descriptor;
110 			}
111 			close(file_descriptor);
112 		}
113 	} while ((ai = ai->ai_next));
114 	in->tcp.ai_ok = NULL;
115 
116 	ERROR_CONNECT("ClientConnect: Socket problem\n");
117 	return FILE_DESCRIPTOR_BAD;
118 }
119