3 * Copyright (C) 2004 Simone Piccardi
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /***************************************************************
22 * Routines for socket operations.
24 * Define routines for socket handling
28 ***************************************************************/
29 #include <sys/types.h> /* primitive system data types */
30 #include <stdio.h> /* standard I/O library */
31 #include <unistd.h> /* unix standard library */
32 #include <string.h> /* C strings library */
33 #include <errno.h> /* error definitions and routines */
34 #include <sys/socket.h> /* socket constants, types and functions */
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
40 /**************************************************************************
44 * Return a string with the numeric address translation of the content
45 * of an addrinfo stucture
47 * Author: Simone Piccardi
50 **************************************************************************/
51 char *ip_ntop(struct addrinfo *addr, char *dst, socklen_t cnt)
53 // char buffer[INET6_ADDRSTRLEN];
55 struct sockaddr_in *ip4;
56 struct sockaddr_in6 *ip6;
57 switch (addr->ai_family) {
59 ip4 = (struct sockaddr_in *) addr->ai_addr;
60 ret = inet_ntop(ip4->sin_family, &ip4->sin_addr, dst, cnt);
63 ip6 = (struct sockaddr_in6 *) addr->ai_addr;
64 ret = inet_ntop(ip6->sin6_family, &ip6->sin6_addr, dst, cnt);
72 /****************************************************************
75 * Return a connected socket given hostname, service, and socket type
77 * Author: Simone Piccardi
80 ****************************************************************/
81 int sockconn(char *host, char *serv, int prot, int type)
83 struct addrinfo hint, *addr, *save;
86 /* initialize hint structure */
87 memset(&hint, 0, sizeof(struct addrinfo));
88 hint.ai_family = PF_UNSPEC; /* generic address (IPv4 or IPv6) */
89 hint.ai_protocol = prot; /* protocol */
90 hint.ai_socktype = type; /* socket type */
91 res = getaddrinfo(host, serv, &hint, &addr); /* calling getaddrinfo */
92 if (res != 0) { /* on error exit */
93 fprintf(stderr, "sockconn: resolution failed:");
94 // fprintf(stderr, "host %s, service %s, protocol %d", host, serv, prot);
95 fprintf(stderr, " %s\n", gai_strerror(res));
96 errno = 0; /* clear errno */
100 while (addr != NULL) { /* loop on possible addresses */
102 sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
103 if (sock < 0) { /* on error */
104 if (addr->ai_next != NULL) { /* if other addresses */
105 addr=addr->ai_next; /* take next */
106 continue; /* restart cycle */
107 } else { /* else stop */
108 perror("sockconn: cannot create socket");
112 /* connect the socket */
113 if ( (res = connect(sock, addr->ai_addr, addr->ai_addrlen) < 0)) {
114 if (addr->ai_next != NULL) { /* if other addresses */
115 addr=addr->ai_next; /* take next */
116 close(sock); /* close socket */
117 continue; /* restart cycle */
118 } else { /* else stop */
119 perror("sockconn: cannot connect");
123 } else break; /* ok, we are connected! */
125 freeaddrinfo(save); /* done, release memory */
128 /****************************************************************
131 * Return a binded socket given hostname, service, and socket type
133 * Author: Simone Piccardi
136 ****************************************************************/
137 int sockbind(char *host, char *serv, int prot, int type)
139 struct addrinfo hint, *addr, *save;
142 char buf[INET6_ADDRSTRLEN];
143 /* initialize hint structure */
144 memset(&hint, 0, sizeof(struct addrinfo));
145 hint.ai_flags = AI_PASSIVE; /* address for binding */
146 hint.ai_family = PF_UNSPEC; /* generic address (IPv4 or IPv6) */
147 hint.ai_protocol = prot; /* protocol */
148 hint.ai_socktype = type; /* socket type */
149 res = getaddrinfo(host, serv, &hint, &addr); /* calling getaddrinfo */
150 if (res != 0) { /* on error exit */
151 fprintf(stderr, "sockbind: resolution failed:");
152 // fprintf(stderr, "host %s, service %s, protocol %d", host, serv, prot);
153 fprintf(stderr, " %s\n", gai_strerror(res));
154 errno = 0; /* clear errno */
157 save = addr; /* saving for freeaddrinfo */
158 while (addr != NULL) { /* loop on possible addresses */
160 sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
161 if (sock < 0) { /* on error */
162 if (addr->ai_next != NULL) { /* if other addresses */
163 addr=addr->ai_next; /* take next */
164 continue; /* restart cycle */
165 } else { /* else stop */
166 perror("sockbind: cannot create socket");
170 /* connect the socket */
171 printf("Indirizzo %s\n", ip_ntop(addr, buf, sizeof(buf)));
172 if ( (res = bind(sock, addr->ai_addr, addr->ai_addrlen)) < 0) {
173 if (addr->ai_next != NULL) { /* if other addresses */
174 addr=addr->ai_next; /* take next */
175 close(sock); /* close socket */
176 continue; /* restart cycle */
177 } else { /* else stop */
178 perror("sockbind: cannot connect");
182 } else break; /* ok, we are binded! */
184 freeaddrinfo(save); /* done, release memory */
187 /****************************************************************
189 * Routine sockbindopt
190 * Return a binded socket given hostname, service, and socket type
191 * Issue a SO_REUSEADDR on the socket before binding on reuse value.
193 * Author: Simone Piccardi
196 ****************************************************************/
197 int sockbindopt(char *host, char *serv, int prot, int type, int reuse)
199 struct addrinfo hint, *addr, *save;
202 char buf[INET6_ADDRSTRLEN];
203 /* initialize hint structure */
204 memset(&hint, 0, sizeof(struct addrinfo));
205 hint.ai_flags = AI_PASSIVE; /* address for binding */
206 hint.ai_family = PF_UNSPEC; /* generic address (IPv4 or IPv6) */
207 hint.ai_protocol = prot; /* protocol */
208 hint.ai_socktype = type; /* socket type */
209 res = getaddrinfo(host, serv, &hint, &addr); /* calling getaddrinfo */
210 if (res != 0) { /* on error exit */
211 fprintf(stderr, "sockbind: resolution failed:");
212 // fprintf(stderr, "host %s, service %s, protocol %d", host, serv, prot);
213 fprintf(stderr, " %s\n", gai_strerror(res));
214 errno = 0; /* clear errno */
217 save = addr; /* saving for freeaddrinfo */
218 while (addr != NULL) { /* loop on possible addresses */
220 sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
221 if (sock < 0) { /* on error */
222 if (addr->ai_next != NULL) { /* if other addresses */
223 addr=addr->ai_next; /* take next */
224 continue; /* restart cycle */
225 } else { /* else stop */
226 perror("sockbind: cannot create socket");
230 /* connect the socket */
231 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
232 &reuse, sizeof(reuse))) {
233 printf("error on socket options\n");
236 printf("Indirizzo %s\n", ip_ntop(addr, buf, sizeof(buf)));
237 if ( (res = bind(sock, addr->ai_addr, addr->ai_addrlen)) < 0) {
238 if (addr->ai_next != NULL) { /* if other addresses */
239 addr=addr->ai_next; /* take next */
240 close(sock); /* close socket */
241 continue; /* restart cycle */
242 } else { /* else stop */
243 perror("sockbind: cannot connect");
247 } else break; /* ok, we are binded! */
249 freeaddrinfo(save); /* done, release memory */