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) {
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) {
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,
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) {
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)
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) {
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,
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) {
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)
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)
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) {
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)
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) {
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 |