1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
15 char trace_string[MAX_TRACE_ELEMENTS * 100 + 400];
17 static const char *spaces = " ";
20 * initializes a new trace
21 * all values will be reset
23 void _start_trace(const char *__file, int __line, int port, struct interface *interface, const char *caller, const char *dialing, int direction, int category, int serial, const char *name)
25 struct timeval current_time;
28 PERROR("trace already started (name=%s) in file %s line %d\n", trace.name, __file, __line);
29 memset(&trace, 0, sizeof(struct trace));
32 SCPY(trace.interface, interface->name);
33 if (caller) if (caller[0])
34 SCPY(trace.caller, caller);
35 if (dialing) if (dialing[0])
36 SCPY(trace.dialing, dialing);
37 trace.direction = direction;
38 trace.category = category;
39 trace.serial = serial;
40 if (name) if (name[0])
41 SCPY(trace.name, name);
43 SCPY(trace.name, "<unknown>");
44 gettimeofday(¤t_time, NULL);
45 trace.sec = current_time.tv_sec;
46 trace.usec = current_time.tv_usec;
51 * adds a new element to the trace
52 * if subelement is given, element will also contain a subelement
53 * if multiple subelements belong to same element, name must be equal for all subelements
55 void _add_trace(const char *__file, int __line, const char *name, const char *sub, const char *fmt, ...)
60 PERROR("trace not started in file %s line %d\n", __file, __line);
62 /* check for required name value */
67 PERROR("trace with name=%s gets element with no string\n", trace.name);
71 /* write name, sub and value */
72 SCPY(trace.element[trace.elements].name, name);
74 SCPY(trace.element[trace.elements].sub, sub);
75 if (fmt) if (fmt[0]) {
77 VUNPRINT(trace.element[trace.elements].value, sizeof(trace.element[trace.elements].value)-1, fmt, args);
81 /* increment elements */
87 * prints trace to socket or log
88 * detail: 1 = brief, 2=short, 3=long
90 static char *print_trace(int detail, int port, char *interface, char *caller, char *dialing, int category)
93 time_t ti = trace.sec;
96 struct mISDNport *mISDNport;
100 trace_string[0] = '\0'; // always clear string
106 if (port >= 0 && trace.port >= 0)
107 if (port != trace.port) return(NULL);
108 if (interface) if (interface[0] && trace.interface[0])
109 if (!!strcasecmp(interface, trace.interface)) return(NULL);
110 if (caller) if (caller[0] && trace.caller[0])
111 if (!!strncasecmp(caller, trace.caller, strlen(trace.caller))) return(NULL);
112 if (dialing) if (dialing[0] && trace.dialing[0])
113 if (!!strncasecmp(dialing, trace.dialing, strlen(trace.dialing))) return(NULL);
114 if (category && trace.category)
115 if (!(category & trace.category)) return(NULL);
119 SCAT(trace_string, "------------------------------------------------------------------------------\n");
121 /* "Port: 1 (BRI PTMP TE)" */
122 if (trace.port >= 0) {
123 mISDNport = mISDNport_first;
125 if (mISDNport->portnum == trace.port)
127 mISDNport = mISDNport->next;
130 SPRINT(buffer, "Port: %d (%s %s %s)", trace.port, (mISDNport->pri)?"PRI":"BRI", (mISDNport->ptp)?"PTP":"PTMP", (mISDNport->ntmode)?"NT":"TE");
131 /* copy interface, if we have a port */
132 if (mISDNport->ifport) if (mISDNport->ifport->interface)
133 SCPY(trace.interface, mISDNport->ifport->interface->name);
135 SPRINT(buffer, "Port: %d (does not exist)\n", trace.port);
136 SCAT(trace_string, buffer);
139 SCAT(trace_string, "Port: ---");
141 if (trace.interface[0]) {
142 /* " Interface: 'Ext'" */
143 SPRINT(buffer, " Interface: '%s'", trace.interface);
144 SCAT(trace_string, buffer);
146 SCAT(trace_string, " Interface: ---");
148 if (trace.caller[0]) {
149 /* " Caller: '021256493'" */
150 SPRINT(buffer, " Caller: '%s'\n", trace.caller);
151 SCAT(trace_string, buffer);
153 SCAT(trace_string, " Caller: ---\n");
155 /* "Time: 25.08.73 05:14:39.282" */
157 SPRINT(buffer, "Time: %02d.%02d.%02d %02d:%02d:%02d.%03d", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec, trace.usec/1000);
158 SCAT(trace_string, buffer);
160 if (trace.direction) {
161 /* " Direction: out" */
162 SPRINT(buffer, " Direction: %s", (trace.direction==DIRECTION_OUT)?"OUT":"IN");
163 SCAT(trace_string, buffer);
165 SCAT(trace_string, " Direction: ---");
167 if (trace.dialing[0]) {
168 /* " Dialing: '57077'" */
169 SPRINT(buffer, " Dialing: '%s'\n", trace.dialing);
170 SCAT(trace_string, buffer);
172 SCAT(trace_string, " Dialing: ---\n");
174 SCAT(trace_string, "------------------------------------------------------------------------------\n");
179 SPRINT(buffer, "%02d.%02d.%02d %02d:%02d:%02d.%03d ", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec, trace.usec/1000);
180 SCAT(trace_string, buffer);
183 /* "CH(45): CC_SETUP (net->user)" */
184 switch (trace.category) {
186 SCAT(trace_string, "CH");
190 SCAT(trace_string, "EP");
194 SCAT(trace_string, "--");
197 SPRINT(buffer, "(%lu): %s", trace.serial, trace.name[0]?trace.name:"<unknown>");
199 SPRINT(buffer, ": %s", trace.name[0]?trace.name:"<unknown>");
200 SCAT(trace_string, buffer);
205 if (trace.port >= 0) {
206 SPRINT(buffer, " port %d", trace.port);
207 SCAT(trace_string, buffer);
210 while(i < trace.elements) {
211 SPRINT(buffer, " %s", trace.element[i].name);
212 if (i) if (!strcmp(trace.element[i].name, trace.element[i-1].name))
214 SCAT(trace_string, buffer);
215 if (trace.element[i].sub[0])
216 SPRINT(buffer, " %s=", trace.element[i].sub);
219 SCAT(trace_string, buffer);
220 if (strchr(trace.element[i].value, ' '))
221 SPRINT(buffer, "'%s'", trace.element[i].value);
223 SPRINT(buffer, "%s", trace.element[i].value);
224 SCAT(trace_string, buffer);
227 SCAT(trace_string, "\n");
232 SCAT(trace_string, "\n");
234 while(i < trace.elements) {
235 SPRINT(buffer, " %s%s", trace.element[i].name, &spaces[strlen(trace.element[i].name)]);
236 if (i) if (!strcmp(trace.element[i].name, trace.element[i-1].name))
238 SCAT(trace_string, buffer);
239 if (trace.element[i].sub[0])
240 SPRINT(buffer, " : %s%s = ", trace.element[i].sub, &spaces[strlen(trace.element[i].sub)]);
242 SPRINT(buffer, " : ");
243 SCAT(trace_string, buffer);
244 if (strchr(trace.element[i].value, ' '))
245 SPRINT(buffer, "'%s'\n", trace.element[i].value);
247 SPRINT(buffer, "%s\n", trace.element[i].value);
248 SCAT(trace_string, buffer);
256 SCAT(trace_string, "\n");
257 return(trace_string);
263 * this function will put the trace to sockets and logfile, if requested
265 void _end_trace(const char *__file, int __line)
269 struct admin_list *admin;
270 struct admin_queue *response, **responsep; /* response pointer */
274 PERROR("trace not started in file %s line %d\n", __file, __line);
276 if (options.deb || options.log[0]) {
277 string = print_trace(1, -1, NULL, NULL, NULL, 0);
281 debug(NULL, NULL, 0, "TRACE", string);
283 if (options.log[0]) {
284 fp = fopen(options.log, "a");
286 ret = fwrite(string, strlen(string), 1, fp);
296 if (admin->trace.detail) {
297 string = print_trace(admin->trace.detail, admin->trace.port, admin->trace.interface, admin->trace.caller, admin->trace.dialing, admin->trace.category);
299 /* seek to end of response list */
300 response = admin->response;
301 responsep = &admin->response;
303 responsep = &response->next;
304 response = response->next;
307 /* create state response */
308 response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message));
312 response->am[0].message = ADMIN_TRACE_RESPONSE;
313 SCPY(response->am[0].u.trace_rsp.text, string);
315 /* attach to response chain */
316 *responsep = response;
317 responsep = &response->next;
318 admin->fd.when |= LCR_FD_WRITE;
323 // fwrite(string, strlen(string), 1, fp);
325 memset(&trace, 0, sizeof(struct trace));