1 /*
2  * Copyright (c) 2014 Brian Swetland
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 
14 #include "network.h"
15 
lookup_hostname(const char * hostname)16 in_addr_t lookup_hostname(const char *hostname) {
17     int err;
18     struct addrinfo *info, *temp;
19     in_addr_t addr = 0;
20 
21     struct addrinfo hints;
22     memset(&hints, 0, sizeof(hints));
23     hints.ai_family = AF_INET;
24     hints.ai_socktype = SOCK_STREAM;
25 
26     err = getaddrinfo(hostname, NULL, &hints, &info);
27     if (err < 0) {
28         printf("getaddrinfo() returns %d, error '%s'\n", err, gai_strerror(err));
29         return 0;
30     }
31 
32     for (temp = info; temp; temp = temp->ai_next) {
33 //      printf("flags 0x%x, family %d, socktype %d, protocol %d, addrlen %d\n",
34 //          temp->ai_flags, temp->ai_family, temp->ai_socktype, temp->ai_protocol, temp->ai_addrlen);
35 
36         if (temp->ai_family == AF_INET && temp->ai_protocol == IPPROTO_TCP) {
37             struct sockaddr_in *sa = (struct sockaddr_in *)temp->ai_addr;
38 //          printf("port %d, addr 0x%x\n", sa->sin_port, sa->sin_addr.s_addr);
39             addr = sa->sin_addr.s_addr;
40         }
41     }
42 
43     freeaddrinfo(info);
44 
45     return addr;
46 }
47 
inet_listen(in_addr_t addr,int type,unsigned port,int shared)48 static int inet_listen(in_addr_t addr, int type, unsigned port, int shared) {
49     struct sockaddr_in sa;
50     int s;
51     if ((s = socket(AF_INET, type, 0)) < 0) {
52         return -1;
53     }
54     if (shared) {
55         int opt = 1;
56         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
57         //setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
58     }
59     memset(&sa, 0, sizeof(sa));
60     sa.sin_family = AF_INET;
61     sa.sin_port = htons(port);
62     sa.sin_addr.s_addr = addr;
63     if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
64         close(s);
65         return -1;
66     }
67     return s;
68 }
69 
inet_connect(in_addr_t addr,int type,unsigned port)70 static int inet_connect(in_addr_t addr, int type, unsigned port) {
71     struct sockaddr_in sa;
72     int s;
73     if ((s = socket(AF_INET, type, 0)) < 0) {
74         return -1;
75     }
76     if (addr == 0xFFFFFFFF) {
77         int opt = 1;
78         setsockopt(s, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
79     }
80     memset(&sa, 0, sizeof(sa));
81     sa.sin_family = AF_INET;
82     sa.sin_port = htons(port);
83     sa.sin_addr.s_addr = addr;
84     if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
85         close(s);
86         return -1;
87     }
88     return s;
89 }
90 
udp_listen(in_addr_t addr,unsigned port,int shared)91 int udp_listen(in_addr_t addr, unsigned port, int shared) {
92     return inet_listen(addr, SOCK_DGRAM, port, shared);
93 }
94 
udp_connect(in_addr_t addr,unsigned port)95 int udp_connect(in_addr_t addr, unsigned port) {
96     return inet_connect(addr, SOCK_DGRAM, port);
97 }
98 
tcp_listen(in_addr_t addr,unsigned port)99 int tcp_listen(in_addr_t addr, unsigned port) {
100     return inet_listen(addr, SOCK_STREAM, port, 0);
101 }
102 
tcp_connect(in_addr_t addr,unsigned port)103 int tcp_connect(in_addr_t addr, unsigned port) {
104     return inet_connect(addr, SOCK_STREAM, port);
105 }
106