modules/sk/sk_socket.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- SK_atoport
- SK_close
- SK_getsock
- SK_accept_connection
- SK_connect
- SK_read
- SK_write
- SK_gets
- SK_puts
- SK_putc
- SK_getc
- SK_getpeername
- SK_getpeerip
1 /***************************************
2 $Revision: 1.20 $
3
4 Socket module - routines facilitating calls to socket library.
5
6 Status: NOT REVUED, TESTED
7
8 Basic code adapted by Chris Ottrey from
9 http://www.ibrado.com/sock-faq/sfaq.html#faq65 - sample source code.
10 ******************/ /******************
11 Modification History:
12 ottrey (08/03/1999) Created from sockhelp.c.
13 ottrey (08/03/1998) Heavily butchered.
14 joao (22/06/1999) Modified socket creation and accepts.
15 marek (December 2000) Added connection function w/timeout.
16 ******************/ /******************
17 Copyright (c) 1999,2000,2001,2002 RIPE NCC
18
19 All Rights Reserved
20
21 Permission to use, copy, modify, and distribute this software and its
22 documentation for any purpose and without fee is hereby granted,
23 provided that the above copyright notice appear in all copies and that
24 both that copyright notice and this permission notice appear in
25 supporting documentation, and that the name of the author not be
26 used in advertising or publicity pertaining to distribution of the
27 software without specific, written prior permission.
28
29 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
30 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
31 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
32 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
33 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
34 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 ***************************************/
36
37 #include "rip.h"
38
39 /* SK_atoport() */
40 /*++++++++++++++++++++++++++++++++++++++
41 Take a service name, and a service type, and return a port number. If the
42 service name is not found, it tries it as a decimal number. The number
43 returned is byte ordered for the network.
44
45 char *service Service name (or port number).
46
47 char *proto Protocol (eg "tcp").
48
49 Author:
50 ottrey.
51
52 ++++++++++++++++++++++++++++++++++++++*/
53 int SK_atoport(const char *service, const char *proto) {
/* [<][>][^][v][top][bottom][index][help] */
54 unsigned port;
55 long int lport;
56 struct servent *serv;
57 char *errpos;
58 struct servent result;
59 char buffer[STR_XXL];
60
61 /* First try to read it from /etc/services */
62
63 #ifdef __linux__
64 if(getservbyname_r(service, proto, &result, buffer, sizeof(buffer), &serv) < 0) serv = NULL;
65 #else
66 serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer));
67 #endif
68
69 if (serv != NULL)
70 port = serv->s_port;
71 else { /* Not in services, maybe a number? */
72 lport = strtol(service,&errpos,0);
73 if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
74 return -1; /* Invalid port address */
75 port = htons(lport);
76 }
77 return port;
78 } /* SK_atoport() */
79
80
81 /* SK_close() */
82 /*++++++++++++++++++++++++++++++++++++++
83
84 int SK_close wrapper around closing the socket. Returns the value
85 returned by close(2)
86
87 int socket socket to be closed
88
89 Author:
90 ottrey
91 ++++++++++++++++++++++++++++++++++++++*/
92 int SK_close(int socket) {
/* [<][>][^][v][top][bottom][index][help] */
93 ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
94
95 return close(socket);
96 }
97
98 /* SK_getsock() */
99 /*++++++++++++++++++++++++++++++++++++++
100
101 int SK_getsock This function creates a socket and binds to it.
102 Returns the number of the created
103 descriptor/listening socket.
104
105 int socket_type SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
106
107 unsigned port The port to listen on. Ports < 1024 are
108 reserved for the root user. Host byte order.
109
110 int backlog Size of the backlog queue to be set on that
111 socket.
112
113 uint32_t bind_address Address to bind to, in network order.
114
115 Authors:
116 ottrey,
117 joao,
118 marek (added htons conversion for port).
119
120 ++++++++++++++++++++++++++++++++++++++*/
121 int SK_getsock(int socket_type, unsigned h_port, int backlog,
/* [<][>][^][v][top][bottom][index][help] */
122 uint32_t bind_address) {
123 struct sockaddr_in address;
124 int listening_socket;
125 int reuse_addr = 1;
126 u_short port = htons(h_port);
127
128 /* Setup internet address information.
129 This is used with the bind() call */
130 memset((char *) &address, 0, sizeof(address));
131 address.sin_family = AF_INET;
132 address.sin_port = port;
133 address.sin_addr.s_addr = bind_address;
134
135 /* Map all of the signals and exit routine */
136
137 listening_socket = socket(AF_INET, socket_type, 0);
138 if (listening_socket < 0) {
139 perror("socket");
140 exit(EXIT_FAILURE);
141 }
142
143 setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr));
144
145 if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
146 perror("bind");
147 close(listening_socket);
148 exit(EXIT_FAILURE);
149 }
150
151
152 if (socket_type == SOCK_STREAM) {
153 listen(listening_socket, backlog); /* Queue up to five connections before
154 having them automatically rejected. */
155 }
156
157 return listening_socket;
158 } /* SK_getsock() */
159
160 /*++++++++++++++++++++++++++++++++++++++
161
162 Wait for an incoming connection on the specified socket
163
164 int SK_accept_connection The socket for communicating to the client
165
166 int listening_socket The socket that the server is bound to
167
168 Authors:
169 joao,
170 marek.
171 ++++++++++++++++++++++++++++++++++++++*/
172 int SK_accept_connection(int listening_socket) {
/* [<][>][^][v][top][bottom][index][help] */
173 int connected_socket = -1;
174 int num_errors = 0;
175
176 #define MAX_ACCEPT_ERRORS 3
177
178 for (;;) {
179
180 ER_dbg_va(FAC_SK, ASP_SK_GEN,
181 "Going to accept connections on socket : %d",listening_socket);
182
183 connected_socket = accept(listening_socket, NULL, NULL);
184 if (connected_socket < 0) {
185 /* Either a real error occured, or blocking was interrupted for
186 some reason. Only abort execution if a real error occured. */
187 switch(errno) {
188 case EINTR: /* Interrupted system call */
189 case ECONNABORTED: /* Software caused connection abort */
190 /* no warning */
191 continue; /* don't return - do the accept again */
192 default:
193 /* special case: shutdown of the server - just return */
194 if( CO_get_do_server() == 0 ) {
195 return -1;
196 }
197 else { /* real error */
198 if( ++num_errors < MAX_ACCEPT_ERRORS ) {
199 /* warn */
200 ER_perror(FAC_SK, SK_ACERW, "(%d) %s", errno, strerror(errno));
201 }
202 else {
203 /* crash */
204 ER_perror(FAC_SK, SK_ACERF,
205 "too many accept() errors (maximum is %d)", MAX_ACCEPT_ERRORS);
206 die;
207 }
208 }
209 }
210 }
211 else { /* success */
212 ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d",
213 connected_socket
214 );
215
216 return connected_socket;
217 }
218
219 }
220 }
221
222
223 /*++++++++++++++++++++++++++++++++++++++
224
225 er_ret_t SK_connect wrapper around connect(), doing non-blocking
226 connection with timeout
227
228 int *sock pointer to the storage for socket descriptor
229
230 char *hostname host to connect to
231
232 int port port to connect to
233
234 int timeout in seconds
235
236 Author: marek
237
238 ++++++++++++++++++++++++++++++++++++++*/
239 er_ret_t SK_connect(int *sock, char *hostname, unsigned int port, unsigned int timeout)
/* [<][>][^][v][top][bottom][index][help] */
240 {
241 struct sockaddr_in sin;
242 struct hostent *hp;
243 int s;
244 int flags;
245 struct timeval ptm;
246 fd_set rset, wset;
247 int gs, sel, er, erlen=sizeof(er);
248 int error;
249 struct hostent result;
250 char aliasbuf[8192]; /* Stevens, UNIX net. prog., p.304 */
251
252 /* look up the host name */
253 #ifdef __linux__
254 er = (gethostbyname_r(hostname, &result, aliasbuf,
255 sizeof(aliasbuf), &hp, &error) < 0 );
256 #else /* default is Solaris implementation */
257 hp = gethostbyname_r(hostname, &result, aliasbuf,
258 sizeof(aliasbuf), &error);
259 er = ( hp == NULL );
260 #endif
261
262 if( er ) {
263 return SK_BADHOST;
264 }
265
266 /* create a socket */
267 s = socket(AF_INET, SOCK_STREAM, 0);
268 if (s < 0) {
269 return SK_SOCKET;
270 }
271
272 /* bind to it */
273 bzero((caddr_t)&sin, sizeof (sin));
274 sin.sin_family = hp->h_addrtype;
275 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
276 close(s);
277 return SK_BIND;
278 }
279 bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
280 sin.sin_port=htons(port);
281
282 /* connect in non-blocking mode */
283 flags = fcntl(s, F_GETFL, 0);
284 fcntl(s, F_SETFL, flags | O_NONBLOCK );
285
286 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0
287 && errno != EINPROGRESS ) {
288 close(s);
289 return SK_CONNECT;
290 }
291
292 /* now wait for success */
293 FD_ZERO( &rset );
294 FD_SET( s, &rset );
295 wset = rset;
296 ptm.tv_usec = 0;
297 ptm.tv_sec = timeout;
298
299 if( (sel=select(s+1, &rset, &wset, NULL, &ptm)) == 0 ) {
300 /* timeout */
301 close(s);
302 return SK_TIMEOUT;
303 }
304 if (sel < 0) {
305 close(s);
306 return SK_CONNECT;
307 }
308
309 gs = getsockopt(s, SOL_SOCKET, SO_ERROR, &er, &erlen);
310
311 if( gs < 0 || er ) { /* Stevens code, p.411 is exceptionally crappy */
312 close(s);
313 return SK_CONNECT;
314 } /* if error */
315
316 fcntl(s, F_SETFL, flags);
317 *sock = s;
318
319 return SK_OK;
320 }
321
322
323 /* SK_read() */
324 /*++++++++++++++++++++++++++++++++++++++
325
326 This is just like the read() system call, except that it will make
327 sure that all your data goes through the socket.
328
329 int SK_read Returns the number of bytes read.
330
331 int sockfd The socket file descriptor.
332
333 char *buf The buffer to be read from the socket.
334
335 size_t count The number of bytes in the buffer.
336
337 Author:
338 ottrey
339
340 ++++++++++++++++++++++++++++++++++++++*/
341 int SK_read(int sockfd, char *buf, size_t count) {
/* [<][>][^][v][top][bottom][index][help] */
342 size_t bytes_read = 0;
343 int this_read;
344
345 while (bytes_read < count) {
346 do
347 this_read = read(sockfd, buf, count - bytes_read);
348 while ( (this_read < 0) && (errno == EINTR) );
349 if (this_read < 0)
350 return this_read;
351 else if (this_read == 0)
352 return bytes_read;
353 bytes_read += this_read;
354 buf += this_read;
355 }
356
357 return count;
358
359 } /* SK_read() */
360
361
362 /* SK_write() */
363 /*++++++++++++++++++++++++++++++++++++++
364
365 int SK_write Returns:
366 -1 on error
367 0 on timeout
368 1 on success (all bytes written)
369
370 int sockfd The socket file descriptor.
371
372 const char *buf The buffer to be written to the socket.
373
374 int count The number of bytes in the buffer.
375
376 const struct timeval *timeout Maximum time to wait between each
377 write() call, or NULL for "forever".
378
379 int *count_sent Set to the number of bytes sucessfully
380 written. This value is always valid,
381 although it will be less than the
382 total number of bytes to send if
383 the function returns -1 or 0. NULL
384 may be sent if the caller does not
385 care about the number of bytes sent on
386 failure.
387
388 ++++++++++++++++++++++++++++++++++++++*/
389
390 int
391 SK_write(int sockfd,
/* [<][>][^][v][top][bottom][index][help] */
392 const char *buf,
393 int count,
394 const struct timeval *timeout,
395 int *count_sent)
396 {
397 int local_count_sent; /* only used if caller passes NULL */
398 fd_set fds;
399 int select_ret;
400 struct timeval tv;
401 int write_ret;
402
403 /* copious logging never hurt anybody (well, except people with slow
404 computers or small hard disks) */
405 ER_dbg_va(FAC_SK, ASP_SK_WRIT,
406 "SK_write = { sockfd=[%d], buf=[%s], count=[%d]",
407 sockfd, buf, count);
408
409 /* allow caller to pass NULL if it doesn't care about the count sent */
410 if (count_sent == NULL) {
411 count_sent = &local_count_sent;
412 }
413
414 /* loop around until we send all of our data, or we get a timeout or
415 disconnect */
416 *count_sent = 0;
417 while (*count_sent < count) {
418
419 /* first, call select() and see if we can write without blocking */
420 FD_ZERO(&fds);
421 FD_SET(sockfd, &fds);
422 if (timeout == NULL) {
423 select_ret = select(sockfd+1, NULL, &fds, NULL, NULL);
424 } else {
425 /* make a copy of timeout, because it's value is undefined
426 on return from select() */
427 tv = *timeout;
428 select_ret = select(sockfd+1, NULL, &fds, NULL, &tv);
429 }
430 /* check for error */
431 if (select_ret < 0) {
432 /* log the error and return "timeout" */
433 ER_perror(FAC_SK, SK_SELECT, "(%d) %s", errno, strerror(errno));
434 return -1;
435 }
436 /* check for timeout */
437 if ((select_ret == 0) || !FD_ISSET(sockfd, &fds)) {
438 return -1;
439 }
440
441
442 /* at this point we can safely write */
443 write_ret = write(sockfd, buf, count - *count_sent);
444
445 /* if write failed, assume other side disconnected */
446 if (write_ret <= 0) {
447 return 0;
448 }
449
450 /* update our current status */
451 *count_sent += write_ret;
452 buf += write_ret;
453
454 }
455
456 /* all bytes sent, return success */
457 return 1;
458 } /* SK_write() */
459
460
461 /* SK_gets() */
462 /*++++++++++++++++++++++++++++++++++++++
463
464 This function reads from a socket, until it recieves a linefeed
465 character. It fills the buffer "str" up to the maximum size "count".
466
467 int SK_gets Returns the total_count of bytes read.
468
469 int sockfd The socket file descriptor.
470
471 char *str The buffer to be written from the socket.
472
473 size_t count The number of bytes in the buffer.
474
475
476 Authors:
477 ottrey,
478 marek (modified for meaningful error codes).
479
480 Side Effects:
481 This function will return -1 if the socket is closed during the read operation.
482
483 Note that if a single line exceeds the length of count, the extra data
484 will be read and discarded! You have been warned.
485
486 ++++++++++++++++++++++++++++++++++++++*/
487 int SK_gets(int sockfd, char *str, size_t count) {
/* [<][>][^][v][top][bottom][index][help] */
488 int bytes_read;
489 int total_count = 0;
490 char *current_position;
491 char last_read = 0;
492
493 int control_c = 0;
494
495 current_position = str;
496 while (last_read != 10) {
497
498 bytes_read = read(sockfd, &last_read, 1);
499 if (bytes_read <= 0) {
500 /* The other side may have closed unexpectedly */
501 return SK_DISCONNECT;
502 /* Is this effective on other platforms than linux? */
503 }
504 if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
505 *current_position = last_read;
506 current_position++;
507 total_count++;
508 }
509
510 if (last_read == -1) {
511 bytes_read = read(sockfd, &last_read, 1);
512 if (last_read == -12) {
513 ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c");
514 control_c = 1;
515 ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT");
516 return SK_INTERRUPT;
517 }
518 }
519 }
520 if (count > 0) {
521 *current_position = 0;
522 }
523
524 return total_count;
525
526 } /* SK_gets() */
527
528
529 /* SK_puts() */
530 /*++++++++++++++++++++++++++++++++++++++
531
532 This function writes a character string out to a socket.
533
534 int SK_puts The total_count of bytes written,
535 or -1 on hangup, error, or timeout
536
537 int sockfd The socket file descriptor.
538
539 char *str The buffer to be written from the socket.
540
541 const struct timeval *timeout Maximum time to wait between each
542 write() call, or NULL for "forever".
543
544 ++++++++++++++++++++++++++++++++++++++*/
545 int
546 SK_puts(int sockfd, const char *str, const struct timeval *timeout)
/* [<][>][^][v][top][bottom][index][help] */
547 {
548 int count_sent;
549 if (SK_write(sockfd, str, strlen(str), timeout, &count_sent) <= 0) {
550 return -1;
551 } else {
552 return count_sent;
553 }
554 } /* SK_puts() */
555
556 /* SK_putc() */
557 /*++++++++++++++++++++++++++++++++++++++
558
559 This function writes a single character out to a socket.
560
561 int SK_putc Returns the number of characters written.
562
563 int sockfd socket
564
565 char ch character
566
567 const struct timeval *timeout Maximum time to wait between each
568 write() call, or NULL for "forever".
569
570 ++++++++++++++++++++++++++++++++++++++*/
571 int
572 SK_putc(int sockfd, char ch, const struct timeval *timeout)
/* [<][>][^][v][top][bottom][index][help] */
573 {
574 int count_sent;
575 SK_write(sockfd, &ch, 1, timeout, &count_sent);
576 return count_sent;
577 }/* SK_putc() */
578
579 /*++++++++++++++++++++++++++++++++++++++
580
581 This function reads a single character from a socket.
582
583 returns EOF when no character can be read.
584
585 ++++++++++++++++++++++++++++++++++++++*/
586 int SK_getc(int sockfd) {
/* [<][>][^][v][top][bottom][index][help] */
587 char ch;
588
589 if( read(sockfd, &ch, 1) <= 0 ) {
590 return EOF;
591 }
592 else {
593 return ch;
594 }
595 }/* SK_getc() */
596
597 /* SK_getpeername() */
598 /*++++++++++++++++++++++++++++++++++++++
599
600 This function will tell you who is at the other end of a connected stream socket.
601
602 char *SK_getpeername Returns allocated string with the IP in it,
603 or "--" if the descriptor is not a socket,
604 or NULL on error.
605
606 int sockfd The socket or file descriptor.
607
608 +html+ <PRE>
609 Authors:
610 ottrey,
611 marek (modified error handling, made MT-Safe).
612 +html+ </PRE>
613
614 ++++++++++++++++++++++++++++++++++++++*/
615 char *SK_getpeername(int sockfd)
/* [<][>][^][v][top][bottom][index][help] */
616 {
617 char *hostaddress=NULL;
618 struct sockaddr_in addr_in;
619 int namelen=sizeof(addr_in);
620
621 if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) == 0) {
622
623 hostaddress = (char *)UT_malloc(INET_ADDRSTRLEN);
624 inet_ntop(AF_INET, &(addr_in.sin_addr), hostaddress, INET_ADDRSTRLEN);
625 }
626 else {
627 int er = errno;
628
629 if( er == ENOTSOCK ) {
630 hostaddress = wr_string("--");
631 }
632 else {
633 /* XXX: hack to avoid crash in the case where peer disconnects */
634 /* To fix this, the socket interface needs to deal with a structure
635 containing not only the file descriptor, but also the address of
636 the host and the peer. Other goodies, like the current time,
637 time of last operation, and last errno could also be included
638 for good measure. */
639 hostaddress = UT_strdup("127.0.0.1");
640 }
641 }
642
643 return hostaddress;
644
645 } /* SK_getpeername() */
646
647
648 /* SK_getpeerip */
649 /*++++++++++++++++++++++++++++++++++++++
650
651 This function will check the ip of the connected peer and store it in the
652 ip_addr_t structure defined in the IP module.
653
654 int SK_getpeerip returns 0 on success, -1 on failure.
655
656 int sockfd The socket descriptor (file will result in -1)
657
658 ip_addr_t *ip Pointer to where the address should be stored.
659
660 +html+ <PRE>
661 Author:
662 marek
663 +html+ </PRE>
664 ++++++++++++++++++++++++++++++++++++++*/
665
666 int SK_getpeerip(int sockfd, ip_addr_t *ip) {
/* [<][>][^][v][top][bottom][index][help] */
667 struct sockaddr_in addr_in;
668 int namelen=sizeof(addr_in);
669 int ret=-1;
670
671 memset(& addr_in, 0, sizeof(struct sockaddr_in));
672
673 if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) {
674 ret=0;
675 IP_addr_s2b(ip, &addr_in, namelen);
676 } else {
677 /* XXX: hack to avoid crash in the case where peer disconnects */
678 /* To fix this, the socket interface needs to deal with a structure
679 containing not only the file descriptor, but also the address of
680 the host and the peer. Other goodies, like the current time,
681 time of last operation, and last errno could also be included
682 for good measure. */
683 ret = 0;
684 addr_in.sin_family = AF_INET;
685 addr_in.sin_addr.s_addr = INADDR_LOOPBACK;
686 addr_in.sin_port = 0;
687 IP_addr_s2b(ip, &addr_in, namelen);
688 }
689
690 return ret;
691 }
692