ucspi-tcp6 1.13.02
ucspi-tcp6
Loading...
Searching...
No Matches
tcpclient.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/param.h>
3#include <netdb.h>
4#include <netinet/in.h>
5#include "sig.h"
6#include "exit.h"
7#include "getoptb.h"
8#include "uint_t.h"
9#include "fmt.h"
10#include "scan.h"
11#include "str.h"
12#include "ip.h"
13#include "socket_if.h"
14#include "fd.h"
15#include "stralloc.h"
16#include "buffer.h"
17#include "error.h"
18#include "logmsg.h"
19#include "pathexec.h"
20#include "timeout.h"
21#include "timeoutconn.h"
22#include "dnsresolv.h"
23#include "byte.h"
24#include "remoteinfo.h"
25
26#define WHO "tcpclient"
27
28void nomem(void)
29{
30 logmsg(WHO,111,FATAL,"out of memory");
31}
32void usage(void)
33{
34 logmsg(WHO,100,USAGE,"tcpclient \
35[ -46hHrRdDqQv ] \
36[ -i iplocal ] \
37[ -p portlocal ] \
38[ -T timeoutconn ] \
39[ -l localname ] \
40[ -t timeoutinfo ] \
41[ -I interface ] \
42host port program");
43}
44
45int verbosity = 1;
46int flagdelay = 1;
49unsigned long itimeout = 26;
50unsigned long ctimeout[2] = {2, 58};
51uint32 netif = 0;
52
53char iplocal[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
54uint16 portlocal = 0;
55char *forcelocal = 0;
56
57char ipremote[16];
59
60const char *hostname;
61const char *loopback = "127.0.0.1";
62static stralloc addresses;
63static stralloc moreaddresses;
64
65static stralloc tmp;
66static stralloc fqdn;
67static char strnum[FMT_ULONG];
68static char ipstr[IP6_FMT];
69
70char seed[128];
71
72int main(int argc,char * const *argv)
73{
74 unsigned long u;
75 int opt;
76 const char *x;
77 int j;
78 int r;
79 int s;
80 int cloop;
81 int ipflag = 0;
82
83 dns_random_init(seed);
84
85 close(6);
86 close(7);
87 sig_ignore(sig_pipe);
88
89 while ((opt = getoptb(argc,(char **)argv,"46dDvqQhHrRi:p:t:T:l:I:")) != opteof)
90 switch(opt) {
91 case '4': ipflag = 1; break;
92 case '6': ipflag = 2; break;
93 case 'd': flagdelay = 1; break;
94 case 'D': flagdelay = 0; break;
95 case 'v': verbosity = 2; break;
96 case 'q': verbosity = 0; break;
97 case 'Q': verbosity = 1; break;
98 case 'l': forcelocal = optarg; break;
99 case 'H': flagremotehost = 0; break;
100 case 'h': flagremotehost = 1; break;
101 case 'R': flagremoteinfo = 0; break;
102 case 'r': flagremoteinfo = 1; break;
103 case 't': scan_ulong(optarg,&itimeout); break;
104 case 'T': j = scan_ulong(optarg,&ctimeout[0]);
105 if (optarg[j] == '+') ++j;
106 scan_ulong(optarg + j,&ctimeout[1]); break;
107 case 'i': if (!ip6_scan(optarg,iplocal)) usage(); break;
108 case 'I': netif = socket_getifidx(optarg); break;
109 case 'p': scan_ulong(optarg,&u); portlocal = u; break;
110 default: usage();
111 }
112 argv += optind;
113
114 if (!verbosity)
115 buffer_2->fd = -1;
116
117 hostname = *argv;
118 if (!hostname || str_equal((char *)hostname,"")) usage();
119 if (str_equal((char *)hostname,"0")) hostname = loopback;
120
121 x = *++argv;
122 if (!x) usage();
123 if (!x[scan_ulong(x,&u)])
124 portremote = u;
125 else {
126 struct servent *se;
127 se = getservbyname(x,"tcp");
128 if (!se)
129 logmsg(WHO,111,FATAL,B("unable to figure out port number for: ",x));
130 uint16_unpack_big((char *)&se->s_port,&portremote);
131 /* i continue to be amazed at the stupidity of the s_port interface */
132 }
133
134 if (!*++argv) usage();
135
136 /* IP address only */
137
138 if (ip4_scan(hostname,ipremote)) {
139 if (!stralloc_copyb(&addresses,(char *)V4mappedprefix,12)) nomem();
140 if (!stralloc_catb(&addresses,ipremote,4)) nomem();
141 byte_copy(iplocal,16,addresses.s);
142 } else if (ip6_scan(hostname,ipremote)) {
143 if (!stralloc_copyb(&addresses,ipremote,16)) nomem();
144 byte_copy(iplocal,16,addresses.s);
145 }
146
147 if (addresses.len < 4) {
148 if (!stralloc_copys(&tmp,hostname)) nomem();
149 dns_ip_qualify(&addresses,&fqdn,&tmp);
150 if (addresses.len < 16)
151 logmsg(WHO,111,ERROR,B("No IP address for: ",hostname));
152 }
153
154 if (addresses.len == 16) {
155 ctimeout[0] += ctimeout[1];
156 ctimeout[1] = 0;
157 }
158
159 for (cloop = 0; cloop < 2; ++cloop) {
160 if (!stralloc_copys(&moreaddresses,"")) nomem();
161 for (j = 0; j + 16 <= addresses.len; j += 16) {
162 if (ipflag == 1 || ip6_isv4mapped(addresses.s + j)) {
163 s = socket_tcp4();
164 if (s == -1) logmsg(WHO,111,FATAL,"unable to create socket");
165 r = socket_bind4(s,iplocal,portlocal);
166 } else {
167 s = socket_tcp6();
168 if (s == -1) logmsg(WHO,111,FATAL,"unable to create socket");
169 r = socket_bind6(s,iplocal,portlocal,netif);
170 }
171 strnum[fmt_ulong(strnum,portlocal)] = 0;
172 if (r == -1) logmsg(WHO,111,FATAL,B("unable to bind to socket for local port: ",strnum));
173 if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop],netif) == 0)
174 goto CONNECTED;
175 close(s);
176 if (!cloop && ctimeout[1] && (errno == ETIMEDOUT)) {
177 if (!stralloc_catb(&moreaddresses,addresses.s + j,16)) nomem();
178 }
179 else {
180 strnum[fmt_ulong(strnum,portremote)] = 0;
181 if (ip6_isv4mapped(addresses.s + j))
182 ipstr[ip4_fmt(ipstr,addresses.s + j + 12)] = 0;
183 else
184 ipstr[ip6_fmt(ipstr,addresses.s + j)] = 0;
185 }
186 }
187 if (!stralloc_copy(&addresses,&moreaddresses)) nomem();
188 }
189 logmsg(WHO,110,DROP,B("unable to connect to: ",ipstr," port: ",strnum));
190
191 _exit(111);
192
193
194 CONNECTED:
195
196 if (!flagdelay)
197 socket_tcpnodelay(s); /* if it fails, bummer */
198
199 /* Local */
200
201 if (socket_local(s,iplocal,&portlocal,&netif) == -1)
202 logmsg(WHO,111,FATAL,"unable to get local address");
203
204 if (!pathexec_env("PROTO",(ipflag - 1)?"TCP":"TCP6")) nomem();
205
206 strnum[fmt_ulong(strnum,portlocal)] = 0;
207 if (!pathexec_env("TCPLOCALPORT",strnum)) nomem();
208
209 if (ip6_isv4mapped(iplocal)) {
210 ipstr[ip6_fmt(ipstr,iplocal)] = 0;
211 if (!pathexec_env("TCP6LOCALIP",ipstr)) nomem();
212 if (!pathexec_env("TCP6LOCALPORT",strnum)) nomem();
213 } else
214 ipstr[ip4_fmt(ipstr,iplocal + 12)] = 0;
215 if (!pathexec_env("TCPLOCALIP",ipstr)) nomem();
216
217 x = forcelocal;
218 if (!x)
219 if (dns_name(&tmp,iplocal) < 0) {
220 if (!stralloc_0(&tmp)) nomem();
221 x = tmp.s;
222 }
223 if (!pathexec_env("TCPLOCALHOST",x)) nomem();
224
225 /* Remote */
226
227 if (socket_remote(s,ipremote,&portremote,&netif) == -1)
228 logmsg(WHO,111,FATAL,"unable to get remote address");
229
230 strnum[fmt_ulong(strnum,portremote)] = 0;
231 if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem();
232
233 if (ip6_isv4mapped(ipremote)) {
234 ipstr[ip6_fmt(ipstr,ipremote)] = 0;
235 if (!pathexec_env("TCP6REMOTEIP",ipstr)) nomem();
236 if (!pathexec_env("TCP6REMOTEPORT",strnum)) nomem();
237 } else
238 ipstr[ip4_fmt(ipstr,ipremote + 12)] = 0;
239 if (!pathexec_env("TCPREMOTEIP",ipstr)) nomem();
240
241 if (verbosity >= 2)
242 log_who(WHO,B("connected to ",ipstr," port ",strnum));
243
244 x = 0;
245 if (flagremotehost)
246 if (dns_name(&tmp,ipremote) < 0) {
247 if (!stralloc_0(&tmp)) nomem();
248 x = tmp.s;
249 }
250 if (!pathexec_env("TCPREMOTEHOST",x)) nomem();
251
252 x = 0;
253 if (flagremoteinfo)
255 if (!stralloc_0(&tmp)) nomem();
256 x = tmp.s;
257 }
258 if (!pathexec_env("TCPREMOTEINFO",x)) nomem();
259
260 if (fd_move(6,s) == -1)
261 logmsg(WHO,111,FATAL,"unable to set up descriptor 6");
262 if (fd_copy(7,6) == -1)
263 logmsg(WHO,111,FATAL,"unable to set up descriptor 7");
264 sig_uncatch(sig_pipe);
265
266 pathexec(argv);
267 logmsg(WHO,111,FATAL,B("unable to run: ",*argv));
268
269 return 0;
270}
int remoteinfo(stralloc *out, char ipremote[16], uint16 portremote, char iplocal[16], uint16 portlocal, unsigned int timeout, uint32 netif)
Definition: remoteinfo.c:97
int main()
Definition: addcr.c:4
uint16 portremote
Definition: tcpclient.c:58
int verbosity
Definition: tcpclient.c:45
uint16 portlocal
Definition: tcpclient.c:54
char iplocal[16]
Definition: tcpclient.c:53
unsigned long ctimeout[2]
Definition: tcpclient.c:50
unsigned long itimeout
Definition: tcpclient.c:49
int flagremotehost
Definition: tcpclient.c:48
int flagremoteinfo
Definition: tcpclient.c:47
char ipremote[16]
Definition: tcpclient.c:57
void nomem(void)
Definition: tcpclient.c:28
const char * hostname
Definition: tcpclient.c:60
const char * loopback
Definition: tcpclient.c:61
int flagdelay
Definition: tcpclient.c:46
uint32 netif
Definition: tcpclient.c:51
char * forcelocal
Definition: tcpclient.c:55
#define WHO
Definition: tcpclient.c:26
char seed[128]
Definition: tcpclient.c:70
void usage(void)
Definition: tcpclient.c:32
int close(int)