1 /*
2   net_utilities.c
3   --------------
4   A bunch of useful functions that I keep using all the time.
5 
6   Copyright (C) 2000  Eu-Jin Goh
7 
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License
10   as published by the Free Software Foundation; either version 2
11   of the License, or (at your option) any later version.
12 
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
21   USA.
22 */
23 
24 /* necessary header files and defines */
25 
26 #include <stdio.h>
27 
28 #include "net_utilities.h"
29 #include "general_utilities.h"
30 
31 /* ------------- Networking Functions ------------- */
32 
33 /*
34   Creates a ipv4 stream socket
35 */
36 int
utlnet_CreateIPV4StreamSocket()37 utlnet_CreateIPV4StreamSocket()
38 {
39     int fd;
40 
41     /* set up the socket */
42     if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
43     {
44 	utl_HandleError("utlnet_CreateIPV4StreamSocket");
45     }
46 
47     return fd;
48 }
49 
50 /*
51    Set socket to be reusable.
52    Returns -1 on failure
53 */
54 int
utlnet_SetSocketReusable(int sock_fd)55 utlnet_SetSocketReusable(int sock_fd)
56 {
57     int sock_opt = 1;
58 
59     /*
60        sets the socket so that it can be reused. this enables another
61        application to make use of the same socket
62     */
63     if(setsockopt(sock_fd, SOL_SOCKET,SO_REUSEADDR,
64 		  (void *)&sock_opt,sizeof(int)) < 0)
65     {
66 	perror("utlnet_SetSocketReusable");
67 	return UTL_FAILURE;
68     }
69     return UTL_SUCCESS;
70 }
71 
72 /*
73   It first tries to convert it assuming that it is a dotted
74   decimal number and if that fails, it uses gethostbyname to convert it.
75 
76   Returns -1 on resolve failure.
77 */
78 int
utlnet_SetIP(struct sockaddr_in * addr,const char * host_name)79 utlnet_SetIP(struct sockaddr_in *addr, const char *host_name)
80 {
81     unsigned long	in_addr;   /* Binary IP address */
82     struct hostent *hostent_ptr;   /* used with gethostbyname() */
83 
84     /*
85       First try to convert the host name as a dotted-decimal number.
86       Only if that fails we call gethostbyname().
87     */
88     if((in_addr = inet_addr(host_name)) != INADDR_NONE)
89     {
90 	addr->sin_addr.s_addr = in_addr; /* conversion succeeded */
91     }
92     else
93     {
94 	if ((hostent_ptr = gethostbyname(host_name)) == NULL)
95 	{
96 	    fprintf(stderr, "utlnet_SetIP: %s", hstrerror(h_errno));
97 	    return UTL_FAILURE;
98 	}
99 
100 	memcpy((char *) &(addr->sin_addr), (char *)hostent_ptr->h_addr,
101 	       hostent_ptr->h_length);
102     }
103 
104     return UTL_SUCCESS;
105 }
106 
107 struct hostent *
utlnet_GetHostName(struct sockaddr_in * addr)108 utlnet_GetHostName(struct sockaddr_in *addr)
109 {
110     return gethostbyaddr((char *)&(addr->sin_addr),sizeof(addr->sin_addr),
111 			 addr->sin_family);
112 }
113 
114 /*
115   Set the port number in a socket addr struct
116 */
117 void
utlnet_SetPort(struct sockaddr_in * addr,const short port)118 utlnet_SetPort(struct sockaddr_in *addr, const short port)
119 {
120     addr->sin_port = htons(port);
121 }
122 
123 /*
124   Set the protocol type in a socket addr struct
125 */
126 void
utlnet_SetIPV4Protocol(struct sockaddr_in * addr)127 utlnet_SetIPV4Protocol(struct sockaddr_in *addr)
128 {
129     addr->sin_family = AF_INET;
130 }
131 
132 /*
133    sets the IP, port and protocol for a IPV4 connection.
134    returns -1 on failure
135 */
136 int
utlnet_InitIPV4ClientSockAddrStruct(struct sockaddr_in * addr,const short port,const char * host_name)137 utlnet_InitIPV4ClientSockAddrStruct(struct sockaddr_in *addr,
138 				    const short port,
139 				    const char *host_name)
140 {
141     memset( (char*) addr, 0, sizeof(*addr));
142     utlnet_SetPort(addr, port);
143     utlnet_SetIPV4Protocol(addr);
144 
145     return utlnet_SetIP(addr, host_name);
146 }
147 
148 /*
149   sets the port, protocol and server ip. the serverIP is typically
150   set to INADDR_ANY to allow kernel selection.
151 */
152 void
utlnet_InitIPV4ServerSockAddrStruct(struct sockaddr_in * addr,const short port,const unsigned int server_ip)153 utlnet_InitIPV4ServerSockAddrStruct(struct sockaddr_in *addr,
154 				    const short port,
155 				    const unsigned int server_ip)
156 {
157     memset( (char*) addr, 0, sizeof(*addr));
158     utlnet_SetPort(addr, port);
159     utlnet_SetIPV4Protocol(addr);
160     addr->sin_addr.s_addr = htonl(server_ip);
161 }
162 
163 /*
164   Sets up the listening socket for the given port and IP address
165   in servAddr. Also sets the queue backlog and the socket option
166   if the port number needs to be reusable.
167 */
168 int
utlnet_InitIPV4ServerSocket(const int sock_fd,struct sockaddr_in * addr,int sock_queue_backlog,char reusable)169 utlnet_InitIPV4ServerSocket(const int sock_fd,
170 			    struct sockaddr_in *addr,
171 			    int sock_queue_backlog,
172 			    char reusable)
173 {
174     if(reusable && (utlnet_SetSocketReusable(sock_fd) == UTL_FAILURE))
175     {
176 	exit(UTL_FAILURE);
177     }
178 
179     if(bind(sock_fd,(struct sockaddr *)addr, sizeof(*addr)) < 0)
180     {
181 	utl_HandleError("utlnet_InitIPV4ServerSocket");
182     }
183     listen(sock_fd, sock_queue_backlog);
184 
185     return UTL_SUCCESS;
186 }
187 
188 /*
189    Connect to a remote host using an IPV4 sockaddr.
190    Returns -1 on failure
191 */
192 int
utlnet_IPV4Connect(int sock_fd,struct sockaddr_in * to_addr)193 utlnet_IPV4Connect(int sock_fd, struct sockaddr_in *to_addr)
194 {
195     if(connect(sock_fd,(struct sockaddr *) to_addr,
196 	       sizeof(struct sockaddr)) < 0)
197     {
198 	return UTL_FAILURE;
199     }
200 
201     return UTL_SUCCESS;
202 }
203 
204 int
utlnet_Accept(const int sock_fd,struct sockaddr_in * from_addr)205 utlnet_Accept(const int sock_fd, struct sockaddr_in *from_addr)
206 {
207     int conn_fd;
208     socklen_t size;
209 
210     size = sizeof(*from_addr);
211     memset( (char *) from_addr, 0, size);
212 
213     if((conn_fd = accept(sock_fd,(struct sockaddr *) from_addr, &size)) < 0)
214     {
215 	utl_HandleError("utlnet_Accept");
216     }
217     return conn_fd;
218 }
219 
220 /* Write/Read to the socket.
221    Returns bytes sent/read or -1 on error */
222 int
utlnet_WriteToSocket(int sock_fd,char * buffer,int length)223 utlnet_WriteToSocket(int sock_fd, char *buffer, int length)
224 {
225     int bytes_sent;
226 
227     if((bytes_sent = write(sock_fd, buffer, length)) < length)
228     {
229 	perror("utlnet_WriteToSocket");
230 	return UTL_FAILURE;
231     }
232     return bytes_sent;
233 }
234 
235 int
utlnet_ReadFromSocket(int sock_fd,char * buffer,int length)236 utlnet_ReadFromSocket(int sock_fd, char *buffer, int length)
237 {
238     int bytes_read;
239 
240     if((bytes_read = read(sock_fd, buffer, length)) < 0)
241     {
242 	perror("utlnet_ReadFromSocket");
243 	return UTL_FAILURE;
244     }
245     return bytes_read;
246 }
247 
248 int
utlnet_WritenBytesToSocket(int sock_fd,char * buffer,int n_bytes)249 utlnet_WritenBytesToSocket(int sock_fd, char *buffer, int n_bytes)
250 {
251     int bytes_sent;
252     int total_sent = 0;
253 
254     while((bytes_sent =
255 	     write(sock_fd, buffer + total_sent, n_bytes - total_sent)) > 0)
256     {
257 	total_sent += bytes_sent;
258 	if(total_sent >= n_bytes)
259 	{
260 	    break;
261 	}
262     }
263 
264     if(total_sent < n_bytes)
265     {
266 	/* this would be the error code returned by write */
267 	return bytes_sent;
268     }
269 
270     return total_sent;
271 }
272 
273 int
utlnet_ReadnBytesFromSocket(int sock_fd,char * buffer,int n_bytes)274 utlnet_ReadnBytesFromSocket(int sock_fd, char *buffer, int n_bytes)
275 {
276     int bytes_read;
277     int total_read = 0;
278 
279     while((bytes_read =
280 	     read(sock_fd, buffer + total_read, n_bytes - total_read)) > 0)
281     {
282 	total_read += bytes_read;
283 	if(total_read >= n_bytes)
284 	{
285 	    break;
286 	}
287     }
288 
289     if(total_read < n_bytes)
290     {
291 	/* this would be the error code returned by read */
292 	return bytes_read;
293     }
294 
295     return total_read;
296 }
297 
298 int
utlnet_PeekAtnBytesFromSocket(int sock_fd,char * buffer,int n_bytes)299 utlnet_PeekAtnBytesFromSocket(int sock_fd, char *buffer, int n_bytes)
300 {
301     return recv(sock_fd, buffer, n_bytes, MSG_PEEK);
302 }
303