5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
25 int silc_net_set_socket_nonblock(int sock);
27 /* This function creates server or daemon or listener or what ever. This
28 does not fork a new process, it must be done by the caller if caller
29 wants to create a child process. This is used by the SILC server.
30 If argument `ip_addr' is NULL `any' address will be used. Returns
31 the created socket or -1 on error. */
33 int silc_net_create_server(int port, char *ip_addr)
36 struct sockaddr_in server;
37 int len = sizeof(server.sin_addr);
39 SILC_LOG_DEBUG(("Creating a new server listener"));
41 /* Create the socket */
42 sock = socket(PF_INET, SOCK_STREAM, 0);
44 SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
48 /* Set the socket options */
49 rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
51 SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
55 /* Set the socket information for bind() */
56 memset(&server, 0, sizeof(server));
57 server.sin_family = PF_INET;
59 server.sin_port = htons(port);
61 /* Convert IP address to network byte order */
63 silc_net_addr2bin(ip_addr, (unsigned char *)&server.sin_addr.s_addr, len);
65 server.sin_addr.s_addr = INADDR_ANY;
67 /* Bind the server socket */
68 rval = bind(sock, (struct sockaddr *)&server, sizeof(server));
70 SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno)));
74 /* Specify that we are listenning */
75 rval = listen(sock, 5);
77 SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno)));
81 /* Set the server socket to non-blocking mode */
82 silc_net_set_socket_nonblock(sock);
84 SILC_LOG_DEBUG(("Server listener created, fd=%d", sock));
89 /* Closes the server by closing the socket connection. */
91 void silc_net_close_server(int sock)
96 SILC_LOG_DEBUG(("Server socket closed"));
99 /* Creates a connection (TCP/IP) to a remote host. Returns the connection
100 socket or -1 on error. This blocks the process while trying to create
103 int silc_net_create_connection(int port, char *host)
106 struct hostent *dest;
107 struct sockaddr_in desthost;
109 SILC_LOG_DEBUG(("Creating connection to host %s port %d", host, port));
112 dest = gethostbyname(host);
114 SILC_LOG_ERROR(("Network (%s) unreachable", host));
118 /* Set socket information */
119 memset(&desthost, 0, sizeof(desthost));
120 desthost.sin_port = htons(port);
121 desthost.sin_family = PF_INET;
122 memcpy(&desthost.sin_addr, dest->h_addr_list[0], sizeof(desthost.sin_addr));
124 /* Create the connection socket */
125 sock = socket(PF_INET, SOCK_STREAM, 0);
127 SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
131 /* Connect to the host */
132 rval = connect(sock, (struct sockaddr *)&desthost, sizeof(desthost));
134 SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
140 /* Set appropriate options */
141 silc_net_set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1);
142 silc_net_set_socket_opt(sock, SOL_SOCKET, SO_KEEPALIVE, 1);
144 SILC_LOG_DEBUG(("Connection created"));
149 /* Creates a connection (TCP/IP) to a remote host. Returns the connection
150 socket or -1 on error. This creates non-blocking socket hence the
151 connection returns directly. To get the result of the connect() one
152 must select() the socket and read the result after it's ready. */
154 int silc_net_create_connection_async(int port, char *host)
157 struct hostent *dest;
158 struct sockaddr_in desthost;
160 SILC_LOG_DEBUG(("Creating connection (async) to host %s port %d",
164 dest = gethostbyname(host);
166 SILC_LOG_ERROR(("Network (%s) unreachable", host));
170 /* Set socket information */
171 memset(&desthost, 0, sizeof(desthost));
172 desthost.sin_port = htons(port);
173 desthost.sin_family = PF_INET;
174 memcpy(&desthost.sin_addr, dest->h_addr_list[0], sizeof(desthost.sin_addr));
176 /* Create the connection socket */
177 sock = socket(PF_INET, SOCK_STREAM, 0);
179 SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
183 /* Set the socket to non-blocking mode */
184 silc_net_set_socket_nonblock(sock);
186 /* Connect to the host */
187 rval = connect(sock, (struct sockaddr *)&desthost, sizeof(desthost));
189 if (errno != EINPROGRESS) {
190 SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
197 /* Set appropriate options */
198 silc_net_set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1);
199 silc_net_set_socket_opt(sock, SOL_SOCKET, SO_KEEPALIVE, 1);
201 SILC_LOG_DEBUG(("Connection operation in progress"));
206 /* Closes the connection by closing the socket connection. */
208 void silc_net_close_connection(int sock)
213 /* Set's the socket to non-blocking mode. */
215 int silc_net_set_socket_nonblock(int sock)
217 return fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
220 /* Converts the IP number string from numbers-and-dots notation to
223 bool silc_net_addr2bin(const char *addr, unsigned char *bin,
229 ret = inet_aton(addr, &tmp);
234 SILC_PUT32_LSB(tmp.s_addr, bin);