4383a271acc316b3a8b4252778fa6b100a67d6c3
[rahunas] / src / rh-serviceclass.c
1 /**
2  * RahuNAS service class
3  * Author: Neutron Soutmun <neo.neutron@gmail.com>
4  * Date:   2009-03-24
5  */
6 #include <stdio.h>
7 #include <arpa/inet.h>
8 #include "rahunasd.h"
9 #include "rh-serviceclass.h"
10 #include "rh-utils.h"
11 #include "rh-ipset.h"
12
13 int serviceclass_do_init (struct main_server *ms, struct serviceclass *sc);
14
15 struct serviceclass *serviceclass_exists(GList *serviceclass_list,
16                                          int serviceclass_id,
17                                          const char *serviceclass_name)
18 {
19   GList *runner = g_list_first(serviceclass_list);
20   struct serviceclass *lserviceclass = NULL;
21
22   while (runner != NULL) {
23     lserviceclass = (struct serviceclass *)runner->data;
24
25     if (lserviceclass->serviceclass_config->serviceclass_id == serviceclass_id)
26       return lserviceclass;
27
28     if (strcmp(lserviceclass->serviceclass_config->serviceclass_name,
29         serviceclass_name) == 0)
30       return lserviceclass;
31
32     runner = g_list_next(runner);
33   }
34   return NULL;
35 }
36
37 struct servicclass *serviceclass_get_by_id(struct main_server *ms,
38                                            int search_id)
39 {
40   GList *runner = g_list_first(ms->serviceclass_list);
41   struct serviceclass *lserviceclass = NULL;
42
43   while (runner != NULL) {
44     lserviceclass = (struct serviceclass *)runner->data;
45
46     if (lserviceclass->serviceclass_config->serviceclass_id == search_id) {
47       return lserviceclass;
48     }
49
50     runner = g_list_next(runner);
51   }
52   return NULL;
53 }
54
55 int serviceclass_cleanup(struct serviceclass *sc)
56 {
57   if (sc == NULL)
58     return 0;
59
60   if (sc->serviceclass_config != NULL)
61     cleanup_serviceclass_config(sc->serviceclass_config);
62
63   return 0;
64 }
65
66 int register_serviceclass(struct main_server *ms,
67                           const char *serviceclass_cfg_file)
68 {
69   GList *serviceclass_list = ms->serviceclass_list;
70   GList *chk = NULL;
71   GList *node = NULL;
72   FILE  *cfg_file = NULL;
73   union rahunas_config *cfg_get = NULL;
74   struct rahunas_serviceclass_config *serviceclass_config = NULL;
75   struct serviceclass *new_serviceclass = NULL;
76   struct serviceclass *old_serviceclass = NULL;
77
78   union rahunas_config config = {
79     .rh_serviceclass.serviceclass_name = NULL,
80     .rh_serviceclass.serviceclass_id = 1,
81     .rh_serviceclass.description  = NULL,
82     .rh_serviceclass.network      = NULL,
83     .rh_serviceclass.network_size = 0,
84     .rh_serviceclass.fake_arpd    = NULL,
85     .rh_serviceclass.fake_arpd_iface = NULL,
86     .rh_serviceclass.init_flag    = 0
87   };
88
89   cfg_file = fopen(serviceclass_cfg_file, "r");
90   if (cfg_file == NULL)
91     return -1;
92
93   if (get_config(serviceclass_cfg_file, &config) == 0) {
94     old_serviceclass = serviceclass_exists(serviceclass_list,
95                                       config.rh_serviceclass.serviceclass_id,
96                                       config.rh_serviceclass.serviceclass_name);
97
98     if (old_serviceclass != NULL) {
99       if (old_serviceclass->dummy_config != NULL) {
100         DP("Cleanup old dummy config");
101         rh_free(&old_serviceclass->dummy_config);
102       }
103
104       old_serviceclass->dummy_config =
105         (struct rahunas_serviceclass_config *) rh_malloc(sizeof(struct rahunas_serviceclass_config));
106
107       if (old_serviceclass->dummy_config == NULL)
108         return -1;
109
110       memset(old_serviceclass->dummy_config, 0,
111         sizeof(struct rahunas_serviceclass_config));
112       memcpy(old_serviceclass->dummy_config, &config,
113         sizeof(struct rahunas_serviceclass_config));
114
115       if (strncmp(config.rh_serviceclass.serviceclass_name,
116            old_serviceclass->serviceclass_config->serviceclass_name, 32) != 0) {
117         old_serviceclass->serviceclass_config->init_flag = VS_RESET;
118       } else {
119         old_serviceclass->serviceclass_config->init_flag = VS_RELOAD;
120       }
121       return 1;
122     }
123   } else {
124     return -1;
125   }
126
127   serviceclass_config = (struct rahunas_serviceclass_config *) rh_malloc(sizeof(struct rahunas_serviceclass_config));
128
129   if (serviceclass_config == NULL)
130     return -1;
131
132   memset(serviceclass_config, 0, sizeof(struct rahunas_serviceclass_config));
133
134   memcpy(serviceclass_config, &config, sizeof(struct rahunas_serviceclass_config));
135
136   new_serviceclass = (struct serviceclass *) rh_malloc(sizeof(struct serviceclass));
137
138   if (new_serviceclass == NULL)
139     return -1;
140
141   memset(new_serviceclass, 0, sizeof(struct serviceclass));
142
143   new_serviceclass->serviceclass_config = serviceclass_config;
144
145   new_serviceclass->serviceclass_config->init_flag = VS_INIT;
146   ms->serviceclass_list = g_list_append(ms->serviceclass_list, new_serviceclass);
147   return 0;
148 }
149
150 int unregister_serviceclass(struct main_server *ms, int serviceclass_id)
151 {
152   GList *serviceclass_list = ms->serviceclass_list;
153   GList *runner = g_list_first(serviceclass_list);
154   struct serviceclass *lserviceclass = NULL;
155
156   while (runner != NULL) {
157     lserviceclass = (struct serviceclass *)runner->data;
158     if (lserviceclass->serviceclass_config->serviceclass_id == serviceclass_id) {
159       serviceclass_cleanup(lserviceclass);
160
161       ms->serviceclass_list = g_list_delete_link(ms->serviceclass_list, runner);
162       break;
163     } else {
164       runner = g_list_next(runner);
165     }
166   }
167   return 0;
168 }
169
170 int unregister_serviceclass_all(struct main_server *ms)
171 {
172   GList *serviceclass_list = ms->serviceclass_list;
173   GList *runner = g_list_first(serviceclass_list);
174   GList *deleting = NULL;
175   struct serviceclass *lserviceclass = NULL;
176
177   while (runner != NULL) {
178     lserviceclass = (struct serviceclass *)runner->data;
179     serviceclass_cleanup(lserviceclass);
180     deleting = runner;
181     runner = g_list_next(runner);
182
183     cleanup_serviceclass_config(lserviceclass->serviceclass_config);
184     ms->serviceclass_list = g_list_delete_link(ms->serviceclass_list, deleting);
185   }
186
187   return 0;
188 }
189
190 int walk_through_serviceclass(int (*callback)(void *, void *), struct main_server *ms)
191 {
192   GList *serviceclass_list = ms->serviceclass_list;
193   GList *runner = g_list_first(serviceclass_list);
194   struct serviceclass *sc = NULL;
195
196   while (runner != NULL) {
197     sc = (struct serviceclass *)runner->data;
198
199     (*callback)(ms, sc);
200
201     runner = g_list_next(runner);
202   }
203
204   return 0;
205 }
206
207 void serviceclass_init(struct main_server *ms, struct serviceclass *sc)
208 {
209   struct rahunas_serviceclass_config *sc_config = NULL;
210
211   if (ms == NULL || sc == NULL)
212     return;
213
214   sc_config = sc->serviceclass_config;
215   logmsg (RH_LOG_NORMAL, "[%s] Service class init", sc_config->serviceclass_name);
216
217   serviceclass_do_init (ms, sc);
218
219   sc_config->init_flag = SC_DONE;
220   DP("Service Class (%s) - Configured", sc->serviceclass_config->serviceclass_name);
221 }
222
223 void serviceclass_reload(struct main_server *ms, struct serviceclass *sc)
224 {
225   if (sc->serviceclass_config->init_flag == SC_DONE) {
226     sc->serviceclass_config->init_flag = SC_NONE;
227     return;
228   }
229
230   while (sc->serviceclass_config->init_flag != SC_DONE) {
231     if (sc->serviceclass_config->init_flag == SC_INIT) {
232       logmsg(RH_LOG_NORMAL, "[%s] - Service class config init",
233              sc->serviceclass_config->serviceclass_name);
234
235       serviceclass_do_init (ms, sc);
236
237       sc->serviceclass_config->init_flag = SC_DONE;
238     } else if (sc->serviceclass_config->init_flag == SC_RELOAD) {
239       logmsg(RH_LOG_NORMAL, "[%s] - Service class config reload",
240              sc->serviceclass_config->serviceclass_name);
241
242       if (sc->dummy_config != NULL) {
243         cleanup_serviceclass_config(sc->serviceclass_config);
244         memcpy(sc->serviceclass_config, sc->dummy_config,
245           sizeof(struct rahunas_serviceclass_config));
246       }
247
248       serviceclass_do_init (ms, sc);
249
250       sc->serviceclass_config->init_flag = SC_DONE;
251     } else if (sc->serviceclass_config->init_flag == SC_RESET) {
252       logmsg(RH_LOG_NORMAL, "[%s] - Service class config reset",
253              sc->serviceclass_config->serviceclass_name);
254
255       if (sc->dummy_config != NULL) {
256         cleanup_serviceclass_config(sc->serviceclass_config);
257         memcpy(sc->serviceclass_config, sc->dummy_config,
258           sizeof(struct rahunas_serviceclass_config));
259         rh_free(&sc->dummy_config);
260       }
261
262       sc->serviceclass_config->init_flag = SC_INIT;
263     } else {
264       /* Prevent infinite loop */
265       sc->serviceclass_config->init_flag = SC_DONE;
266     }
267   }
268 }
269
270
271 void serviceclass_unused_cleanup(struct main_server *ms)
272 {
273   GList *serviceclass_list = ms->serviceclass_list;
274   GList *runner = g_list_first(serviceclass_list);
275   struct serviceclass *lserviceclass = NULL;
276
277   while (runner != NULL) {
278     lserviceclass = (struct serviceclass *)runner->data;
279     if (lserviceclass->serviceclass_config->init_flag == SC_NONE) {
280       logmsg(RH_LOG_NORMAL, "[%s] - Service class config removed",
281              lserviceclass->serviceclass_config->serviceclass_name);
282       unregister_serviceclass(ms, lserviceclass->serviceclass_config->serviceclass_id);
283
284       // Set runner to the first of list due to unregister may delete head
285       runner = g_list_first(ms->serviceclass_list);
286     } else {
287       runner = g_list_next(runner);
288     }
289   }
290 }
291
292 int serviceclass_do_init (struct main_server *ms, struct serviceclass *sc)
293 {
294   struct rahunas_serviceclass_config *sc_config = sc->serviceclass_config;
295
296   logmsg (RH_LOG_NORMAL, "[%s] Mapping network: %s",
297                          sc_config->serviceclass_name,
298                          sc_config->network);
299   if (sc_config->fake_arpd != NULL) {
300     if ((strncasecmp (sc_config->fake_arpd, "yes", strlen ("yes")) == 0) &&
301         (sc_config->fake_arpd_iface != NULL)) {
302       logmsg(RH_LOG_NORMAL, "[%s] Fake-arpd: Enabled (on %s)",
303                             sc_config->serviceclass_name,
304                             sc_config->fake_arpd_iface);
305     } else {
306       logmsg(RH_LOG_NORMAL, "[%s] Fake-arpd: Disabled",
307                             sc_config->serviceclass_name);
308     }
309   }
310 }