1 /* net.c --
2 * Created: Fri Feb 21 20:58:10 1997 by faith@dict.org
3 * Copyright 1997, 1998, 1999, 2000, 2002 Rickard E. Faith (faith@dict.org)
4 * Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 1, or (at your option) any
9 * later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "dictP.h"
22
23 #include <sys/ioctl.h>
24 #include <sys/stat.h>
25 #include <sys/socket.h>
26 #include <sys/param.h>
27 #include <fcntl.h>
28
29 #include "dictd.h"
30
31 #ifndef MAXHOSTNAMELEN
32 #define MAXHOSTNAMELEN 64
33 #endif
34
35 #ifndef INADDR_NONE
36 #define INADDR_NONE (-1)
37 #endif
38
inet_ntopW(struct sockaddr * sa)39 const char *inet_ntopW (struct sockaddr *sa) {
40 static char buf[40];
41
42 switch (sa->sa_family) {
43 case AF_INET:
44 return inet_ntop (sa->sa_family, &(((struct sockaddr_in *)sa)->sin_addr), buf, sizeof(buf));
45 case AF_INET6:
46 return inet_ntop (sa->sa_family, &(((struct sockaddr_in6 *)sa)->sin6_addr), buf, sizeof(buf));
47 default:
48 errno = EAFNOSUPPORT;
49 return NULL;
50 }
51 }
52
net_hostname(void)53 const char *net_hostname( void )
54 {
55 static char hostname[128] = "";
56 int err;
57
58 if (!hostname[0]) {
59 if (err = gethostname(hostname, sizeof(hostname)), err != 0) {
60 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
61 exit(EXIT_FAILURE);
62 }
63 }
64
65 hostname[sizeof(hostname)-1] = '\0';
66 return hostname;
67 }
68
net_connect_tcp(const char * host,const char * service,int address_family)69 int net_connect_tcp( const char *host, const char *service, int address_family )
70 {
71 struct addrinfo *r = NULL;
72 struct addrinfo *rtmp = NULL;
73 struct addrinfo hints;
74 int s;
75
76 memset (&hints, 0, sizeof (struct addrinfo));
77 hints.ai_family = address_family;
78 hints.ai_protocol = IPPROTO_TCP;
79 hints.ai_socktype = SOCK_STREAM;
80 hints.ai_flags = AI_ADDRCONFIG;
81
82 if (getaddrinfo (host, service, &hints, &r) != 0) {
83 return NET_NOHOST;
84 }
85
86 for (rtmp = r; r != NULL; r = r->ai_next) {
87 s = socket (r->ai_family, r->ai_socktype, r->ai_protocol);
88 if (s < 0) {
89 if (r->ai_next != NULL)
90 continue;
91
92 err_fatal_errno( __FUNCTION__, "Can't open socket\n");
93 }
94
95 PRINTF(DBG_VERBOSE,("Trying %s (%s)...", host, inet_ntopW(r->ai_addr)));
96
97 if (connect (s, r->ai_addr, r->ai_addrlen) >= 0) {
98 PRINTF(DBG_VERBOSE,("Connected."));
99 freeaddrinfo (rtmp);
100 return s;
101 }
102
103 PRINTF(DBG_VERBOSE,("Failed: %s\n", strerror (errno)));
104
105 close (s);
106 }
107 freeaddrinfo (rtmp);
108
109 return NET_NOCONNECT;
110 }
111
net_open_tcp(const char * address,const char * service,int queueLength,int address_family)112 int net_open_tcp (
113 const char *address,
114 const char *service,
115 int queueLength,
116 int address_family)
117 {
118 struct addrinfo hints, *r, *rtmp;
119 int s = -1;
120 int err;
121
122 memset (&hints, 0, sizeof (struct addrinfo));
123 hints.ai_family = address_family;
124 hints.ai_protocol = IPPROTO_TCP;
125 hints.ai_socktype = SOCK_STREAM;
126 hints.ai_flags = AI_PASSIVE;
127
128 if (getaddrinfo (address, service, &hints, &r) != 0)
129 err_fatal ( __FUNCTION__, "getaddrinfo: Failed, address = \"%s\", service = \"%s\"\n", address, service);
130
131 for (rtmp = r; r != NULL; r = r->ai_next) {
132 s = socket (r->ai_family, r->ai_socktype, r->ai_protocol);
133
134 if (s < 0) {
135 if (r->ai_next != NULL)
136 continue;
137
138 freeaddrinfo (rtmp);
139 err_fatal_errno (__FUNCTION__, "Can't open socket\n");
140 }
141
142 {
143 const int one = 1;
144 err = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
145 if (err != 0){
146 err_fatal_errno (__FUNCTION__, "Can't setsockopt\n");
147 }
148 }
149
150 if (bind(s, r->ai_addr, r->ai_addrlen) < 0) {
151 if (r->ai_next != NULL) {
152 close (s);
153 continue;
154 }
155 freeaddrinfo (rtmp);
156 err_fatal_errno( __FUNCTION__, "Can't bind %s/tcp to %s\n",
157 service, address?address:"ANY" );
158 }
159
160 if (listen( s, queueLength ) < 0) {
161 if (r->ai_next != NULL) {
162 close (s);
163 continue;
164 }
165 freeaddrinfo (rtmp);
166 err_fatal_errno( __FUNCTION__, "Can't listen to %s/tcp on %s\n",
167 service, address );
168 }
169
170 break;
171 }
172 freeaddrinfo (rtmp);
173
174 return s;
175 }
176
net_read(int s,char * buf,int maxlen)177 int net_read( int s, char *buf, int maxlen )
178 {
179 int len;
180 int n = 0;
181 char c;
182 char *pt = buf;
183
184 *pt = '\0';
185
186 for (len = 0; len < maxlen && (n = read( s, &c, 1 )) > 0; /*void*/) {
187 switch (c) {
188 case '\n': *pt = '\0'; return len;
189 case '\r': break;
190 default: *pt++ = c; ++len; break;
191 }
192 }
193 *pt = '\0';
194 if (!n) return len ? len : EOF;
195 return n; /* error code */
196 }
197
net_write(int s,const char * buf,int len)198 int net_write( int s, const char *buf, int len )
199 {
200 int left = len;
201 int count;
202
203 while (left) {
204 if ((count = write(s, buf, left)) != left) {
205 if (count <= 0) return count; /* error code */
206 }
207 left -= count;
208 }
209 return len;
210 }
211