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