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