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