1 /*
2  * Copyright (c) 2014 Brian Swetland
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 
29 #include "network.h"
30 
lookup_hostname(const char * hostname)31 in_addr_t lookup_hostname(const char *hostname)
32 {
33     int err;
34     struct addrinfo *info, *temp;
35     in_addr_t addr = 0;
36 
37     struct addrinfo hints;
38     memset(&hints, 0, sizeof(hints));
39     hints.ai_family = AF_INET;
40     hints.ai_socktype = SOCK_STREAM;
41 
42     err = getaddrinfo(hostname, NULL, &hints, &info);
43     if (err < 0) {
44         printf("getaddrinfo() returns %d, error '%s'\n", err, gai_strerror(err));
45         return 0;
46     }
47 
48     for (temp = info; temp; temp = temp->ai_next) {
49 //      printf("flags 0x%x, family %d, socktype %d, protocol %d, addrlen %d\n",
50 //          temp->ai_flags, temp->ai_family, temp->ai_socktype, temp->ai_protocol, temp->ai_addrlen);
51 
52         if (temp->ai_family == AF_INET && temp->ai_protocol == IPPROTO_TCP) {
53             struct sockaddr_in *sa = (struct sockaddr_in *)temp->ai_addr;
54 //          printf("port %d, addr 0x%x\n", sa->sin_port, sa->sin_addr.s_addr);
55             addr = sa->sin_addr.s_addr;
56         }
57     }
58 
59     freeaddrinfo(info);
60 
61     return addr;
62 }
63 
inet_listen(in_addr_t addr,int type,unsigned port,int shared)64 static int inet_listen(in_addr_t addr, int type, unsigned port, int shared)
65 {
66     struct sockaddr_in sa;
67     int s;
68     if ((s = socket(AF_INET, type, 0)) < 0) {
69         return -1;
70     }
71     if (shared) {
72         int opt = 1;
73         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
74         //setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
75     }
76     memset(&sa, 0, sizeof(sa));
77     sa.sin_family = AF_INET;
78     sa.sin_port = htons(port);
79     sa.sin_addr.s_addr = addr;
80     if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
81         close(s);
82         return -1;
83     }
84     return s;
85 }
86 
inet_connect(in_addr_t addr,int type,unsigned port)87 static int inet_connect(in_addr_t addr, int type, unsigned port)
88 {
89     struct sockaddr_in sa;
90     int s;
91     if ((s = socket(AF_INET, type, 0)) < 0) {
92         return -1;
93     }
94     if (addr == 0xFFFFFFFF) {
95         int opt = 1;
96         setsockopt(s, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
97     }
98     memset(&sa, 0, sizeof(sa));
99     sa.sin_family = AF_INET;
100     sa.sin_port = htons(port);
101     sa.sin_addr.s_addr = addr;
102     if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
103         close(s);
104         return -1;
105     }
106     return s;
107 }
108 
udp_listen(in_addr_t addr,unsigned port,int shared)109 int udp_listen(in_addr_t addr, unsigned port, int shared)
110 {
111     return inet_listen(addr, SOCK_DGRAM, port, shared);
112 }
113 
udp_connect(in_addr_t addr,unsigned port)114 int udp_connect(in_addr_t addr, unsigned port)
115 {
116     return inet_connect(addr, SOCK_DGRAM, port);
117 }
118 
tcp_listen(in_addr_t addr,unsigned port)119 int tcp_listen(in_addr_t addr, unsigned port)
120 {
121     return inet_listen(addr, SOCK_STREAM, port, 0);
122 }
123 
tcp_connect(in_addr_t addr,unsigned port)124 int tcp_connect(in_addr_t addr, unsigned port)
125 {
126     return inet_connect(addr, SOCK_STREAM, port);
127 }
128