1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "alloc-util.h"
4 #include "string-table.h"
5 #include "timesyncd-server.h"
6 
7 static const char * const server_type_table[_SERVER_TYPE_MAX] = {
8         [SERVER_SYSTEM]   = "system",
9         [SERVER_FALLBACK] = "fallback",
10         [SERVER_LINK]     = "link",
11         [SERVER_RUNTIME]  = "runtime",
12 };
13 
14 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(server_type, ServerType);
15 
server_address_new(ServerName * n,ServerAddress ** ret,const union sockaddr_union * sockaddr,socklen_t socklen)16 int server_address_new(
17                 ServerName *n,
18                 ServerAddress **ret,
19                 const union sockaddr_union *sockaddr,
20                 socklen_t socklen) {
21 
22         ServerAddress *a, *tail;
23 
24         assert(n);
25         assert(sockaddr);
26         assert(socklen >= offsetof(struct sockaddr, sa_data));
27         assert(socklen <= sizeof(union sockaddr_union));
28 
29         a = new(ServerAddress, 1);
30         if (!a)
31                 return -ENOMEM;
32 
33         *a = (ServerAddress) {
34                 .name = n,
35                 .socklen = socklen,
36         };
37 
38         memcpy(&a->sockaddr, sockaddr, socklen);
39 
40         LIST_FIND_TAIL(addresses, n->addresses, tail);
41         LIST_INSERT_AFTER(addresses, n->addresses, tail, a);
42 
43         if (ret)
44                 *ret = a;
45 
46         return 0;
47 }
48 
server_address_free(ServerAddress * a)49 ServerAddress* server_address_free(ServerAddress *a) {
50         if (!a)
51                 return NULL;
52 
53         if (a->name) {
54                 LIST_REMOVE(addresses, a->name->addresses, a);
55 
56                 if (a->name->manager && a->name->manager->current_server_address == a)
57                         manager_set_server_address(a->name->manager, NULL);
58         }
59 
60         return mfree(a);
61 }
62 
server_name_new(Manager * m,ServerName ** ret,ServerType type,const char * string)63 int server_name_new(
64                 Manager *m,
65                 ServerName **ret,
66                 ServerType type,
67                 const char *string) {
68 
69         ServerName *n;
70 
71         assert(m);
72         assert(string);
73 
74         n = new(ServerName, 1);
75         if (!n)
76                 return -ENOMEM;
77 
78         *n = (ServerName) {
79                 .manager = m,
80                 .type = type,
81                 .string = strdup(string),
82         };
83 
84         if (!n->string) {
85                 free(n);
86                 return -ENOMEM;
87         }
88 
89         switch (type) {
90         case SERVER_SYSTEM:
91                 LIST_APPEND(names, m->system_servers, n);
92                 break;
93         case SERVER_LINK:
94                 LIST_APPEND(names, m->link_servers, n);
95                 break;
96         case SERVER_FALLBACK:
97                 LIST_APPEND(names, m->fallback_servers, n);
98                 break;
99         case SERVER_RUNTIME:
100                 LIST_APPEND(names, m->runtime_servers, n);
101                 break;
102         default:
103                 assert_not_reached();
104         }
105 
106         if (type != SERVER_FALLBACK &&
107             m->current_server_name &&
108             m->current_server_name->type == SERVER_FALLBACK)
109                 manager_set_server_name(m, NULL);
110 
111         log_debug("Added new %s server %s.", server_type_to_string(type), string);
112 
113         if (ret)
114                 *ret = n;
115 
116         return 0;
117 }
118 
server_name_free(ServerName * n)119 ServerName *server_name_free(ServerName *n) {
120         if (!n)
121                 return NULL;
122 
123         server_name_flush_addresses(n);
124 
125         if (n->manager) {
126                 if (n->type == SERVER_SYSTEM)
127                         LIST_REMOVE(names, n->manager->system_servers, n);
128                 else if (n->type == SERVER_LINK)
129                         LIST_REMOVE(names, n->manager->link_servers, n);
130                 else if (n->type == SERVER_FALLBACK)
131                         LIST_REMOVE(names, n->manager->fallback_servers, n);
132                 else if (n->type == SERVER_RUNTIME)
133                         LIST_REMOVE(names, n->manager->runtime_servers, n);
134                 else
135                         assert_not_reached();
136 
137                 if (n->manager->current_server_name == n)
138                         manager_set_server_name(n->manager, NULL);
139         }
140 
141         log_debug("Removed server %s.", n->string);
142 
143         free(n->string);
144         return mfree(n);
145 }
146 
server_name_flush_addresses(ServerName * n)147 void server_name_flush_addresses(ServerName *n) {
148         assert(n);
149 
150         while (n->addresses)
151                 server_address_free(n->addresses);
152 }
153