ad408880e5d5127044189c7f5a047b008a62aed3
[obnox/wireshark/wip.git] / resolv.c
1 /* resolv.c
2  * Routines for network object lookup
3  *
4  * $Id: resolv.c,v 1.12 1999/09/26 14:39:12 deniel Exp $
5  *
6  * Laurent Deniel <deniel@worldnet.fr>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #ifndef WIN32
37 #ifndef AVOID_DNS_TIMEOUT
38 #define AVOID_DNS_TIMEOUT
39 #endif
40 #endif
41
42
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46
47 #ifdef HAVE_SYS_TYPES_H
48 # include <sys/types.h>
49 #endif
50
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h>
53 #endif
54
55 #ifdef HAVE_NETDB_H
56 #include <netdb.h>
57 #endif
58
59 #include <signal.h>
60
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
63 #endif
64
65 #ifdef AVOID_DNS_TIMEOUT
66 # include <setjmp.h>
67 #endif
68
69 #include "packet.h"
70 #include "packet-ipv6.h"
71 #include "globals.h"
72 #include "resolv.h"
73
74 #ifndef MAXNAMELEN
75 #define MAXNAMELEN      64      /* max name length (hostname and port name) */
76 #endif
77 #define MAXMANUFLEN     9       /* max vendor name length with ending '\0' */
78 #define HASHETHSIZE     1024
79 #define HASHHOSTSIZE    1024
80 #define HASHMANUFSIZE   256
81 #define HASHPORTSIZE    256
82
83 /* hash table used for host and port lookup */
84
85 typedef struct hashname {
86   u_int                 addr;
87   u_char                name[MAXNAMELEN];
88   struct hashname       *next;
89 } hashname_t;
90
91 /* hash tables used for ethernet and manufacturer lookup */
92
93 typedef struct hashmanuf {
94   u_char                addr[3];
95   char                  name[MAXMANUFLEN];
96   struct hashmanuf      *next;
97 } hashmanuf_t;
98
99 typedef struct hashether {
100   u_char                addr[6];
101   char                  name[MAXNAMELEN];
102   struct hashether      *next;
103 } hashether_t;
104
105 /* internal ethernet type */
106
107 typedef struct _ether
108 {
109   u_char                addr[6];
110   char                  name[MAXNAMELEN];
111 } ether_t;
112
113 static hashname_t       *host_table[HASHHOSTSIZE];
114 static hashname_t       *udp_port_table[HASHPORTSIZE];
115 static hashname_t       *tcp_port_table[HASHPORTSIZE];
116 static hashether_t      *eth_table[HASHETHSIZE];
117 static hashmanuf_t      *manuf_table[HASHMANUFSIZE];
118
119 static int              eth_resolution_initialized = 0;
120
121 /*
122  *  Global variables (can be changed in GUI sections)
123  */
124
125 int g_resolving_actif = 1;              /* routines are active by default */
126
127 gchar *g_ethers_path  = EPATH_ETHERS;
128 gchar *g_pethers_path = NULL;           /* "$HOME"/EPATH_PERSONAL_ETHERS    */
129 gchar *g_manuf_path   = EPATH_MANUF;    /* may only be changed before the   */
130                                         /* first resolving call             */
131
132 /*
133  *  Local function definitions 
134  */
135
136 static u_char *serv_name_lookup(u_int port, u_int proto)
137 {
138
139   hashname_t *tp;
140   hashname_t **table;
141   char *serv_proto = NULL;
142   struct servent *servp;
143   int i;
144
145   switch(proto) {
146   case IPPROTO_UDP:
147     table = udp_port_table;
148     serv_proto = "udp";
149     break;
150   case IPPROTO_TCP:
151     table = tcp_port_table;
152     serv_proto = "tcp";
153     break;
154   default:
155     /* not yet implemented */
156     return NULL;
157     /*NOTREACHED*/
158     break;
159   } /* proto */
160   
161   i = port & (HASHPORTSIZE - 1);
162   tp = table[ i & (HASHPORTSIZE - 1)];
163
164   if( tp == NULL ) {
165     tp = table[ i & (HASHPORTSIZE - 1)] = 
166       (hashname_t *)g_malloc(sizeof(hashname_t));
167   } else {  
168     while(1) {
169       if( tp->addr == port ) {
170         return tp->name;
171       }
172       if (tp->next == NULL) {
173         tp->next = (hashname_t *)g_malloc(sizeof(hashname_t));
174         tp = tp->next;
175         break;
176       }
177       tp = tp->next;
178     }
179   }
180   
181   /* fill in a new entry */
182   tp->addr = port;
183   tp->next = NULL;
184
185   if ((servp = getservbyport(htons(port), serv_proto)) == NULL) {
186     /* unknown port */
187     sprintf(tp->name, "%d", port);
188   } else {
189     strncpy(tp->name, servp->s_name, MAXNAMELEN);
190     tp->name[MAXNAMELEN-1] = '\0';
191   }
192
193   return (tp->name);
194
195 } /* serv_name_lookup */
196
197 #ifdef AVOID_DNS_TIMEOUT
198
199 #define DNS_TIMEOUT     2       /* max sec per call */
200
201 jmp_buf hostname_env;
202
203 static void abort_network_query(int sig)
204 {
205   longjmp(hostname_env, 1);
206 }
207 #endif /* AVOID_DNS_TIMEOUT */
208
209 static u_char *host_name_lookup(u_int addr)
210 {
211
212   hashname_t * volatile tp;
213   hashname_t **table = host_table;
214   struct hostent *hostp;
215
216   tp = table[ addr & (HASHHOSTSIZE - 1)];
217
218   if( tp == NULL ) {
219     tp = table[ addr & (HASHHOSTSIZE - 1)] = 
220       (hashname_t *)g_malloc(sizeof(hashname_t));
221   } else {  
222     while(1) {
223       if( tp->addr == addr ) {
224         return tp->name;
225       }
226       if (tp->next == NULL) {
227         tp->next = (hashname_t *)g_malloc(sizeof(hashname_t));
228         tp = tp->next;
229         break;
230       }
231       tp = tp->next;
232     }
233   }
234   
235   /* fill in a new entry */
236   tp->addr = addr;
237   tp->next = NULL;
238
239 #ifdef AVOID_DNS_TIMEOUT
240     
241   /* Quick hack to avoid DNS/YP timeout */
242   
243   if (!setjmp(hostname_env)) {
244     signal(SIGALRM, abort_network_query);
245     alarm(DNS_TIMEOUT);
246 #endif
247     hostp = gethostbyaddr((char *)&addr, 4, AF_INET);
248 #ifdef AVOID_DNS_TIMEOUT
249     alarm(0);
250 #endif
251     if (hostp != NULL) {
252       strncpy(tp->name, hostp->h_name, MAXNAMELEN);
253       tp->name[MAXNAMELEN-1] = '\0';
254       return tp->name;
255     }
256 #ifdef AVOID_DNS_TIMEOUT
257   }
258 #endif
259
260   /* unknown host or DNS timeout */
261
262   sprintf(tp->name, "%s", ip_to_str((guint8 *)&addr));  
263
264   return (tp->name);
265
266 } /* host_name_lookup */
267
268 static u_char *host_name_lookup6(struct e_in6_addr *addr)
269 {
270   static u_char name[MAXNAMELEN];
271 #ifdef INET6
272   struct hostent *hostp;
273
274 #ifdef AVOID_DNS_TIMEOUT
275     
276   /* Quick hack to avoid DNS/YP timeout */
277   
278   if (!setjmp(hostname_env)) {
279     signal(SIGALRM, abort_network_query);
280     alarm(DNS_TIMEOUT);
281 #endif /* AVOID_DNS_TIMEOUT */
282     hostp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET6);
283 #ifdef AVOID_DNS_TIMEOUT
284     alarm(0);
285 #endif
286     if (hostp != NULL) {
287       strncpy(name, hostp->h_name, MAXNAMELEN);
288       name[MAXNAMELEN-1] = '\0';
289       return name;
290     }
291 #ifdef AVOID_DNS_TIMEOUT
292   }
293 #endif
294
295   /* unknown host or DNS timeout */
296 #endif /* INET6 */
297   sprintf(name, "%s", ip6_to_str(addr));  
298   return (name);
299 }
300
301 /*
302  *  Miscellaneous functions
303  */
304
305 static int fgetline(char **buf, int *size, FILE *fp)
306 {
307   int len;
308   int c;
309
310   if (fp == NULL)
311     return -1;
312
313   if (*buf == NULL) {
314     if (*size == 0) 
315       *size = BUFSIZ;
316     
317     if ((*buf = g_malloc(*size)) == NULL)
318       return -1;
319   }
320
321   if (feof(fp))
322     return -1;
323     
324   len = 0;
325   while ((c = getc(fp)) != EOF && c != '\n') {
326     if (len+1 >= *size) {
327       if ((*buf = g_realloc(*buf, *size += BUFSIZ)) == NULL)
328         return -1;
329     }
330     (*buf)[len++] = c;
331   }
332
333   if (len == 0 && c == EOF)
334     return -1;
335     
336   (*buf)[len] = '\0';
337     
338   return len;
339
340 } /* fgetline */
341
342
343 /*
344  * Ethernet / manufacturer resolution
345  *
346  * The following functions implement ethernet address resolution and
347  * ethers files parsing (see ethers(4)). 
348  *
349  * /etc/manuf has the same format as ethers(4) except that names are 
350  * truncated to MAXMANUFLEN-1 characters and that an address contains 
351  * only 3 bytes (instead of 6).
352  *
353  * Notes:
354  *
355  * I decide to not use the existing functions (see ethers(3) on some 
356  * operating systems) for the following reasons:
357  * - performance gains (use of hash tables and some other enhancements),
358  * - use of two ethers files (system-wide and per user),
359  * - avoid the use of NIS maps,
360  * - lack of these functions on some systems.
361  *
362  * So the following functions do _not_ behave as the standard ones.
363  *
364  * -- Laurent.
365  */
366
367
368 static int parse_ether_line(char *line, ether_t *eth, int six_bytes)
369 {
370   /*
371    *  See man ethers(4) for /etc/ethers file format
372    *  (not available on all systems).
373    *  We allow both ethernet address separators (':' and '-').
374    */
375
376   gchar *cp;
377   int a0, a1, a2, a3, a4, a5;
378     
379   if ((cp = strchr(line, '#')))
380     *cp = '\0';
381   
382   if ((cp = strtok(line, " \t\n")) == NULL)
383     return -1;
384
385   if (six_bytes) {
386     if (sscanf(cp, "%x:%x:%x:%x:%x:%x", &a0, &a1, &a2, &a3, &a4, &a5) != 6) {
387       if (sscanf(cp, "%x-%x-%x-%x-%x-%x", &a0, &a1, &a2, &a3, &a4, &a5) != 6)
388         return -1;
389     }
390   } else {
391     if (sscanf(cp, "%x:%x:%x", &a0, &a1, &a2) != 3) {
392       if (sscanf(cp, "%x-%x-%x", &a0, &a1, &a2) != 3)
393         return -1;
394     }
395   }
396
397   if ((cp = strtok(NULL, " \t\n")) == NULL)
398     return -1;
399
400   eth->addr[0] = a0;
401   eth->addr[1] = a1;
402   eth->addr[2] = a2;
403   if (six_bytes) {
404     eth->addr[3] = a3;
405     eth->addr[4] = a4;
406     eth->addr[5] = a5;
407   } else {
408     eth->addr[3] = 0;
409     eth->addr[4] = 0;
410     eth->addr[5] = 0;
411   }
412
413   strncpy(eth->name, cp, MAXNAMELEN);
414   eth->name[MAXNAMELEN-1] = '\0';
415
416   return 0;
417
418 } /* parse_ether_line */
419
420 static FILE *eth_p = NULL;
421
422 static void set_ethent(char *path)
423 {
424   if (eth_p)
425     rewind(eth_p);
426   else
427     eth_p = fopen(path, "r");
428 }
429
430 static void end_ethent(void)
431 {
432   if (eth_p) {
433     fclose(eth_p);
434     eth_p = NULL;
435   }
436 }
437
438 static ether_t *get_ethent(int six_bytes)
439 {
440  
441   static ether_t eth;
442   static int     size = 0;
443   static char   *buf = NULL;
444   
445   if (eth_p == NULL) 
446     return NULL;
447
448   while (fgetline(&buf, &size, eth_p) >= 0) {
449     if (parse_ether_line(buf, &eth, six_bytes) == 0) {
450       return &eth;
451     }
452   }
453     
454   return NULL;
455
456 } /* get_ethent */
457
458 static ether_t *get_ethbyname(u_char *name)
459 {
460   ether_t *eth;
461   
462   set_ethent(g_ethers_path);
463
464   while ((eth = get_ethent(1)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
465     ;
466
467   if (eth == NULL) {
468     end_ethent();
469     
470     set_ethent(g_pethers_path);
471
472     while ((eth = get_ethent(1)) && strncmp(name, eth->name, MAXNAMELEN) != 0)
473       ;
474
475     end_ethent();
476   }
477
478   return eth;
479
480 } /* get_ethbyname */
481
482 static ether_t *get_ethbyaddr(u_char *addr)
483 {
484
485   ether_t *eth;
486   
487   set_ethent(g_ethers_path);
488
489   while ((eth = get_ethent(1)) && memcmp(addr, eth->addr, 6) != 0)
490     ;
491
492   if (eth == NULL) {
493     end_ethent();
494     
495     set_ethent(g_pethers_path);
496     
497     while ((eth = get_ethent(1)) && memcmp(addr, eth->addr, 6) != 0)
498       ;
499     
500     end_ethent();
501   }
502
503   return eth;
504
505 } /* get_ethbyaddr */
506
507 static void add_manuf_name(u_char *addr, u_char *name)
508 {
509
510   hashmanuf_t *tp;
511   hashmanuf_t **table = manuf_table;
512
513   tp = table[ ((int)addr[2]) & (HASHMANUFSIZE - 1)];
514
515   if( tp == NULL ) {
516     tp = table[ ((int)addr[2]) & (HASHMANUFSIZE - 1)] = 
517       (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
518   } else {  
519     while(1) {
520       if (tp->next == NULL) {
521         tp->next = (hashmanuf_t *)g_malloc(sizeof(hashmanuf_t));
522         tp = tp->next;
523         break;
524       }
525       tp = tp->next;
526     }
527   }
528   
529   memcpy(tp->addr, addr, sizeof(tp->addr));
530   strncpy(tp->name, name, MAXMANUFLEN);
531   tp->name[MAXMANUFLEN-1] = '\0';
532   tp->next = NULL;
533
534 } /* add_manuf_name */
535
536 static hashmanuf_t *manuf_name_lookup(u_char *addr)
537 {
538
539   hashmanuf_t *tp;
540   hashmanuf_t **table = manuf_table;
541
542   tp = table[ ((int)addr[2]) & (HASHMANUFSIZE - 1)];
543   
544   while(tp != NULL) {
545     if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
546       return tp;
547     }
548     tp = tp->next;
549   }
550   
551   return NULL;
552
553 } /* manuf_name_lookup */
554
555 static hashether_t *add_eth_name(u_char *addr, u_char *name)
556 {
557   hashether_t *tp;
558   hashether_t **table = eth_table;
559   int i,j;
560
561   j = (addr[2] << 8) | addr[3];
562   i = (addr[4] << 8) | addr[5];
563
564   tp = table[ (i ^ j) & (HASHETHSIZE - 1)];
565
566   if( tp == NULL ) {
567     tp = table[ (i ^ j) & (HASHETHSIZE - 1)] = 
568       (hashether_t *)g_malloc(sizeof(hashether_t));
569   } else {  
570     while(1) {
571       if (tp->next == NULL) {
572         tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
573         tp = tp->next;
574         break;
575       }
576       tp = tp->next;
577     }
578   }
579   
580   memcpy(tp->addr, addr, sizeof(tp->addr));
581   strncpy(tp->name, name, MAXNAMELEN);
582   tp->name[MAXNAMELEN-1] = '\0';
583   tp->next = NULL;
584
585   return tp;
586
587 } /* add_eth_name */
588
589 static u_char *eth_name_lookup(u_char *addr)
590 {
591   hashmanuf_t *manufp;
592   hashether_t *tp;
593   hashether_t **table = eth_table;
594   ether_t *eth;
595   int i,j;
596
597   j = (addr[2] << 8) | addr[3];
598   i = (addr[4] << 8) | addr[5];
599
600   tp = table[ (i ^ j) & (HASHETHSIZE - 1)];
601
602   if( tp == NULL ) {
603     tp = table[ (i ^ j) & (HASHETHSIZE - 1)] = 
604       (hashether_t *)g_malloc(sizeof(hashether_t));
605   } else {  
606     while(1) {
607       if (memcmp(tp->addr, addr, sizeof(tp->addr)) == 0) {
608         return tp->name;
609       }
610       if (tp->next == NULL) {
611         tp->next = (hashether_t *)g_malloc(sizeof(hashether_t));
612         tp = tp->next;
613         break;
614       }
615       tp = tp->next;
616     }
617   }
618   
619   /* fill in a new entry */
620
621   memcpy(tp->addr, addr, sizeof(tp->addr));
622   tp->next = NULL;
623
624   if ( (eth = get_ethbyaddr(addr)) == NULL) {
625     /* unknown name */
626
627     if ((manufp = manuf_name_lookup(addr)) == NULL)
628       sprintf(tp->name, "%s", ether_to_str((guint8 *)addr));
629     else
630       sprintf(tp->name, "%s_%02x:%02x:%02x", 
631               manufp->name, addr[3], addr[4], addr[5]);
632
633   } else {
634     strncpy(tp->name, eth->name, MAXNAMELEN);
635     tp->name[MAXNAMELEN-1] = '\0';
636   }
637
638   return (tp->name);
639
640 } /* eth_name_lookup */
641
642 static u_char *eth_addr_lookup(u_char *name)
643 {
644   ether_t *eth;
645   hashether_t *tp;
646   hashether_t **table = eth_table;
647   int i;
648
649   /* to be optimized (hash table from name to addr) */
650   for (i = 0; i < HASHETHSIZE; i++) {
651     tp = table[i];
652     while (tp) {
653       if (strcmp(tp->name, name) == 0)
654         return tp->addr;
655       tp = tp->next;
656     }
657   }
658
659   /* not in hash table : performs a file lookup */
660
661   if ((eth = get_ethbyname(name)) == NULL)
662     return NULL;
663
664   /* add new entry in hash table */
665
666   tp = add_eth_name(eth->addr, name);
667
668   return tp->addr;
669
670 } /* eth_addr_lookup */
671
672 static void initialize_ethers(void)
673 {
674   ether_t *eth;
675
676 #ifdef DEBUG_RESOLV
677   signal(SIGSEGV, SIG_IGN);
678 #endif
679
680   if (g_pethers_path == NULL) {
681     g_pethers_path = g_malloc(strlen(getenv("HOME")) + 
682                               strlen(EPATH_PERSONAL_ETHERS) + 2);
683     sprintf(g_pethers_path, "%s/%s", 
684             (char *)getenv("HOME"), EPATH_PERSONAL_ETHERS);
685   }
686
687   /* manuf hash table initialization */
688
689   set_ethent(g_manuf_path);
690
691   while ((eth = get_ethent(0))) {
692     add_manuf_name(eth->addr, eth->name);
693   }
694
695   end_ethent();
696
697 } /* initialize_ethers */
698
699 /* 
700  *  External Functions
701  */
702
703 extern u_char *get_hostname(u_int addr) 
704 {
705   if (!g_resolving_actif)
706     return ip_to_str((guint8 *)&addr);
707
708   return host_name_lookup(addr);
709 }
710
711 extern gchar *get_hostname6(struct e_in6_addr *addr) 
712 {
713 #ifdef INET6
714   if (!g_resolving_actif)
715     return ip6_to_str(addr);
716   if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MULTICAST(addr))
717     return ip6_to_str(addr);
718 #endif
719   return host_name_lookup6(addr);
720 }
721
722 extern void add_host_name(u_int addr, u_char *name)
723 {
724
725   hashname_t *tp;
726   hashname_t **table = host_table;
727
728   tp = table[ addr & (HASHHOSTSIZE - 1)];
729
730   if( tp == NULL ) {
731     tp = table[ addr & (HASHHOSTSIZE - 1)] = 
732       (hashname_t *)g_malloc(sizeof(hashname_t));
733   } else {  
734     while(1) {
735       if (tp->next == NULL) {
736         tp->next = (hashname_t *)g_malloc(sizeof(hashname_t));
737         tp = tp->next;
738         break;
739       }
740       tp = tp->next;
741     }
742   }
743   
744   strncpy(tp->name, name, MAXNAMELEN);
745   tp->name[MAXNAMELEN-1] = '\0';
746   tp->addr = addr;
747   tp->next = NULL;
748
749 } /* add_host_name */
750
751 extern u_char *get_udp_port(u_int port) 
752 {
753   static gchar  str[3][MAXNAMELEN];
754   static gchar *cur;
755
756   if (!g_resolving_actif) {
757     if (cur == &str[0][0]) {
758       cur = &str[1][0];
759     } else if (cur == &str[1][0]) {  
760       cur = &str[2][0];
761     } else {  
762       cur = &str[0][0];
763     }
764     sprintf(cur, "%d", port);
765     return cur;
766   }
767
768   return serv_name_lookup(port, IPPROTO_UDP);
769
770 } /* get_udp_port */
771
772 extern u_char *get_tcp_port(u_int port) 
773 {
774   static gchar  str[3][MAXNAMELEN];
775   static gchar *cur;
776
777   if (!g_resolving_actif) {
778     if (cur == &str[0][0]) {
779       cur = &str[1][0];
780     } else if (cur == &str[1][0]) {  
781       cur = &str[2][0];
782     } else {  
783       cur = &str[0][0];
784     }
785     sprintf(cur, "%d", port);
786     return cur;
787   }
788
789   return serv_name_lookup(port, IPPROTO_TCP);
790
791 } /* get_tcp_port */
792
793 extern u_char *get_ether_name(u_char *addr)
794 {
795   if (!g_resolving_actif)
796     return ether_to_str((guint8 *)addr);
797
798   if (!eth_resolution_initialized) {
799     initialize_ethers();
800     eth_resolution_initialized = 1;
801   }
802
803   return eth_name_lookup(addr);
804
805 } /* get_ether_name */
806
807 extern u_char *get_ether_addr(u_char *name)
808 {
809
810   /* force resolution (do not check g_resolving_actif) */
811
812   if (!eth_resolution_initialized) {
813     initialize_ethers();
814     eth_resolution_initialized = 1;
815   }
816
817   return eth_addr_lookup(name);
818
819 } /* get_ether_addr */
820
821 extern u_char *get_manuf_name(u_char *addr) 
822 {
823   static gchar  str[3][MAXMANUFLEN];
824   static gchar *cur;
825   hashmanuf_t  *manufp;
826
827   if (g_resolving_actif && !eth_resolution_initialized) {
828     initialize_ethers();
829     eth_resolution_initialized = 1;
830   }
831
832   if (!g_resolving_actif || ((manufp = manuf_name_lookup(addr)) == NULL)) {
833     if (cur == &str[0][0]) {
834       cur = &str[1][0];
835     } else if (cur == &str[1][0]) {  
836       cur = &str[2][0];
837     } else {  
838       cur = &str[0][0];
839     }
840     sprintf(cur, "%02x:%02x:%02x", addr[0], addr[1], addr[2]);
841     return cur;
842   }
843   
844   return manufp->name;
845
846 } /* get_manuf_name */
847
848
849
850 /* return IP address of either hostname or IP address in text format.
851  * Used more in the dfilter parser rather than in packet dissectors */
852 unsigned long get_host_ipaddr(const char *host)
853 {
854         struct hostent          *hp = NULL;
855         unsigned long           ipaddr;
856
857         hp = gethostbyname(host);
858         if (hp == NULL) {
859                 hp = gethostbyaddr(host, strlen(host), AF_INET);
860                 if (hp == NULL) {
861                         return 0;
862                 }
863         }
864
865         memcpy(&ipaddr, hp->h_addr, hp->h_length);
866
867         return ntohl(ipaddr);
868 }