]> rtime.felk.cvut.cz Git - can-utils.git/blob - cansniffer.c
candump: Enable HW timestamping before using it
[can-utils.git] / cansniffer.c
1 /*
2  * cansniffer.c
3  *
4  * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of Volkswagen nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * Alternatively, provided that this notice is retained in full, this
20  * software may be distributed under the terms of the GNU General
21  * Public License ("GPL") version 2, in which case the provisions of the
22  * GPL apply INSTEAD OF those given above.
23  *
24  * The provided data structures and external interfaces from this code
25  * are not restricted to be used by modules with a GPL compatible license.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38  * DAMAGE.
39  *
40  * Send feedback to <linux-can@vger.kernel.org>
41  *
42  */
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <fcntl.h>
49 #include <signal.h>
50 #include <ctype.h>
51 #include <libgen.h>
52 #include <time.h>
53
54 #include <sys/time.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <sys/socket.h>
58 #include <sys/ioctl.h>
59 #include <sys/uio.h>
60 #include <net/if.h>
61
62 #include <linux/can.h>
63 #include <linux/can/bcm.h>
64
65 #include "terminal.h"
66
67 #define U64_DATA(p) (*(unsigned long long*)(p)->data)
68
69 #define SETFNAME "sniffset."
70 #define ANYDEV   "any"
71
72 /* flags */
73
74 #define ENABLE  1 /* by filter or user */
75 #define DISPLAY 2 /* is on the screen */
76 #define UPDATE  4 /* needs to be printed on the screen */
77 #define CLRSCR  8 /* clear screen in next loop */
78
79 /* flags testing & setting */
80
81 #define is_set(id, flag) (sniftab[id].flags & flag)
82 #define is_clr(id, flag) (!(sniftab[id].flags & flag))
83
84 #define do_set(id, flag) (sniftab[id].flags |= flag)
85 #define do_clr(id, flag) (sniftab[id].flags &= ~flag)
86
87 /* time defaults */
88
89 #define TIMEOUT 500 /* in 10ms */
90 #define HOLD    100 /* in 10ms */
91 #define LOOP     20 /* in 10ms */
92
93 #define ATTCOLOR ATTBOLD FGRED
94
95 #define STARTLINESTR "XX delta   ID  data ... "
96
97 struct snif {
98         int flags;
99         long hold;
100         long timeout;
101         struct timeval laststamp;
102         struct timeval currstamp;
103         struct can_frame last;
104         struct can_frame current;
105         struct can_frame marker;
106         struct can_frame notch;
107 } sniftab[2048];
108
109
110 extern int optind, opterr, optopt;
111
112 static int running = 1;
113 static int clearscreen = 1;
114 static int notch;
115 static int filter_id_only;
116 static long timeout = TIMEOUT;
117 static long hold = HOLD;
118 static long loop = LOOP;
119 static unsigned char binary;
120 static unsigned char binary_gap;
121 static unsigned char color;
122 static char *interface;
123
124 void rx_setup (int fd, int id);
125 void rx_delete (int fd, int id);
126 void print_snifline(int id);
127 int handle_keyb(int fd);
128 int handle_bcm(int fd, long currcms);
129 int handle_timeo(int fd, long currcms);
130 void writesettings(char* name);
131 void readsettings(char* name, int sockfd);
132
133 void print_usage(char *prg)
134 {
135         const char manual [] = {
136                 "commands that can be entered at runtime:\n"
137                 "\n"
138                 "q<ENTER>       - quit\n"
139                 "b<ENTER>       - toggle binary / HEX-ASCII output\n"
140                 "B<ENTER>       - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n"
141                 "c<ENTER>       - toggle color mode\n"
142                 "#<ENTER>       - notch currently marked/changed bits (can be used repeatedly)\n"
143                 "*<ENTER>       - clear notched marked\n"
144                 "rMYNAME<ENTER> - read settings file (filter/notch)\n"
145                 "wMYNAME<ENTER> - write settings file (filter/notch)\n"
146                 "+FILTER<ENTER> - add CAN-IDs to sniff\n"
147                 "-FILTER<ENTER> - remove CAN-IDs to sniff\n"
148                 "\n"
149                 "FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n"
150                 "+1F5<ENTER>    - add CAN-ID 0x1F5\n"
151                 "-42E<ENTER>    - remove CAN-ID 0x42E\n"
152                 "-42E7FF<ENTER> - remove CAN-ID 0x42E (using Bitmask)\n"
153                 "-500700<ENTER> - remove CAN-IDs 0x500 - 0x5FF\n"
154                 "+400600<ENTER> - add CAN-IDs 0x400 - 0x5FF\n"
155                 "+000000<ENTER> - add all CAN-IDs\n"
156                 "-000000<ENTER> - remove all CAN-IDs\n"
157                 "\n"
158                 "if (id & filter) == (sniff-id & filter) the action (+/-) is performed,\n"
159                 "which is quite easy when the filter is 000\n"
160                 "\n"
161         };
162
163         fprintf(stderr, "\nUsage: %s [can-interface]\n", prg);
164         fprintf(stderr, "Options: -m <mask>  (initial FILTER default 0x00000000)\n");
165         fprintf(stderr, "         -v <value> (initial FILTER default 0x00000000)\n");
166         fprintf(stderr, "         -q         (quiet - all IDs deactivated)\n");
167         fprintf(stderr, "         -r <name>  (read %sname from file)\n", SETFNAME);
168         fprintf(stderr, "         -b         (start with binary mode)\n");
169         fprintf(stderr, "         -B         (start with binary mode with gap - exceeds 80 chars!)\n");
170         fprintf(stderr, "         -c         (color changes)\n");
171         fprintf(stderr, "         -f         (filter on CAN-ID only)\n");
172         fprintf(stderr, "         -t <time>  (timeout for ID display [x10ms] default: %d, 0 = OFF)\n", TIMEOUT);
173         fprintf(stderr, "         -h <time>  (hold marker on changes [x10ms] default: %d)\n", HOLD);
174         fprintf(stderr, "         -l <time>  (loop time (display) [x10ms] default: %d)\n", LOOP);
175         fprintf(stderr, "Use interface name '%s' to receive from all can-interfaces\n", ANYDEV);
176         fprintf(stderr, "\n");
177         fprintf(stderr, "%s", manual);
178 }
179
180 void sigterm(int signo)
181 {
182         running = 0;
183 }
184
185 int main(int argc, char **argv)
186 {
187         fd_set rdfs;
188         int s;
189         canid_t mask = 0;
190         canid_t value = 0;
191         long currcms = 0;
192         long lastcms = 0;
193         unsigned char quiet = 0;
194         int opt, ret;
195         struct timeval timeo, start_tv, tv;
196         struct sockaddr_can addr;
197         struct ifreq ifr;
198         int i;
199
200
201         signal(SIGTERM, sigterm);
202         signal(SIGHUP, sigterm);
203         signal(SIGINT, sigterm);
204
205         for (i=0; i < 2048 ;i++) /* default: check all CAN-IDs */
206                 do_set(i, ENABLE);
207
208         while ((opt = getopt(argc, argv, "m:v:r:t:h:l:qbBcf?")) != -1) {
209                 switch (opt) {
210                 case 'm':
211                         sscanf(optarg, "%x", &mask);
212                         break;
213
214                 case 'v':
215                         sscanf(optarg, "%x", &value);
216                         break;
217
218                 case 'r':
219                         readsettings(optarg, 0); /* no BCM-setting here */
220                         break;
221
222                 case 't':
223                         sscanf(optarg, "%ld", &timeout);
224                         break;
225
226                 case 'h':
227                         sscanf(optarg, "%ld", &hold);
228                         break;
229
230                 case 'l':
231                         sscanf(optarg, "%ld", &loop);
232                         break;
233
234                 case 'q':
235                         quiet = 1;
236                         break;
237
238                 case 'b':
239                         binary = 1;
240                         binary_gap = 0;
241                         break;
242
243                 case 'B':
244                         binary = 1;
245                         binary_gap = 1;
246                         break;
247
248                 case 'c':
249                         color = 1;
250                         break;
251
252                 case 'f':
253                         filter_id_only = 1;
254                         break;
255
256                 case '?':
257                         break;
258
259                 default:
260                         fprintf(stderr, "Unknown option %c\n", opt);
261                         break;
262                 }
263         }
264
265         if (optind == argc) {
266                 print_usage(basename(argv[0]));
267                 exit(0);
268         }
269         
270         if (mask || value) {
271                 for (i=0; i < 2048 ;i++) {
272                         if ((i & mask) ==  (value & mask))
273                                 do_set(i, ENABLE);
274                         else
275                                 do_clr(i, ENABLE);
276                 }
277         }
278
279         if (quiet)
280                 for (i=0; i < 2048 ;i++)
281                         do_clr(i, ENABLE);
282
283         if (strlen(argv[optind]) >= IFNAMSIZ) {
284                 printf("name of CAN device '%s' is too long!\n", argv[optind]);
285                 return 1;
286         }
287
288         interface = argv[optind];
289
290         if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM)) < 0) {
291                 perror("socket");
292                 return 1;
293         }
294
295         addr.can_family = AF_CAN;
296
297         if (strcmp(ANYDEV, argv[optind])) {
298                 strcpy(ifr.ifr_name, argv[optind]);
299                 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
300                         perror("SIOCGIFINDEX");
301                         exit(1);
302                 }
303                 addr.can_ifindex = ifr.ifr_ifindex;
304         }
305         else
306                 addr.can_ifindex = 0; /* any can interface */
307
308         if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
309                 perror("connect");
310                 return 1;
311         }
312
313         for (i=0; i < 2048 ;i++) /* initial BCM setup */
314                 if (is_set(i, ENABLE))
315                         rx_setup(s, i);
316
317         gettimeofday(&start_tv, NULL);
318         tv.tv_sec = tv.tv_usec = 0;
319
320         printf("%s", CSR_HIDE); /* hide cursor */
321
322         while (running) {
323
324                 FD_ZERO(&rdfs);
325                 FD_SET(0, &rdfs);
326                 FD_SET(s, &rdfs);
327
328                 timeo.tv_sec  = 0;
329                 timeo.tv_usec = 10000 * loop;
330
331                 if ((ret = select(s+1, &rdfs, NULL, NULL, &timeo)) < 0) {
332                         //perror("select");
333                         running = 0;
334                         continue;
335                 }
336
337                 gettimeofday(&tv, NULL);
338                 currcms = (tv.tv_sec - start_tv.tv_sec) * 100 + (tv.tv_usec / 10000);
339
340                 if (FD_ISSET(0, &rdfs))
341                         running &= handle_keyb(s);
342
343                 if (FD_ISSET(s, &rdfs))
344                         running &= handle_bcm(s, currcms);
345
346                 if (currcms - lastcms >= loop) {
347                         running &= handle_timeo(s, currcms);
348                         lastcms = currcms;
349                 }
350         }
351
352         printf("%s", CSR_SHOW); /* show cursor */
353
354         close(s);
355         return 0;
356 }
357
358 void rx_setup (int fd, int id){
359
360         struct {
361                 struct bcm_msg_head msg_head;
362                 struct can_frame frame;
363         } txmsg;
364
365         txmsg.msg_head.opcode  = RX_SETUP;
366         txmsg.msg_head.can_id  = id;
367         txmsg.msg_head.flags   = RX_CHECK_DLC;
368         txmsg.msg_head.ival1.tv_sec  = 0;
369         txmsg.msg_head.ival1.tv_usec = 0;
370         txmsg.msg_head.ival2.tv_sec  = 0;
371         txmsg.msg_head.ival2.tv_usec = 0;
372         txmsg.msg_head.nframes = 1;
373         U64_DATA(&txmsg.frame) = (__u64) 0xFFFFFFFFFFFFFFFFULL;
374
375         if (filter_id_only)
376                 txmsg.msg_head.flags |= RX_FILTER_ID;
377
378         if (write(fd, &txmsg, sizeof(txmsg)) < 0)
379                 perror("write");
380 };
381
382 void rx_delete (int fd, int id){
383
384         struct bcm_msg_head msg_head;
385
386         msg_head.opcode  = RX_DELETE;
387         msg_head.can_id  = id;
388         msg_head.nframes = 0;
389
390         if (write(fd, &msg_head, sizeof(msg_head)) < 0)
391                 perror("write");
392 }
393
394 int handle_keyb(int fd){
395
396         char cmd [20] = {0};
397         int i;
398         unsigned int mask;
399         unsigned int value;
400
401         if (read(0, cmd, 19) > strlen("+123456\n"))
402                 return 1; /* ignore */
403
404         if (strlen(cmd) > 0)
405                 cmd[strlen(cmd)-1] = 0; /* chop off trailing newline */
406
407         switch (cmd[0]) {
408
409         case '+':
410         case '-':
411                 sscanf(&cmd[1], "%x", &value);
412                 if (strlen(&cmd[1]) > 3) {
413                         mask = value & 0xFFF;
414                         value >>= 12;
415                 }
416                 else
417                         mask = 0x7FF;
418
419                 if (cmd[0] == '+') {
420                         for (i=0; i < 2048 ;i++) {
421                                 if (((i & mask) == (value & mask)) && (is_clr(i, ENABLE))) {
422                                         do_set(i, ENABLE);
423                                         rx_setup(fd, i);
424                                 }
425                         }
426                 }
427                 else { /* '-' */
428                         for (i=0; i < 2048 ;i++) {
429                                 if (((i & mask) == (value & mask)) && (is_set(i, ENABLE))) {
430                                         do_clr(i, ENABLE);
431                                         rx_delete(fd, i);
432                                 }
433                         }
434                 }
435                 break;
436
437         case 'w' :
438                 writesettings(&cmd[1]);
439                 break;
440
441         case 'r' :
442                 readsettings(&cmd[1], fd);
443                 break;
444
445         case 'q' :
446                 running = 0;
447                 break;
448
449         case 'B' :
450                 binary_gap = 1;
451                 if (binary)
452                         binary = 0;
453                 else
454                         binary = 1;
455
456                 break;
457
458         case 'b' :
459                 binary_gap = 0;
460                 if (binary)
461                         binary = 0;
462                 else
463                         binary = 1;
464
465                 break;
466
467         case 'c' :
468                 if (color)
469                         color = 0;
470                 else
471                         color = 1;
472
473                 break;
474
475         case '#' :
476                 notch = 1;
477                 break;
478
479         case '*' :
480                 for (i=0; i < 2048; i++)
481                         U64_DATA(&sniftab[i].notch) = (__u64) 0;
482                 break;
483
484         default:
485                 break;
486         }
487
488         clearscreen = 1;
489
490         return 1; /* ok */
491 };
492
493 int handle_bcm(int fd, long currcms){
494
495         int nbytes, id;
496
497         struct {
498                 struct bcm_msg_head msg_head;
499                 struct can_frame frame;
500         } bmsg;
501
502         if ((nbytes = read(fd, &bmsg, sizeof(bmsg))) < 0) {
503                 perror("bcm read");
504                 return 0; /* quit */
505         }
506
507         id = bmsg.msg_head.can_id;
508         ioctl(fd, SIOCGSTAMP, &sniftab[id].currstamp);
509
510         if (bmsg.msg_head.opcode != RX_CHANGED) {
511                 printf("received strange BCM opcode %d!\n", bmsg.msg_head.opcode);
512                 return 0; /* quit */
513         }
514
515         if (nbytes != sizeof(bmsg)) {
516                 printf("received strange BCM data length %d!\n", nbytes);
517                 return 0; /* quit */
518         }
519
520         sniftab[id].current = bmsg.frame;
521         U64_DATA(&sniftab[id].marker) |= 
522                 U64_DATA(&sniftab[id].current) ^ U64_DATA(&sniftab[id].last);
523         sniftab[id].timeout = (timeout)?(currcms + timeout):0;
524
525         if (is_clr(id, DISPLAY))
526                 clearscreen = 1; /* new entry -> new drawing */
527
528         do_set(id, DISPLAY);
529         do_set(id, UPDATE);
530         
531         return 1; /* ok */
532 };
533
534 int handle_timeo(int fd, long currcms){
535
536         int i;
537         int force_redraw = 0;
538         static unsigned int frame_count;
539
540         if (clearscreen) {
541                 char startline[80];
542                 printf("%s%s", CLR_SCREEN, CSR_HOME);
543                 snprintf(startline, 79, "< cansniffer %s # l=%ld h=%ld t=%ld >", interface, loop, hold, timeout);
544                 printf("%s%*s",STARTLINESTR, 79-(int)strlen(STARTLINESTR), startline);
545                 force_redraw = 1;
546                 clearscreen = 0;
547         }
548
549         if (notch) {
550                 for (i=0; i < 2048; i++)
551                         U64_DATA(&sniftab[i].notch) |= U64_DATA(&sniftab[i].marker);
552                 notch = 0;
553         }
554
555         printf("%s", CSR_HOME);
556         printf("%02d\n", frame_count++); /* rolling display update counter */
557         frame_count %= 100;
558
559         for (i=0; i < 2048; i++) {
560
561                 if is_set(i, ENABLE) {
562
563                                 if is_set(i, DISPLAY) {
564
565                                                 if (is_set(i, UPDATE) || (force_redraw)){
566                                                         print_snifline(i);
567                                                         sniftab[i].hold = currcms + hold;
568                                                         do_clr(i, UPDATE);
569                                                 }
570                                                 else
571                                                         if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
572                                                                 U64_DATA(&sniftab[i].marker) = (__u64) 0;
573                                                                 print_snifline(i);
574                                                                 sniftab[i].hold = 0; /* disable update by hold */
575                                                         }
576                                                         else
577                                                                 printf("%s", CSR_DOWN); /* skip my line */
578
579                                                 if (sniftab[i].timeout && sniftab[i].timeout < currcms) {
580                                                         do_clr(i, DISPLAY);
581                                                         do_clr(i, UPDATE);
582                                                         clearscreen = 1; /* removed entry -> new drawing next time */
583                                                 }
584                                         }
585                                 sniftab[i].last      = sniftab[i].current;
586                                 sniftab[i].laststamp = sniftab[i].currstamp;
587                         }
588         }
589
590         return 1; /* ok */
591
592 };
593
594 void print_snifline(int id){
595
596         long diffsec  = sniftab[id].currstamp.tv_sec  - sniftab[id].laststamp.tv_sec;
597         long diffusec = sniftab[id].currstamp.tv_usec - sniftab[id].laststamp.tv_usec;
598         int dlc_diff  = sniftab[id].last.can_dlc - sniftab[id].current.can_dlc;
599         int i,j;
600
601         if (diffusec < 0)
602                 diffsec--, diffusec += 1000000;
603
604         if (diffsec < 0)
605                 diffsec = diffusec = 0;
606
607         if (diffsec > 10)
608                 diffsec = 9, diffusec = 999999;
609
610         printf("%ld.%06ld  %3X  ", diffsec, diffusec, id);
611
612         if (binary) {
613
614                 for (i=0; i<sniftab[id].current.can_dlc; i++) {
615                         for (j=7; j>=0; j--) {
616                                 if ((color) && (sniftab[id].marker.data[i] & 1<<j) &&
617                                     (!(sniftab[id].notch.data[i] & 1<<j)))
618                                         if (sniftab[id].current.data[i] & 1<<j)
619                                                 printf("%s1%s", ATTCOLOR, ATTRESET);
620                                         else
621                                                 printf("%s0%s", ATTCOLOR, ATTRESET);
622                                 else
623                                         if (sniftab[id].current.data[i] & 1<<j)
624                                                 putchar('1');
625                                         else
626                                                 putchar('0');
627                         }
628                         if (binary_gap)
629                                 putchar(' ');
630                 }
631
632                 /*
633                  * when the can_dlc decreased (dlc_diff > 0),
634                  * we need to blank the former data printout
635                  */
636                 for (i=0; i<dlc_diff; i++) {
637                         printf("        ");
638                         if (binary_gap)
639                                 putchar(' ');
640                 }
641         }
642         else {
643
644                 for (i=0; i<sniftab[id].current.can_dlc; i++)
645                         if ((color) && (sniftab[id].marker.data[i]) && (!(sniftab[id].notch.data[i])))
646                                 printf("%s%02X%s ", ATTCOLOR, sniftab[id].current.data[i], ATTRESET);
647                         else
648                                 printf("%02X ", sniftab[id].current.data[i]);
649
650                 if (sniftab[id].current.can_dlc < 8)
651                         printf("%*s", (8 - sniftab[id].current.can_dlc) * 3, "");
652
653                 for (i=0; i<sniftab[id].current.can_dlc; i++)
654                         if ((sniftab[id].current.data[i] > 0x1F) && 
655                             (sniftab[id].current.data[i] < 0x7F))
656                                 if ((color) && (sniftab[id].marker.data[i]) && (!(sniftab[id].notch.data[i])))
657                                         printf("%s%c%s", ATTCOLOR, sniftab[id].current.data[i], ATTRESET);
658                                 else
659                                         putchar(sniftab[id].current.data[i]);
660                         else
661                                 putchar('.');
662
663                 /*
664                  * when the can_dlc decreased (dlc_diff > 0),
665                  * we need to blank the former data printout
666                  */
667                 for (i=0; i<dlc_diff; i++)
668                         putchar(' ');
669         }
670
671         putchar('\n');
672
673         U64_DATA(&sniftab[id].marker) = (__u64) 0;
674
675 };
676
677
678 void writesettings(char* name){
679
680         int fd;
681         char fname[30] = SETFNAME;
682         int i,j;
683         char buf[8]= {0};
684
685         strncat(fname, name, 29 - strlen(fname)); 
686         fd = open(fname,  O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
687     
688         if (fd > 0) {
689
690                 for (i=0; i < 2048 ;i++) {
691                         sprintf(buf, "<%03X>%c.", i, (is_set(i, ENABLE))?'1':'0');
692                         write(fd, buf, 7);
693                         for (j=0; j<8 ; j++){
694                                 sprintf(buf, "%02X", sniftab[i].notch.data[j]);
695                                 write(fd, buf, 2);
696                         }
697                         write(fd, "\n", 1);
698                         /* 7 + 16 + 1 = 24 bytes per entry */ 
699                 }
700                 close(fd);
701         }
702         else
703                 printf("unable to write setting file '%s'!\n", fname);
704 };
705
706 void readsettings(char* name, int sockfd){
707
708         int fd;
709         char fname[30] = SETFNAME;
710         char buf[25] = {0};
711         int i,j;
712
713         strncat(fname, name, 29 - strlen(fname)); 
714         fd = open(fname, O_RDONLY);
715     
716         if (fd > 0) {
717                 if (!sockfd)
718                         printf("reading setting file '%s' ... ", fname);
719
720                 for (i=0; i < 2048 ;i++) {
721                         if (read(fd, &buf, 24) == 24) {
722                                 if (buf[5] & 1) {
723                                         if (is_clr(i, ENABLE)) {
724                                                 do_set(i, ENABLE);
725                                                 if (sockfd)
726                                                         rx_setup(sockfd, i);
727                                         }
728                                 }
729                                 else
730                                         if (is_set(i, ENABLE)) {
731                                                 do_clr(i, ENABLE);
732                                                 if (sockfd)
733                                                         rx_delete(sockfd, i);
734                                         }
735                                 for (j=7; j>=0 ; j--){
736                                         sniftab[i].notch.data[j] =
737                                                 (__u8) strtoul(&buf[2*j+7], (char **)NULL, 16) & 0xFF;
738                                         buf[2*j+7] = 0; /* cut off each time */
739                                 }
740                         }
741                         else {
742                                 if (!sockfd)
743                                         printf("was only able to read until index %d from setting file '%s'!\n",
744                                                i, fname);
745                         }
746                 }
747     
748                 if (!sockfd)
749                         printf("done\n");
750
751                 close(fd);
752         }
753         else
754                 printf("unable to read setting file '%s'!\n", fname);
755 };