Larry Doolittle writes:
[oweals/busybox.git] / libbb / xconnect.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Connect to host at port using address resolution from getaddrinfo
6  *
7  */
8
9 #include <unistd.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <errno.h>
15 #include <netdb.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include "libbb.h"
20
21 /* Return network byte ordered port number for a service.
22  * If "port" is a number use it as the port.
23  * If "port" is a name it is looked up in /etc/services, if it isnt found return
24  * default_port
25  */
26 unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port)
27 {
28         unsigned short port_nr = htons(default_port);
29         if (port) {
30                 char *endptr;
31                 int old_errno;
32                 long port_long;
33
34                 /* Since this is a lib function, we're not allowed to reset errno to 0.
35                  * Doing so could break an app that is deferring checking of errno. */
36                 old_errno = errno;
37                 errno = 0;
38                 port_long = strtol(port, &endptr, 10);
39                 if (errno != 0 || *endptr!='\0' || endptr==port || port_long < 0 || port_long > 65535) {
40                         struct servent *tserv = getservbyname(port, protocol);
41                         if (tserv) {
42                                 port_nr = tserv->s_port;
43                         }
44                 } else {
45                         port_nr = htons(port_long);
46                 }
47                 errno = old_errno;
48         }
49         return port_nr;
50 }
51
52 void bb_lookup_host(struct sockaddr_in *s_in, const char *host)
53 {
54         struct hostent *he;
55
56         memset(s_in, 0, sizeof(struct sockaddr_in));
57         s_in->sin_family = AF_INET;
58         he = xgethostbyname(host);
59         memcpy(&(s_in->sin_addr), he->h_addr_list[0], he->h_length);
60 }
61
62 int xconnect(struct sockaddr_in *s_addr)
63 {
64         int s = socket(AF_INET, SOCK_STREAM, 0);
65         if (connect(s, (struct sockaddr_in *)s_addr, sizeof(struct sockaddr_in)) < 0)
66         {
67                 bb_perror_msg_and_die("Unable to connect to remote host (%s)",
68                                 inet_ntoa(s_addr->sin_addr));
69         }
70         return s;
71 }