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