1 /*
2 * Copyright (c) 2009, 2012 by Farsight Security, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* Import. */
18
19 #include "private.h"
20
21 /* Macros. */
22
23 #define ALIAS_FILE_OPERATOR NMSG_ETCDIR "/nmsg.opalias"
24 #define ALIAS_FILE_GROUP NMSG_ETCDIR "/nmsg.gralias"
25
26 #define ALIAS_SZ_INIT 16
27 #define MAX_LINE_SZ 1024
28
29 struct nmsg_alias {
30 size_t max_idx;
31 char **value;
32 };
33
34 static int nmsg_alias_initialized = 0;
35 static struct nmsg_alias alias_operator;
36 static struct nmsg_alias alias_group;
37
38 /* Forward. */
39
40 static nmsg_res alias_init(struct nmsg_alias *, const char *fname);
41 static nmsg_res alias_resize(struct nmsg_alias *, unsigned n);
42 static void alias_free(struct nmsg_alias *);
43
44 /* Functions. */
45
46 const char *
nmsg_alias_by_key(nmsg_alias_e ae,unsigned key)47 nmsg_alias_by_key(nmsg_alias_e ae, unsigned key) {
48 struct nmsg_alias *al = NULL;
49
50 if (ae == nmsg_alias_operator)
51 al = &alias_operator;
52 else if (ae == nmsg_alias_group)
53 al = &alias_group;
54
55 assert(al != NULL);
56
57 if (key <= al->max_idx)
58 return (al->value[key]);
59
60 return (NULL);
61 }
62
63 unsigned
nmsg_alias_by_value(nmsg_alias_e ae,const char * value)64 nmsg_alias_by_value(nmsg_alias_e ae, const char *value) {
65 struct nmsg_alias *al = NULL;
66
67 if (ae == nmsg_alias_operator)
68 al = &alias_operator;
69 else if (ae == nmsg_alias_group)
70 al = &alias_group;
71
72 assert(al != NULL);
73
74 for (unsigned i = 0; i <= al->max_idx; i++)
75 if (al->value[i] != NULL &&
76 strcasecmp(value, al->value[i]) == 0)
77 return (i);
78
79 return (0);
80 }
81
82 nmsg_res
_nmsg_alias_init(void)83 _nmsg_alias_init(void) {
84
85 if (nmsg_alias_initialized == 0) {
86 nmsg_res res = nmsg_res_failure;
87 char *envfile;
88
89 envfile = getenv("NMSG_OPALIAS_FILE");
90 if (envfile)
91 res = alias_init(&alias_operator, envfile);
92
93 if (res != nmsg_res_success)
94 res = alias_init(&alias_operator, ALIAS_FILE_OPERATOR);
95
96 if (res != nmsg_res_success)
97 return (res);
98
99 res = nmsg_res_failure;
100 envfile = getenv("NMSG_GRALIAS_FILE");
101 if (envfile)
102 res = alias_init(&alias_group, envfile);
103
104 if (res != nmsg_res_success)
105 res = alias_init(&alias_group, ALIAS_FILE_GROUP);
106
107 if (res != nmsg_res_success)
108 return (res);
109
110 nmsg_alias_initialized = 1;
111 }
112
113 return (nmsg_res_success);
114 }
115
116 void
_nmsg_alias_fini(void)117 _nmsg_alias_fini(void) {
118 if (nmsg_alias_initialized == 1) {
119 alias_free(&alias_operator);
120 alias_free(&alias_group);
121 nmsg_alias_initialized = 0;
122 }
123 }
124
125 /* Private. */
126
127 static nmsg_res
alias_init(struct nmsg_alias * al,const char * fname)128 alias_init(struct nmsg_alias *al, const char *fname) {
129 FILE *fp;
130 char line[MAX_LINE_SZ];
131 char *saveptr, *str_key, *str_value;
132 char *t;
133 unsigned key;
134 nmsg_res res;
135
136 res = nmsg_res_success;
137
138 al->value = malloc(sizeof(*(al->value)) * (ALIAS_SZ_INIT + 1));
139 if (al->value == NULL)
140 return (nmsg_res_failure);
141 al->max_idx = ALIAS_SZ_INIT;
142 for (unsigned i = 0; i <= al->max_idx; i++)
143 al->value[i] = NULL;
144
145 fp = fopen(fname, "r");
146 if (fp == NULL)
147 /* file may not exist */
148 return (nmsg_res_success);
149
150 while (fgets(line, sizeof(line), fp) != NULL) {
151 str_key = strtok_r(line, " \t", &saveptr);
152 str_value = strtok_r(NULL, " \t\n", &saveptr);
153 if (str_key == NULL || str_value == NULL) {
154 res = nmsg_res_failure;
155 break;
156 }
157
158 key = (unsigned) strtoul(str_key, &t, 0);
159 if (*t != '\0') {
160 res = nmsg_res_failure;
161 break;
162 }
163
164 if (key > al->max_idx) {
165 if (alias_resize(al, key) != nmsg_res_success) {
166 res = nmsg_res_failure;
167 break;
168 }
169 }
170
171 al->value[key] = strdup(str_value);
172 }
173
174 fclose(fp);
175 return (res);
176 }
177
178 static nmsg_res
alias_resize(struct nmsg_alias * al,unsigned n)179 alias_resize(struct nmsg_alias *al, unsigned n) {
180 unsigned max_idx;
181 void *tmp;
182
183 n += 1;
184
185 if (n > al->max_idx) {
186 max_idx = al->max_idx * 2;
187 if (n > max_idx)
188 max_idx = n + 1;
189
190 tmp = al->value;
191 al->value = realloc(al->value, (max_idx + 1) * sizeof(*(al->value)));
192 if (al->value == NULL) {
193 free(tmp);
194 al->max_idx = 0;
195 return (nmsg_res_failure);
196 }
197 for (unsigned i = al->max_idx + 1; i <= max_idx; i++)
198 al->value[i] = NULL;
199 al->max_idx = max_idx;
200 }
201 return (nmsg_res_success);
202 }
203
204 static void
alias_free(struct nmsg_alias * al)205 alias_free(struct nmsg_alias *al) {
206 for (unsigned i = 0; i <= al->max_idx; i++)
207 if (al->value[i] != NULL)
208 free(al->value[i]);
209 free(al->value);
210 al->value = NULL;
211 al->max_idx = 0;
212 }
213