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