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