0 | 0 |
/*
|
1 | |
* Copyright (C) 2000-2020, Thomas Maier-Komor
|
|
1 |
* Copyright (C) 2000-2021, Thomas Maier-Komor
|
2 | 2 |
*
|
3 | 3 |
* This file is part of mbuffer's source code.
|
4 | 4 |
*
|
|
24 | 24 |
|
25 | 25 |
|
26 | 26 |
#include <errno.h>
|
|
27 |
#include <netdb.h>
|
|
28 |
#include <net/if.h>
|
27 | 29 |
#include <stdio.h>
|
28 | 30 |
#include <stdlib.h>
|
29 | 31 |
#include <string.h>
|
|
81 | 83 |
|
82 | 84 |
|
83 | 85 |
#ifdef HAVE_GETADDRINFO
|
|
86 |
|
|
87 |
static const char *addrinfo2str(const struct addrinfo *ai, char *buf)
|
|
88 |
{
|
|
89 |
char *at = buf;
|
|
90 |
struct protoent *pent = getprotobynumber(ai->ai_protocol);
|
|
91 |
if (pent && pent->p_name) {
|
|
92 |
size_t l = strlen(pent->p_name);
|
|
93 |
memcpy(at,pent->p_name,l);
|
|
94 |
at[l] = '/';
|
|
95 |
at += l + 1;
|
|
96 |
}
|
|
97 |
if (ai->ai_family == AF_INET) {
|
|
98 |
if (ai->ai_addrlen == sizeof(struct sockaddr_in)) {
|
|
99 |
struct sockaddr_in *a = (struct sockaddr_in *) ai->ai_addr;
|
|
100 |
at += sprintf(at,"%u.%u.%u.%u:%hu"
|
|
101 |
, (a->sin_addr.s_addr >> 24) & 0xff
|
|
102 |
, (a->sin_addr.s_addr >> 16) & 0xff
|
|
103 |
, (a->sin_addr.s_addr >> 8) & 0xff
|
|
104 |
, (a->sin_addr.s_addr) & 0xff
|
|
105 |
, ntohs(a->sin_port));
|
|
106 |
} else {
|
|
107 |
strcpy(at,"<ipv4 with unexpected addrlen>");
|
|
108 |
}
|
|
109 |
} else if (ai->ai_family == AF_INET6) {
|
|
110 |
if (ai->ai_addrlen == sizeof(struct sockaddr_in6)) {
|
|
111 |
struct sockaddr_in6 *a = (struct sockaddr_in6 *) ai->ai_addr;
|
|
112 |
char scope[IF_NAMESIZE+1];
|
|
113 |
if (0 == if_indextoname(a->sin6_scope_id,scope+1))
|
|
114 |
scope[0] = 0;
|
|
115 |
else
|
|
116 |
scope[0] = '%';
|
|
117 |
at += sprintf(at,"[%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx]%s:%hu"
|
|
118 |
, ntohs(a->sin6_addr.s6_addr[0])
|
|
119 |
, ntohs(a->sin6_addr.s6_addr[1])
|
|
120 |
, ntohs(a->sin6_addr.s6_addr[2])
|
|
121 |
, ntohs(a->sin6_addr.s6_addr[3])
|
|
122 |
, ntohs(a->sin6_addr.s6_addr[4])
|
|
123 |
, ntohs(a->sin6_addr.s6_addr[5])
|
|
124 |
, ntohs(a->sin6_addr.s6_addr[6])
|
|
125 |
, ntohs(a->sin6_addr.s6_addr[7])
|
|
126 |
, scope
|
|
127 |
, ntohs(a->sin6_port));
|
|
128 |
} else {
|
|
129 |
strcpy(at,"<ipv4 with unexpected addrlen>");
|
|
130 |
}
|
|
131 |
} else {
|
|
132 |
strcpy(buf,"<unknown address family>");
|
|
133 |
}
|
|
134 |
return buf;
|
|
135 |
}
|
|
136 |
|
84 | 137 |
|
85 | 138 |
void initNetworkInput(const char *addr)
|
86 | 139 |
{
|
|
104 | 157 |
port = host + 1;
|
105 | 158 |
host = 0;
|
106 | 159 |
} else {
|
|
160 |
if ((host[0] == '[') && (port[-1] == ']')) {
|
|
161 |
++host;
|
|
162 |
port[-1] = 0;
|
|
163 |
}
|
107 | 164 |
*port = 0;
|
108 | 165 |
++port;
|
109 | 166 |
bzero(&hint,sizeof(hint));
|
110 | 167 |
hint.ai_family = AddrFam;
|
111 | 168 |
hint.ai_protocol = IPPROTO_TCP;
|
112 | 169 |
hint.ai_socktype = SOCK_STREAM;
|
113 | |
#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
|
|
170 |
#ifdef AI_V4MAPPED
|
|
171 |
hint.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
|
|
172 |
#else
|
114 | 173 |
hint.ai_flags = AI_ADDRCONFIG;
|
115 | |
#else
|
116 | |
hint.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
|
117 | 174 |
#endif
|
118 | 175 |
err = getaddrinfo(host,0,&hint,&cinfo);
|
119 | 176 |
if (err != 0)
|
|
133 | 190 |
debugmsg("creating socket for address familiy %d\n",x->ai_family);
|
134 | 191 |
sock = socket(x->ai_family, SOCK_STREAM, 0);
|
135 | 192 |
if (sock == -1) {
|
136 | |
warningmsg("unable to create socket for input: %s\n",strerror(errno));
|
|
193 |
warningmsg("unable to create socket for address family %u: %s\n",x->ai_family,strerror(errno));
|
137 | 194 |
continue;
|
138 | 195 |
}
|
139 | 196 |
if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)))
|
|
142 | 199 |
debugmsg("successfully bound socket - address length %d\n",x->ai_addrlen);
|
143 | 200 |
break;
|
144 | 201 |
}
|
145 | |
warningmsg("could not bind to socket for network input: %s\n",strerror(errno));
|
|
202 |
char addrstr[64+IF_NAMESIZE];
|
|
203 |
warningmsg("could not bind to socket for %s: %s\n",addrinfo2str(x,addrstr),strerror(errno));
|
146 | 204 |
(void) close(sock);
|
147 | 205 |
}
|
148 | 206 |
if (x == 0)
|
|
210 | 268 |
port = strrchr(host,':');
|
211 | 269 |
if (port == 0)
|
212 | 270 |
fatal("syntax error - target must be given in the form <host>:<port>\n");
|
|
271 |
if ((host[0] == '[') && (port > host) && (port[-1] == ']')) {
|
|
272 |
++host;
|
|
273 |
port[-1] = 0;
|
|
274 |
}
|
213 | 275 |
*port++ = 0;
|
214 | 276 |
bzero(&hint,sizeof(hint));
|
215 | 277 |
hint.ai_family = AddrFam;
|
|
226 | 288 |
errormsg("unable to create socket: %s\n",strerror(errno));
|
227 | 289 |
continue;
|
228 | 290 |
}
|
|
291 |
char addrstr[64+IF_NAMESIZE];
|
229 | 292 |
if (0 == connect(fd, x->ai_addr, x->ai_addrlen)) {
|
230 | 293 |
struct sockaddr_in local_address;
|
231 | 294 |
socklen_t addr_size = sizeof(local_address);
|
|
233 | 296 |
infomsg("successfully connected to %s from :%d\n",addr,ntohs((&local_address)->sin_port));
|
234 | 297 |
break;
|
235 | 298 |
}
|
|
299 |
warningmsg("error connecting to %s: %s\n",addrinfo2str(x,addrstr),strerror(errno));
|
236 | 300 |
(void) close(fd);
|
237 | 301 |
fd = -1;
|
238 | |
warningmsg("error connecting to %s: %s\n",addr,strerror(errno));
|
239 | 302 |
}
|
240 | 303 |
if (fd == -1) {
|
241 | 304 |
errormsg("unable to connect to %s\n",addr);
|