1 /* $Id: dktrace.c,v 1.6 2005/07/14 22:56:25 ted46045 Exp $ */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 // added by nhatier for compilation under MSVC
6 #ifdef _MSC_VER
7 #include <string.h>
8 #define strncasecmp strnicmp
9 #define strcasecmp stricmp
10 #define snprintf _snprintf
11 #else
12 #ifndef _STRINGS_H
13 #include <strings.h>
14 #endif
15 #ifndef _STRING_H
16 #include <string.h>
17 #endif
18 #endif
19 // end added by nhatier
20 #include "dktrace.h"
21
22 //dk_init() is a macro now in dktrace.h
23
24 static int *
getPointer(DK_TRACE * dkp,DK_TRACE_TYPE type)25 getPointer(DK_TRACE *dkp, DK_TRACE_TYPE type)
26 {
27 switch (type) {
28 case DKT_RAW_HEADER: return dkp->ccounts_h;
29 case DKT_CANON_HEADER: return dkp->ccounts_H;
30 case DKT_RAW_BODY: return dkp->ccounts_b;
31 case DKT_CANON_BODY: return dkp->ccounts_B;
32 default: return 0;
33 }
34 }
35
36 //Modified version of dkparselist()
dkt_parselist(char * list,char * letters,char * values[])37 static int dkt_parselist(char *list, char *letters, char *values[])
38 {
39 char key;
40 int i;
41 char *value;
42
43 /* start with all args unset */
44 for (i = 0; letters[i]; i++)
45 {
46 values[i] = NULL;
47 }
48 key = 0;
49 while (*list)
50 {
51 if ((*list == ' ')||(*list == '\t')||(*list == '\r')||(*list == '\n'))
52 {
53 list++;
54 }
55 else if (*list == '=')
56 {
57 char *ws;
58
59 ++list;
60 value = list;
61 ws = list;
62 while (1)
63 {
64 /* copy up to null or semicolon, deleting whitespace as we go */
65 *ws = *list;
66 if ((*list == ' ')||(*list == '\t')||(*list == '\r')||(*list == '\n'))
67 {
68 /* ignore */
69 }
70 else if (!*list)
71 {
72 break;
73 }
74 else if (*list == ';')
75 {
76 *ws = '\0';
77 list++;
78 break;
79 }
80 else
81 {
82 ws++;
83 }
84 list++;
85 }
86 if (!key)
87 {
88 return 0; //No key
89 }
90 /* if we find a matching letter, remember the value */
91 for (i = 0; letters[i]; i++)
92 {
93 if (key == letters[i])
94 {
95 if (values[i])
96 {
97 return 0; /* no duplicate keys. TC23 */
98 }
99 values[i] = value;
100 }
101 }
102 key = 0;
103 }
104 else
105 {
106 if (key)
107 {
108 return 0; /* they already gave us a key. TC24 */
109 }
110 key = *list++;
111 }
112 }
113 return 1;
114 }
115
116 extern void
dkt_add(DK_TRACE * dkp,DK_TRACE_TYPE type,const unsigned char * data,int dataLength)117 dkt_add(DK_TRACE *dkp, DK_TRACE_TYPE type, const unsigned char *data, int dataLength)
118 {
119 int *ip;
120 ip = getPointer(dkp, type);
121 if (!ip) return;
122
123 while (dataLength-- > 0) ip[*data++]++;
124 }
125
126 //useful for building table directly
127 extern void
dkt_quickadd(DK_TRACE * dkp,DK_TRACE_TYPE type,int index,int count)128 dkt_quickadd(DK_TRACE *dkp, DK_TRACE_TYPE type, int index, int count)
129 {
130 int *ip;
131 ip = getPointer(dkp, type);
132 if (!ip) return;
133 if ((index < 256) && (index >= 0))
134 ip[index] = ip[index] + count;
135 }
136
137 //reverse of dkt_quickadd, reads data from table and returns the int count
138 extern int
dkt_getcount(DK_TRACE * dkp,DK_TRACE_TYPE type,int index,int count)139 dkt_getcount(DK_TRACE *dkp, DK_TRACE_TYPE type, int index, int count)
140 {
141 int *ip;
142 ip = getPointer(dkp, type);
143 if (!ip) return 0;
144 if ((index < 256) && (index >= 0))
145 return ip[index];
146 return 0;
147 }
148
149
150 /*
151 * Fills in DK_TRACE *diff_table with the differences between
152 * *dka (before) and *dkb (after), (after - before = diff)
153 */
154 extern int
dkt_diff(DK_TRACE * dka,DK_TRACE * dkb,DK_TRACE_TYPE type,DK_TRACE * diff_table)155 dkt_diff(DK_TRACE *dka, DK_TRACE *dkb, DK_TRACE_TYPE type, DK_TRACE *diff_table)
156 {
157 int *inputa, *inputb, *output;
158 int i;
159 inputa = getPointer(dka,type);
160 if (!inputa)
161 return 0;
162 inputb = getPointer(dkb,type);
163 if (!inputb)
164 return 0;
165 output = getPointer(diff_table,type);
166 if (!output)
167 return 0;
168
169 for (i = 0; i < 256; i++)
170 {
171 output[i] = (inputb[i] - inputa[i]);
172 }
173 return 1;
174 }
175
176 /*
177 * Generate the tag=value; data for a particular trace type
178 * returns length of generated C string including ending '\0'
179 */
180
181 extern int
dkt_generate(DK_TRACE * dkp,DK_TRACE_TYPE type,char * buffer,int maxBufferSize)182 dkt_generate(DK_TRACE *dkp, DK_TRACE_TYPE type, char* buffer, int maxBufferSize)
183 {
184 int *ip;
185 char *cp;
186 int ix;
187 int len;
188 int highest;
189
190 if (maxBufferSize < 20) return 0; /* Getting too close, you lose */
191 cp = buffer;
192 ip = getPointer(dkp, type);
193 if (!ip) return 0;
194 *buffer++ = (char) type; --maxBufferSize;
195 *buffer++ = '='; --maxBufferSize;
196
197 /* Only produce as many entries as needed, rather than the full 256 */
198
199 for (ix=0, highest=0; ix < 256; ++ix) {
200 if (ip[ix] != 0) highest = ix;
201 }
202
203 for (ix=0; ix <= highest; ++ix) {
204 if (ip[ix] != 0) {
205 len = snprintf(buffer, maxBufferSize, "%d", ip[ix]);
206 buffer += len;
207 maxBufferSize -= len;
208 }
209 if (maxBufferSize < 10) return 0; /* Getting too close, you lose */
210 *buffer++ = ':'; --maxBufferSize;
211 }
212
213 /* Finish up the tag with a semi-colon and turn it into a C string */
214 --buffer;
215 *buffer++ = ';'; //replace last ':'
216 *buffer++ = '\0'; --maxBufferSize;
217 return buffer - cp;
218 }
219
220 //converts a header to to a DK_TRACE table
dkt_hdrtotrace(char * ptr,DK_TRACE * store)221 extern int dkt_hdrtotrace(char *ptr, DK_TRACE *store)
222 {
223 char *values[4]; // hHbB
224 int idx;
225 int delim_count;
226 char *sptr,*eptr;
227 DK_TRACE_TYPE dk_trace_tag[4] =
228 {
229 DKT_RAW_HEADER,
230 DKT_CANON_HEADER,
231 DKT_RAW_BODY,
232 DKT_CANON_BODY
233 };
234 int *ip;
235
236 if ((strncasecmp(ptr, "DomainKey-Trace:", 16)) || !store || (!dkt_parselist(ptr + 16,"hHbB", values)))
237 {
238 return 0;
239 }
240 for (idx = 0; idx < 4; idx++)
241 {
242 if (!values[idx])
243 continue;
244 ip = getPointer(store, dk_trace_tag[idx]);
245 if (!ip) return 0;
246 sptr = values[idx];
247 for (delim_count = 0; ((delim_count < 256) && (*sptr != '\0')); sptr++)
248 {
249 if (*sptr == ':')
250 {
251 delim_count++;
252 continue;
253 }
254 //find the end of the int
255 for (eptr = sptr + 1; ((*eptr != ':')&&(*eptr != '\0')); eptr++);
256 if (*eptr == '\0') //if end of values for key finish up
257 {
258 ip[delim_count] = atoi(sptr);
259 break;
260 }
261 *eptr = '\0';
262 ip[delim_count] = atoi(sptr);
263 delim_count++;
264 sptr = eptr;
265 }
266 }
267 return 1;
268 }
269