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