f3b05d22d288aae2f1f240ac4db4bef6e6652c1e
[project/unetd.git] / main.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
4 */
5 #define _GNU_SOURCE
6 #include <unistd.h>
7 #include <arpa/inet.h>
8 #include <libubox/uloop.h>
9 #include <libubox/blobmsg_json.h>
10 #include "unetd.h"
11
12 struct cmdline_network {
13 struct cmdline_network *next;
14 char *data;
15 };
16
17 static struct cmdline_network *cmd_nets;
18 static const char *hosts_file;
19 const char *mssfix_path = UNETD_MSS_BPF_PATH;
20 const char *data_dir = UNETD_DATA_DIR;
21 bool debug;
22
23 static void
24 network_write_hosts(struct network *net, FILE *f)
25 {
26 struct network_host *host;
27 char ip[INET6_ADDRSTRLEN];
28
29 if (!net->net_config.local_host)
30 return;
31
32 avl_for_each_element(&net->hosts, host, node) {
33 inet_ntop(AF_INET6, &host->peer.local_addr, ip, sizeof(ip));
34 fprintf(f, "%s\t%s\n", ip, network_host_name(host));
35 }
36 }
37
38 void unetd_write_hosts(void)
39 {
40 struct network *net;
41 char *tmpfile = NULL;
42 FILE *f;
43 int fd;
44
45 if (!hosts_file)
46 return;
47
48 asprintf(&tmpfile, "%s.XXXXXXXX", hosts_file);
49 fd = mkstemp(tmpfile);
50 if (fd < 0) {
51 perror("mkstemp");
52 goto out;
53 }
54
55 chmod(tmpfile, 0644);
56 f = fdopen(fd, "w");
57 if (!f) {
58 close(fd);
59 goto out;
60 }
61
62 avl_for_each_element(&networks, net, node)
63 network_write_hosts(net, f);
64
65 fclose(f);
66
67 if (rename(tmpfile, hosts_file))
68 unlink(tmpfile);
69
70 out:
71 free(tmpfile);
72 }
73
74 static void add_networks(void)
75 {
76 struct cmdline_network *net;
77 static struct blob_buf b;
78 struct blob_attr *name;
79
80 for (net = cmd_nets; net; net = net->next) {
81 blob_buf_init(&b, 0);
82 if (!blobmsg_add_json_from_string(&b, net->data))
83 continue;
84
85 blobmsg_parse(&network_policy[NETWORK_ATTR_NAME], 1, &name,
86 blobmsg_data(b.head), blobmsg_len(b.head));
87 if (!name)
88 continue;
89
90 unetd_network_add(blobmsg_get_string(name), b.head);
91 }
92
93 blob_buf_free(&b);
94 }
95
96 int main(int argc, char **argv)
97 {
98 struct cmdline_network *net;
99 int ch;
100
101 while ((ch = getopt(argc, argv, "D:dh:M:N:")) != -1) {
102 switch (ch) {
103 case 'D':
104 data_dir = optarg;
105 break;
106 case 'd':
107 debug = true;
108 break;
109 case 'h':
110 hosts_file = optarg;
111 break;
112 case 'N':
113 net = calloc(1, sizeof(*net));
114 net->next = cmd_nets;
115 net->data = optarg;
116 cmd_nets = net;
117 break;
118 case 'M':
119 mssfix_path = optarg;
120 break;
121 }
122 }
123
124 uloop_init();
125 unetd_ubus_init();
126 unetd_write_hosts();
127 add_networks();
128 uloop_run();
129 network_free_all();
130 uloop_done();
131
132 return 0;
133 }