* Fix a slight bug in the state-machine. This caused the client end of a
[openssl.git] / demos / tunala / ip.c
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 unsigned 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, &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 unsigned 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, &in_addr, sizeof(struct sockaddr_in)) != 0) &&
69                         (errno != EINPROGRESS))
70                 goto err;
71         return fd;
72 err:
73         if(fd != -1)
74                 close(fd);
75         return -1;
76 }
77
78 static unsigned char all_local_ip[] = {0x00,0x00,0x00,0x00};
79
80 int ip_parse_address(const char *address, unsigned char **parsed_ip,
81                 unsigned short *parsed_port, int accept_all_ip)
82 {
83         char buf[256];
84         struct hostent *lookup;
85         unsigned long port;
86         char *temp;
87         const char *ptr = strstr(address, ":");
88         unsigned 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         port = strtoul(ptr, &temp, 10);
114         if((temp == ptr) || (*temp != '\0') || (port > 65535))
115                 return 0;
116         *parsed_ip = ip;
117         *parsed_port = (unsigned short)port;
118         return 1;
119 }
120
121 int ip_create_listener(const char *address)
122 {
123         unsigned char *ip;
124         unsigned short port;
125
126         if(!ip_parse_address(address, &ip, &port, 1))
127                 return -1;
128         return ip_create_listener_split(ip, port);
129 }
130
131 int ip_create_connection(const char *address)
132 {
133         unsigned char *ip;
134         unsigned short port;
135
136         if(!ip_parse_address(address, &ip, &port, 0))
137                 return -1;
138         return ip_create_connection_split(ip, port);
139 }
140
141 int ip_accept_connection(int listen_fd)
142 {
143         return accept(listen_fd, NULL, NULL);
144 }
145
146 #endif /* !defined(NO_IP) */
147