OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
ip.c
Go to the documentation of this file.
1 #include "tunala.h"
2 
3 #ifndef NO_IP
4 
5 #define IP_LISTENER_BACKLOG 511 /* So if it gets masked by 256 or some other
6  such value it'll still be respectable */
7 
8 /* Any IP-related initialisations. For now, this means blocking SIGPIPE */
9 int ip_initialise(void)
10 {
11  struct sigaction sa;
12 
13  sa.sa_handler = SIG_IGN;
14  sa.sa_flags = 0;
15  sigemptyset(&sa.sa_mask);
16  if(sigaction(SIGPIPE, &sa, NULL) != 0)
17  return 0;
18  return 1;
19 }
20 
21 int ip_create_listener_split(const char *ip, unsigned short port)
22 {
23  struct sockaddr_in in_addr;
24  int fd = -1;
25  int reuseVal = 1;
26 
27  /* Create the socket */
28  if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
29  goto err;
30  /* Set the SO_REUSEADDR flag - servers act weird without it */
31  if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuseVal),
32  sizeof(reuseVal)) != 0)
33  goto err;
34  /* Prepare the listen address stuff */
35  in_addr.sin_family = AF_INET;
36  memcpy(&in_addr.sin_addr.s_addr, ip, 4);
37  in_addr.sin_port = htons(port);
38  /* Bind to the required port/address/interface */
39  if(bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) != 0)
40  goto err;
41  /* Start "listening" */
42  if(listen(fd, IP_LISTENER_BACKLOG) != 0)
43  goto err;
44  return fd;
45 err:
46  if(fd != -1)
47  close(fd);
48  return -1;
49 }
50 
51 int ip_create_connection_split(const char *ip, unsigned short port)
52 {
53  struct sockaddr_in in_addr;
54  int flags, fd = -1;
55 
56  /* Create the socket */
57  if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
58  goto err;
59  /* Make it non-blocking */
60  if(((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
61  (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0))
62  goto err;
63  /* Prepare the connection address stuff */
64  in_addr.sin_family = AF_INET;
65  memcpy(&in_addr.sin_addr.s_addr, ip, 4);
66  in_addr.sin_port = htons(port);
67  /* Start a connect (non-blocking, in all likelihood) */
68  if((connect(fd, (struct sockaddr *)&in_addr,
69  sizeof(struct sockaddr_in)) != 0) &&
70  (errno != EINPROGRESS))
71  goto err;
72  return fd;
73 err:
74  if(fd != -1)
75  close(fd);
76  return -1;
77 }
78 
79 static char all_local_ip[] = {0x00,0x00,0x00,0x00};
80 
81 int ip_parse_address(const char *address, const char **parsed_ip,
82  unsigned short *parsed_port, int accept_all_ip)
83 {
84  char buf[256];
85  struct hostent *lookup;
86  unsigned long port;
87  const char *ptr = strstr(address, ":");
88  const char *ip = all_local_ip;
89 
90  if(!ptr) {
91  /* We assume we're listening on all local interfaces and have
92  * only specified a port. */
93  if(!accept_all_ip)
94  return 0;
95  ptr = address;
96  goto determine_port;
97  }
98  if((ptr - address) > 255)
99  return 0;
100  memset(buf, 0, 256);
101  memcpy(buf, address, ptr - address);
102  ptr++;
103  if((lookup = gethostbyname(buf)) == NULL) {
104  /* Spit a message to differentiate between lookup failures and
105  * bad strings. */
106  fprintf(stderr, "hostname lookup for '%s' failed\n", buf);
107  return 0;
108  }
109  ip = lookup->h_addr_list[0];
110 determine_port:
111  if(strlen(ptr) < 1)
112  return 0;
113  if(!int_strtoul(ptr, &port) || (port > 65535))
114  return 0;
115  *parsed_ip = ip;
116  *parsed_port = (unsigned short)port;
117  return 1;
118 }
120 int ip_create_listener(const char *address)
121 {
122  const char *ip;
123  unsigned short port;
124 
125  if(!ip_parse_address(address, &ip, &port, 1))
126  return -1;
127  return ip_create_listener_split(ip, port);
128 }
130 int ip_create_connection(const char *address)
131 {
132  const char *ip;
133  unsigned short port;
134 
135  if(!ip_parse_address(address, &ip, &port, 0))
136  return -1;
137  return ip_create_connection_split(ip, port);
138 }
140 int ip_accept_connection(int listen_fd)
141 {
142  return accept(listen_fd, NULL, NULL);
143 }
144 
145 #endif /* !defined(NO_IP) */
146