We always HAVE_CONFIG_H so don't bother checking whether we have it or not.
[metze/wireshark/wip.git] / epan / ftypes / ftype-bytes.c
1 /*
2  * $Id$
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2001 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <ftypes-int.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <epan/addr_resolv.h>
30 #include <epan/strutil.h>
31 #include <epan/oids.h>
32
33 #define CMP_MATCHES cmp_matches
34
35 static void
36 bytes_fvalue_new(fvalue_t *fv)
37 {
38         fv->value.bytes = NULL;
39 }
40
41 static void
42 bytes_fvalue_free(fvalue_t *fv)
43 {
44         if (fv->value.bytes) {
45                 g_byte_array_free(fv->value.bytes, TRUE);
46                 fv->value.bytes=NULL;
47         }
48 }
49
50
51 static void
52 bytes_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
53 {
54         g_assert(already_copied);
55
56         /* Free up the old value, if we have one */
57         bytes_fvalue_free(fv);
58
59         fv->value.bytes = (GByteArray *)value;
60 }
61
62 static int
63 bytes_repr_len(fvalue_t *fv, ftrepr_t rtype _U_)
64 {
65         if (fv->value.bytes->len == 0) {
66                 /* Empty array of bytes, so the representation
67                  * is an empty string. */
68                 return 0;
69         } else {
70                 /* 3 bytes for each byte of the byte "NN:" minus 1 byte
71                  * as there's no trailing ":". */
72                 return fv->value.bytes->len * 3 - 1;
73         }
74 }
75
76 /*
77  * OID_REPR_LEN:
78  *
79  * 5 for the first byte ([0-2].[0-39].)
80  * for each extra byte if the sub-id is:
81  *   1 byte it can be at most "127." (4 bytes we give it 4)
82  *   2 bytes it can be at most "16383." (6 bytes we give it 8)
83  *   3 bytes it can be at most "2097151." (8 bytes we give it 12)
84  *   4 bytes it can be at most "268435456." (10 bytes we give it 16)
85  *   5 bytes it can be at most "34359738368." (12 bytes we give it 20)
86  *
87  *  a 5 bytes encoded subid can already overflow the guint32 that holds a sub-id,
88  *  making it a completely different issue!
89  */
90 #define OID_REPR_LEN(fv) (5 + (4 * ((fv)->value.bytes->len-1)))
91
92 static int
93 oid_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_)
94 {
95         return OID_REPR_LEN(fv);
96 }
97
98 static void
99 oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
100 {
101         const char* oid_str = oid_encoded2string(fv->value.bytes->data,fv->value.bytes->len);
102         /*
103          * XXX:
104          * I'm assuming that oid_repr_len is going to be called before to set buf's size.
105          * or else we might have a BO.
106          * I guess that is why this callback is not passed a length.
107          *    -- lego
108          */
109         strncpy(buf,oid_str,OID_REPR_LEN(fv));
110 }
111
112 static void
113 bytes_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
114 {
115         guint8 *c;
116         char *write_cursor;
117         unsigned int i;
118
119         c = fv->value.bytes->data;
120         write_cursor = buf;
121
122         for (i = 0; i < fv->value.bytes->len; i++) {
123                 if (i == 0) {
124                         sprintf(write_cursor, "%02x", *c++);
125                         write_cursor += 2;
126                 }
127                 else {
128                         sprintf(write_cursor, ":%02x", *c++);
129                         write_cursor += 3;
130                 }
131         }
132 }
133
134 static void
135 common_fvalue_set(fvalue_t *fv, guint8* data, guint len)
136 {
137         /* Free up the old value, if we have one */
138         bytes_fvalue_free(fv);
139
140         fv->value.bytes = g_byte_array_new();
141         g_byte_array_append(fv->value.bytes, data, len);
142 }
143
144 static void
145 ax25_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
146 {
147         g_assert(!already_copied);
148         common_fvalue_set(fv, value, FT_AX25_ADDR_LEN);
149 }
150
151 static void
152 ether_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
153 {
154         g_assert(!already_copied);
155         common_fvalue_set(fv, (guint8*)value, FT_ETHER_LEN);
156 }
157
158 static void
159 oid_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
160 {
161         g_assert(already_copied);
162
163         /* Free up the old value, if we have one */
164         bytes_fvalue_free(fv);
165
166         fv->value.bytes = (GByteArray *)value;
167 }
168
169
170 static gpointer
171 value_get(fvalue_t *fv)
172 {
173         return fv->value.bytes->data;
174 }
175
176 static gboolean
177 bytes_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
178 {
179         GByteArray      *bytes;
180
181         bytes = g_byte_array_new();
182
183         g_byte_array_append(bytes, (guint8 *)s, (guint)strlen(s));
184
185         /* Free up the old value, if we have one */
186         bytes_fvalue_free(fv);
187         fv->value.bytes = bytes;
188
189         return TRUE;
190 }
191
192 static gboolean
193 bytes_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
194 {
195         GByteArray      *bytes;
196         gboolean        res;
197
198         bytes = g_byte_array_new();
199
200         res = hex_str_to_bytes(s, bytes, TRUE);
201
202         if (!res) {
203                 if (logfunc != NULL)
204                         logfunc("\"%s\" is not a valid byte string.", s);
205                 g_byte_array_free(bytes, TRUE);
206                 return FALSE;
207         }
208
209         /* Free up the old value, if we have one */
210         bytes_fvalue_free(fv);
211
212         fv->value.bytes = bytes;
213
214         return TRUE;
215 }
216
217 static gboolean
218 ax25_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc logfunc)
219 {
220         gchar   *mac;
221
222         /*
223          * Don't log a message if this fails; we'll try looking it
224          * up as another way if it does, and if that fails,
225          * we'll log a message.
226          */
227         if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
228                 if (fv->value.bytes->len > FT_AX25_ADDR_LEN) {
229                         logfunc("\"%s\" contains too many bytes to be a valid AX.25 address.",
230                             s);
231                         return FALSE;
232                 }
233                 else if (fv->value.bytes->len < FT_AX25_ADDR_LEN && !allow_partial_value) {
234                         logfunc("\"%s\" contains too few bytes to be a valid AX.25 address.",
235                             s);
236                         return FALSE;
237                 }
238
239                 return TRUE;
240         }
241
242         mac = get_ax25_name(s);
243         if (!mac) {
244                 logfunc("\"%s\" is not a valid AX.25 address.",
245                     s);
246                 return FALSE;
247         }
248
249         ax25_fvalue_set(fv, mac, FALSE);
250         return TRUE;
251 }
252
253 static gboolean
254 ether_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc logfunc)
255 {
256         guint8  *mac;
257
258         /*
259          * Don't log a message if this fails; we'll try looking it
260          * up as an Ethernet host name if it does, and if that fails,
261          * we'll log a message.
262          */
263         if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
264                 if (fv->value.bytes->len > FT_ETHER_LEN) {
265                         logfunc("\"%s\" contains too many bytes to be a valid Ethernet address.",
266                             s);
267                         return FALSE;
268                 }
269                 else if (fv->value.bytes->len < FT_ETHER_LEN && !allow_partial_value) {
270                         logfunc("\"%s\" contains too few bytes to be a valid Ethernet address.",
271                             s);
272                         return FALSE;
273                 }
274
275                 return TRUE;
276         }
277
278         mac = get_ether_addr(s);
279         if (!mac) {
280                 logfunc("\"%s\" is not a valid hostname or Ethernet address.",
281                     s);
282                 return FALSE;
283         }
284
285         ether_fvalue_set(fv, mac, FALSE);
286         return TRUE;
287 }
288
289 static gboolean
290 oid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
291 {
292         GByteArray      *bytes;
293         gboolean        res;
294
295
296         /*
297          * Don't log a message if this fails; we'll try looking it
298          * up as an OID if it does, and if that fails,
299          * we'll log a message.
300          */
301         /* do not try it as '.' is handled as valid separator for hexbytes :(
302         if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
303                 return TRUE;
304         }
305         */
306
307         bytes = g_byte_array_new();
308         res = oid_str_to_bytes(s, bytes);
309         if (!res) {
310                 if (logfunc != NULL)
311                         logfunc("\"%s\" is not a valid OBJECT IDENTIFIER.", s);
312                 g_byte_array_free(bytes, TRUE);
313                 return FALSE;
314         }
315
316         /* Free up the old value, if we have one */
317         bytes_fvalue_free(fv);
318         fv->value.bytes = bytes;
319
320         return TRUE;
321 }
322
323 static guint
324 len(fvalue_t *fv)
325 {
326         return fv->value.bytes->len;
327 }
328
329 static void
330 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
331 {
332         guint8* data;
333
334         data = fv->value.bytes->data + offset;
335
336         g_byte_array_append(bytes, data, length);
337 }
338
339
340 static gboolean
341 cmp_eq(fvalue_t *fv_a, fvalue_t *fv_b)
342 {
343         GByteArray      *a = fv_a->value.bytes;
344         GByteArray      *b = fv_b->value.bytes;
345
346         if (a->len != b->len) {
347                 return FALSE;
348         }
349
350         return (memcmp(a->data, b->data, a->len) == 0);
351 }
352
353
354 static gboolean
355 cmp_ne(fvalue_t *fv_a, fvalue_t *fv_b)
356 {
357         GByteArray      *a = fv_a->value.bytes;
358         GByteArray      *b = fv_b->value.bytes;
359
360         if (a->len != b->len) {
361                 return TRUE;
362         }
363
364         return (memcmp(a->data, b->data, a->len) != 0);
365 }
366
367
368 static gboolean
369 cmp_gt(fvalue_t *fv_a, fvalue_t *fv_b)
370 {
371         GByteArray      *a = fv_a->value.bytes;
372         GByteArray      *b = fv_b->value.bytes;
373
374         if (a->len > b->len) {
375                 return TRUE;
376         }
377
378         if (a->len < b->len) {
379                 return FALSE;
380         }
381
382         return (memcmp(a->data, b->data, a->len) > 0);
383 }
384
385 static gboolean
386 cmp_ge(fvalue_t *fv_a, fvalue_t *fv_b)
387 {
388         GByteArray      *a = fv_a->value.bytes;
389         GByteArray      *b = fv_b->value.bytes;
390
391         if (a->len > b->len) {
392                 return TRUE;
393         }
394
395         if (a->len < b->len) {
396                 return FALSE;
397         }
398
399         return (memcmp(a->data, b->data, a->len) >= 0);
400 }
401
402 static gboolean
403 cmp_lt(fvalue_t *fv_a, fvalue_t *fv_b)
404 {
405         GByteArray      *a = fv_a->value.bytes;
406         GByteArray      *b = fv_b->value.bytes;
407
408         if (a->len < b->len) {
409                 return TRUE;
410         }
411
412         if (a->len > b->len) {
413                 return FALSE;
414         }
415
416         return (memcmp(a->data, b->data, a->len) < 0);
417 }
418
419 static gboolean
420 cmp_le(fvalue_t *fv_a, fvalue_t *fv_b)
421 {
422         GByteArray      *a = fv_a->value.bytes;
423         GByteArray      *b = fv_b->value.bytes;
424
425         if (a->len < b->len) {
426                 return TRUE;
427         }
428
429         if (a->len > b->len) {
430                 return FALSE;
431         }
432
433         return (memcmp(a->data, b->data, a->len) <= 0);
434 }
435
436 static gboolean
437 cmp_bitwise_and(fvalue_t *fv_a, fvalue_t *fv_b)
438 {
439         GByteArray      *a = fv_a->value.bytes;
440         GByteArray      *b = fv_b->value.bytes;
441         guint i = 0;
442         unsigned char *p_a, *p_b;
443
444         if (b->len != a->len) {
445                 return FALSE;
446         }
447         p_a = a->data;
448         p_b = b->data;
449         while (i < b->len) {
450                 if (p_a[i] & p_b[i])
451                         return TRUE;
452                 else
453                         i++;
454         }
455         return FALSE;
456 }
457
458 static gboolean
459 cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
460 {
461         GByteArray      *a = fv_a->value.bytes;
462         GByteArray      *b = fv_b->value.bytes;
463
464         if (epan_memmem(a->data, a->len, b->data, b->len)) {
465                 return TRUE;
466         }
467         else {
468                 return FALSE;
469         }
470 }
471
472 static gboolean
473 cmp_matches(fvalue_t *fv_a, fvalue_t *fv_b)
474 {
475         GByteArray *a = fv_a->value.bytes;
476         GRegex *regex = fv_b->value.re;
477
478         /* fv_b is always a FT_PCRE, otherwise the dfilter semcheck() would have
479          * warned us. For the same reason (and because we're using g_malloc()),
480          * fv_b->value.re is not NULL.
481          */
482         if (strcmp(fv_b->ftype->name, "FT_PCRE") != 0) {
483                 return FALSE;
484         }
485         if (! regex) {
486                 return FALSE;
487         }
488         return g_regex_match_full(
489                 regex,                  /* Compiled PCRE */
490                 a->data,                /* The data to check for the pattern... */
491                 (int)a->len,    /* ... and its length */
492                 0,                              /* Start offset within data */
493                 0,                              /* GRegexMatchFlags */
494                 NULL,                   /* We are not interested in the match information */
495                 NULL                    /* We don't want error information */
496                 );
497         /* NOTE - DO NOT g_free(data) */
498 }
499
500 void
501 ftype_register_bytes(void)
502 {
503
504         static ftype_t bytes_type = {
505                 FT_BYTES,                                       /* ftype */
506                 "FT_BYTES",                                     /* name */
507                 "Sequence of bytes",            /* pretty_name */
508                 0,                                                      /* wire_size */
509                 bytes_fvalue_new,                       /* new_value */
510                 bytes_fvalue_free,                      /* free_value */
511                 bytes_from_unparsed,            /* val_from_unparsed */
512                 bytes_from_string,                      /* val_from_string */
513                 bytes_to_repr,                          /* val_to_string_repr */
514                 bytes_repr_len,                         /* len_string_repr */
515
516                 bytes_fvalue_set,                       /* set_value */
517                 NULL,                                           /* set_value_uinteger */
518                 NULL,                                           /* set_value_sinteger */
519                 NULL,                                           /* set_value_integer64 */
520                 NULL,                                           /* set_value_floating */
521
522                 value_get,                                      /* get_value */
523                 NULL,                                           /* get_value_uinteger */
524                 NULL,                                           /* get_value_sinteger */
525                 NULL,                                           /* get_value_integer64 */
526                 NULL,                                           /* get_value_floating */
527
528                 cmp_eq,
529                 cmp_ne,
530                 cmp_gt,
531                 cmp_ge,
532                 cmp_lt,
533                 cmp_le,
534                 cmp_bitwise_and,
535                 cmp_contains,
536                 CMP_MATCHES,
537
538                 len,
539                 slice,
540         };
541
542         static ftype_t uint_bytes_type = {
543                 FT_UINT_BYTES,          /* ftype */
544                 "FT_UINT_BYTES",                /* name */
545                 "Sequence of bytes",            /* pretty_name */
546                 0,                              /* wire_size */
547                 bytes_fvalue_new,               /* new_value */
548                 bytes_fvalue_free,              /* free_value */
549                 bytes_from_unparsed,            /* val_from_unparsed */
550                 NULL,                           /* val_from_string */
551                 bytes_to_repr,                  /* val_to_string_repr */
552                 bytes_repr_len,                 /* len_string_repr */
553
554                 bytes_fvalue_set,               /* set_value */
555                 NULL,                           /* set_value_uinteger */
556                 NULL,                           /* set_value_sinteger */
557                 NULL,                           /* set_value_integer64 */
558                 NULL,                           /* set_value_floating */
559
560                 value_get,                      /* get_value */
561                 NULL,                           /* get_value_uinteger */
562                 NULL,                           /* get_value_sinteger */
563                 NULL,                           /* get_value_integer64 */
564                 NULL,                           /* get_value_floating */
565
566                 cmp_eq,
567                 cmp_ne,
568                 cmp_gt,
569                 cmp_ge,
570                 cmp_lt,
571                 cmp_le,
572                 cmp_bitwise_and,
573                 cmp_contains,
574                 NULL,                           /* cmp_matches */
575
576                 len,
577                 slice,
578         };
579
580         static ftype_t ax25_type = {
581                 FT_AX25,                        /* ftype */
582                 "FT_AX25",                      /* name */
583                 "AX.25 address",                /* pretty_name */
584                 FT_AX25_ADDR_LEN,               /* wire_size */
585                 bytes_fvalue_new,               /* new_value */
586                 bytes_fvalue_free,              /* free_value */
587                 ax25_from_unparsed,             /* val_from_unparsed */
588                 NULL,                           /* val_from_string */
589                 bytes_to_repr,                  /* val_to_string_repr */
590                 bytes_repr_len,                 /* len_string_repr */
591
592                 ax25_fvalue_set,                /* set_value */
593                 NULL,                           /* set_value_uinteger */
594                 NULL,                           /* set_value_integer */
595                 NULL,                           /* set_value_integer64 */
596                 NULL,                           /* set_value_floating */
597
598                 value_get,                      /* get_value */
599                 NULL,                           /* set_value_uinteger */
600                 NULL,                           /* get_value_integer */
601                 NULL,                           /* get_value_integer64 */
602                 NULL,                           /* get_value_floating */
603
604                 cmp_eq,
605                 cmp_ne,
606                 cmp_gt,
607                 cmp_ge,
608                 cmp_lt,
609                 cmp_le,
610                 cmp_bitwise_and,
611                 cmp_contains,
612                 CMP_MATCHES,
613
614                 len,
615                 slice,
616         };
617
618         static ftype_t ether_type = {
619                 FT_ETHER,                       /* ftype */
620                 "FT_ETHER",                     /* name */
621                 "Ethernet or other MAC address",/* pretty_name */
622                 FT_ETHER_LEN,                   /* wire_size */
623                 bytes_fvalue_new,               /* new_value */
624                 bytes_fvalue_free,              /* free_value */
625                 ether_from_unparsed,            /* val_from_unparsed */
626                 NULL,                           /* val_from_string */
627                 bytes_to_repr,                  /* val_to_string_repr */
628                 bytes_repr_len,                 /* len_string_repr */
629
630                 ether_fvalue_set,               /* set_value */
631                 NULL,                           /* set_value_uinteger */
632                 NULL,                           /* set_value_sinteger */
633                 NULL,                           /* set_value_integer64 */
634                 NULL,                           /* set_value_floating */
635
636                 value_get,                      /* get_value */
637                 NULL,                           /* get_value_uinteger */
638                 NULL,                           /* get_value_sinteger */
639                 NULL,                           /* get_value_integer64 */
640                 NULL,                           /* get_value_floating */
641
642                 cmp_eq,
643                 cmp_ne,
644                 cmp_gt,
645                 cmp_ge,
646                 cmp_lt,
647                 cmp_le,
648                 cmp_bitwise_and,
649                 cmp_contains,
650                 CMP_MATCHES,
651
652                 len,
653                 slice,
654         };
655
656         static ftype_t oid_type = {
657                 FT_OID,                 /* ftype */
658                 "FT_OID",                       /* name */
659                 "ASN.1 object identifier",      /* pretty_name */
660                 0,                      /* wire_size */
661                 bytes_fvalue_new,               /* new_value */
662                 bytes_fvalue_free,              /* free_value */
663                 oid_from_unparsed,              /* val_from_unparsed */
664                 NULL,                           /* val_from_string */
665                 oid_to_repr,                    /* val_to_string_repr */
666                 oid_repr_len,                   /* len_string_repr */
667
668                 oid_fvalue_set,         /* set_value */
669                 NULL,                           /* set_value_uinteger */
670                 NULL,                           /* set_value_sinteger */
671                 NULL,                           /* set_value_integer64 */
672                 NULL,                           /* set_value_floating */
673
674                 value_get,                      /* get_value */
675                 NULL,                           /* get_value_uinteger */
676                 NULL,                           /* get_value_sinteger */
677                 NULL,                           /* get_value_integer64 */
678                 NULL,                           /* get_value_floating */
679
680                 cmp_eq,
681                 cmp_ne,
682                 cmp_gt,
683                 cmp_ge,
684                 cmp_lt,
685                 cmp_le,
686                 cmp_bitwise_and,
687                 cmp_contains,
688                 NULL,                           /* cmp_matches */
689
690                 len,
691                 slice,
692         };
693
694         ftype_register(FT_BYTES, &bytes_type);
695         ftype_register(FT_UINT_BYTES, &uint_bytes_type);
696         ftype_register(FT_AX25, &ax25_type);
697         ftype_register(FT_ETHER, &ether_type);
698         ftype_register(FT_OID, &oid_type);
699 }