]>
git.zerfleddert.de Git - amt/blob - tcp.c
2 * TCP helper functions.
4 * Copyright (C) 2007 Gerd Hoffmann <kraxel@redhat.com
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 /* ------------------------------------------------------------------ */
34 static char *strfamily(int family
)
37 case PF_INET6
: return "ipv6";
38 case PF_INET
: return "ipv4";
39 case PF_UNIX
: return "unix";
44 int tcp_connect(struct addrinfo
*ai
,
45 char *addr
, char *port
,
46 char *host
, char *serv
)
48 struct addrinfo
*res
,*e
;
49 struct addrinfo
*lres
, ask
;
50 char uaddr
[INET6_ADDRSTRLEN
+1];
52 char uhost
[INET6_ADDRSTRLEN
+1];
57 ai
->ai_flags
= AI_CANONNAME
;
58 if (0 != (rc
= getaddrinfo(host
, serv
, ai
, &res
))) {
60 fprintf(stderr
,"getaddrinfo (peer): %s\n", gai_strerror(rc
));
63 for (e
= res
; e
!= NULL
; e
= e
->ai_next
) {
64 if (0 != getnameinfo((struct sockaddr
*)e
->ai_addr
,e
->ai_addrlen
,
65 uhost
,INET6_ADDRSTRLEN
,userv
,32,
66 NI_NUMERICHOST
| NI_NUMERICSERV
)) {
68 fprintf(stderr
,"getnameinfo (peer): oops\n");
71 if (-1 == (sock
= socket(e
->ai_family
, e
->ai_socktype
,
74 fprintf(stderr
,"socket (%s): %s\n",
75 strfamily(e
->ai_family
),strerror(errno
));
78 setsockopt(sock
,SOL_SOCKET
,SO_REUSEADDR
,&opt
,sizeof(opt
));
79 if (NULL
!= addr
|| NULL
!= port
) {
81 memset(&ask
,0,sizeof(ask
));
82 ask
.ai_flags
= AI_PASSIVE
;
83 ask
.ai_family
= e
->ai_family
;
84 ask
.ai_socktype
= e
->ai_socktype
;
85 if (0 != (rc
= getaddrinfo(addr
, port
, &ask
, &lres
))) {
87 fprintf(stderr
,"getaddrinfo (local): %s\n",
91 if (0 != getnameinfo((struct sockaddr
*)lres
->ai_addr
,
93 uaddr
,INET6_ADDRSTRLEN
,uport
,32,
94 NI_NUMERICHOST
| NI_NUMERICSERV
)) {
96 fprintf(stderr
,"getnameinfo (local): oops\n");
99 if (-1 == bind(sock
, lres
->ai_addr
, lres
->ai_addrlen
)) {
101 fprintf(stderr
,"%s [%s] %s bind: %s\n",
102 strfamily(lres
->ai_family
),uaddr
,uport
,
107 /* connect to peer */
108 if (-1 == connect(sock
,e
->ai_addr
,e
->ai_addrlen
)) {
110 fprintf(stderr
,"%s %s [%s] %s connect: %s\n",
111 strfamily(e
->ai_family
),e
->ai_canonname
,uhost
,userv
,
117 fprintf(stderr
,"%s %s [%s] %s open\n",
118 strfamily(e
->ai_family
),e
->ai_canonname
,uhost
,userv
);
119 fcntl(sock
,F_SETFL
,O_NONBLOCK
);
125 int tcp_listen(struct addrinfo
*ai
, char *addr
, char *port
)
127 struct addrinfo
*res
,*e
;
128 char uaddr
[INET6_ADDRSTRLEN
+1];
130 int slisten
,rc
,opt
=1;
133 ai
->ai_flags
= AI_PASSIVE
;
134 if (0 != (rc
= getaddrinfo(addr
, port
, ai
, &res
))) {
136 fprintf(stderr
,"getaddrinfo: %s\n",gai_strerror(rc
));
140 /* create socket + bind */
141 for (e
= res
; e
!= NULL
; e
= e
->ai_next
) {
142 getnameinfo((struct sockaddr
*)e
->ai_addr
,e
->ai_addrlen
,
143 uaddr
,INET6_ADDRSTRLEN
,uport
,32,
144 NI_NUMERICHOST
| NI_NUMERICSERV
);
145 if (-1 == (slisten
= socket(e
->ai_family
, e
->ai_socktype
,
148 fprintf(stderr
,"socket (%s): %s\n",
149 strfamily(e
->ai_family
),strerror(errno
));
153 setsockopt(slisten
,SOL_SOCKET
,SO_REUSEADDR
,&opt
,sizeof(opt
));
154 if (-1 == bind(slisten
, e
->ai_addr
, e
->ai_addrlen
)) {
156 fprintf(stderr
,"%s [%s] %s bind: %s\n",
157 strfamily(e
->ai_family
),uaddr
,uport
,
167 /* wait for a incoming connection */
169 fprintf(stderr
,"listen on %s [%s] %s ...\n",
170 strfamily(e
->ai_family
),uaddr
,uport
);
171 fcntl(slisten
,F_SETFL
,O_NONBLOCK
);