1 /*
2  * ZMap Copyright 2013 Regents of the University of Michigan
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy
6  * of the License at http://www.apache.org/licenses/LICENSE-2.0
7  */
8 
9 #include "fieldset.h"
10 
11 #include <string.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 #include <assert.h>
15 
16 #include "../lib/logger.h"
17 #include "../lib/xalloc.h"
18 
gen_fielddef_set(fielddefset_t * fds,fielddef_t fs[],int len)19 void gen_fielddef_set(fielddefset_t *fds, fielddef_t fs[], int len)
20 {
21 	if (fds->len + len > MAX_FIELDS) {
22 		log_fatal("fieldset", "out of room in field def set");
23 	}
24 	fielddef_t *open = &(fds->fielddefs[fds->len]);
25 	memcpy(open, fs, len*sizeof(fielddef_t));
26 	fds->len += len;
27 }
28 
fs_new_fieldset(void)29 fieldset_t *fs_new_fieldset(void)
30 {
31 	fieldset_t *f = xcalloc(1, sizeof(fieldset_t));
32 	return f;
33 }
34 
fs_add_word(fieldset_t * fs,const char * name,int type,int free_,size_t len,field_val_t value)35 static inline void fs_add_word(fieldset_t *fs, const char *name, int type,
36 		int free_, size_t len, field_val_t value)
37 {
38 	if (fs->len + 1 >= MAX_FIELDS) {
39 		log_fatal("fieldset", "out of room in fieldset");
40 	}
41 	field_t *f = &(fs->fields[fs->len]);
42 	fs->len++;
43 	f->type = type;
44 	f->name = name;
45 	f->len = len;
46 	f->value = value;
47 	f->free_ = free_;
48 }
49 
fs_modify_word(fieldset_t * fs,const char * name,int type,int free_,size_t len,field_val_t value)50 static void fs_modify_word(fieldset_t *fs, const char *name, int type,
51 		int free_, size_t len, field_val_t value)
52 {
53 	for (int i=0; i<fs->len; i++) {
54 		if (!strcmp(fs->fields[i].name, name)) {
55 			if (fs->fields[i].free_) {
56 				free(fs->fields[i].value.ptr);
57 				fs->fields[i].value.ptr = NULL;
58 			}
59 			fs->fields[i].type = type;
60 			fs->fields[i].free_ = free_;
61 			fs->fields[i].len = len;
62 			fs->fields[i].value = value;
63 			return;
64 		}
65 	}
66 	fs_add_word(fs, name, type, free_, len, value);
67 }
68 
fs_add_null(fieldset_t * fs,const char * name)69 void fs_add_null(fieldset_t *fs, const char *name)
70 {
71 	field_val_t val = { .ptr = NULL };
72 	fs_add_word(fs, name, FS_NULL, 0, 0, val);
73 }
74 
fs_add_string(fieldset_t * fs,const char * name,char * value,int free_)75 void fs_add_string(fieldset_t *fs, const char *name, char *value, int free_)
76 {
77 	field_val_t val = { .ptr = value };
78 	fs_add_word(fs, name, FS_STRING, free_, strlen(value), val);
79 }
80 
fs_add_uint64(fieldset_t * fs,const char * name,uint64_t value)81 void fs_add_uint64(fieldset_t *fs, const char *name, uint64_t value)
82 {
83 	field_val_t val = { .num = value };
84 	fs_add_word(fs, name, FS_UINT64, 0, sizeof(uint64_t), val);
85 }
86 
fs_add_binary(fieldset_t * fs,const char * name,size_t len,void * value,int free_)87 void fs_add_binary(fieldset_t *fs, const char *name, size_t len,
88 		void *value, int free_)
89 {
90 	field_val_t val = { .ptr = value };
91 	fs_add_word(fs, name, FS_BINARY, free_, len, val);
92 }
93 
94 // Modify
fs_modify_null(fieldset_t * fs,const char * name)95 void fs_modify_null(fieldset_t *fs, const char *name)
96 {
97 	field_val_t val = { .ptr = NULL };
98 	fs_modify_word(fs, name, FS_NULL, 0, 0, val);
99 }
100 
fs_modify_string(fieldset_t * fs,const char * name,char * value,int free_)101 void fs_modify_string(fieldset_t *fs, const char *name, char *value, int free_)
102 {
103 	field_val_t val = { .ptr = value };
104 	fs_modify_word(fs, name, FS_STRING, free_, strlen(value), val);
105 }
106 
fs_modify_uint64(fieldset_t * fs,const char * name,uint64_t value)107 void fs_modify_uint64(fieldset_t *fs, const char *name, uint64_t value)
108 {
109 	field_val_t val = { .num = value };
110 	fs_modify_word(fs, name, FS_UINT64, 0, sizeof(uint64_t), val);
111 }
112 
fs_modify_binary(fieldset_t * fs,const char * name,size_t len,void * value,int free_)113 void fs_modify_binary(fieldset_t *fs, const char *name, size_t len,
114 		void *value, int free_)
115 {
116 	field_val_t val = { .ptr = value };
117 	fs_modify_word(fs, name, FS_BINARY, free_, len, val);
118 }
119 
fs_get_uint64_by_index(fieldset_t * fs,int index)120 uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index)
121 {
122 	return (uint64_t) fs->fields[index].value.num;
123 }
124 
fs_get_string_by_index(fieldset_t * fs,int index)125 char* fs_get_string_by_index(fieldset_t *fs, int index)
126 {
127 	return (char*) fs->fields[index].value.ptr;
128 }
129 
fds_get_index_by_name(fielddefset_t * fds,char * name)130 int fds_get_index_by_name(fielddefset_t *fds, char *name)
131 {
132 	for (int i=0; i < fds->len; i++) {
133 		if (!strcmp(fds->fielddefs[i].name, name)) {
134 			return i;
135 		}
136 	}
137 	return -1;
138 }
139 
fs_free(fieldset_t * fs)140 void fs_free(fieldset_t *fs)
141 {
142 	if (!fs) {
143 		return;
144 	}
145 	for (int i=0; i < fs->len; i++) {
146 		field_t *f = &(fs->fields[i]);
147 		if (f->free_) {
148 			free(f->value.ptr);
149 		}
150 	}
151 	free(fs);
152 }
153 
fs_generate_fieldset_translation(translation_t * t,fielddefset_t * avail,char ** req,int reqlen)154 void fs_generate_fieldset_translation(translation_t *t,
155 		fielddefset_t *avail, char** req, int reqlen)
156 {
157 	memset(t, 0, sizeof(translation_t));
158 	if (!t) {
159 		log_fatal("fieldset", "unable to allocate memory for translation");
160 	}
161 	for (int i=0; i < reqlen; i++) {
162 		int l = fds_get_index_by_name(avail, req[i]);
163 		if (l < 0) {
164 			log_fatal("fieldset", "specified field (%s) not "
165 					      "available in selected "
166 					      "probe module.", req[i]);
167 		}
168 		t->translation[t->len++] = l;
169 	}
170 }
171 
fs_generate_full_fieldset_translation(translation_t * t,fielddefset_t * avail)172 void fs_generate_full_fieldset_translation(translation_t *t, fielddefset_t *avail)
173 {
174 	memset(t, 0, sizeof(translation_t));
175 	if (!t) {
176 		log_fatal("fieldset", "unable to allocate memory for translation");
177 	}
178 	t->len = avail->len;
179 	for (int i=0; i < avail->len; i++) {
180 		t->translation[i] = i;
181 	}
182 }
183 
translate_fieldset(fieldset_t * fs,translation_t * t)184 fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t)
185 {
186 	fieldset_t *retv = fs_new_fieldset();
187 	if (!retv) {
188 		log_fatal("fieldset", "unable to allocate space for translated field set");
189 	}
190 	for (int i=0; i < t->len; i++) {
191 		int o = t->translation[i];
192 		memcpy(&(retv->fields[i]), &(fs->fields[o]), sizeof(field_t));
193 	}
194 	retv->len = t->len;
195 	return retv;
196 }
197 
198