]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libpcap/nametoaddr.c
Merge compiler-rt release_40 branch r292009.
[FreeBSD/FreeBSD.git] / contrib / libpcap / nametoaddr.c
1 /*
2  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Name to id translation routines used by the scanner.
22  * These functions are not time critical.
23  *
24  * $FreeBSD$
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef DECNETLIB
32 #include <sys/types.h>
33 #include <netdnet/dnetdb.h>
34 #endif
35
36 #ifdef WIN32
37 #include <pcap-stdinc.h>
38
39 #else /* WIN32 */
40
41 #include <sys/param.h>
42 #include <sys/types.h>                          /* concession to AIX */
43 #include <sys/socket.h>
44 #include <sys/time.h>
45
46 #include <netinet/in.h>
47 #endif /* WIN32 */
48
49 #ifndef WIN32
50 #ifdef HAVE_ETHER_HOSTTON
51 /*
52  * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
53  * ether_hostton()?
54  */
55 #ifdef HAVE_NETINET_IF_ETHER_H
56 struct mbuf;            /* Squelch compiler warnings on some platforms for */
57 struct rtentry;         /* declarations in <net/if.h> */
58 #include <net/if.h>     /* for "struct ifnet" in "struct arpcom" on Solaris */
59 #include <netinet/if_ether.h>
60 #endif /* HAVE_NETINET_IF_ETHER_H */
61 #ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
62 #include <netinet/ether.h>
63 #endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
64 #endif /* HAVE_ETHER_HOSTTON */
65 #include <arpa/inet.h>
66 #include <netdb.h>
67 #endif /* WIN32 */
68
69 #include <ctype.h>
70 #include <errno.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <stdio.h>
74
75 #include "pcap-int.h"
76
77 #include "gencode.h"
78 #include <pcap/namedb.h>
79
80 #ifdef HAVE_OS_PROTO_H
81 #include "os-proto.h"
82 #endif
83
84 #ifndef NTOHL
85 #define NTOHL(x) (x) = ntohl(x)
86 #define NTOHS(x) (x) = ntohs(x)
87 #endif
88
89 static inline int xdtoi(int);
90
91 /*
92  *  Convert host name to internet address.
93  *  Return 0 upon failure.
94  */
95 bpf_u_int32 **
96 pcap_nametoaddr(const char *name)
97 {
98 #ifndef h_addr
99         static bpf_u_int32 *hlist[2];
100 #endif
101         bpf_u_int32 **p;
102         struct hostent *hp;
103
104         if ((hp = gethostbyname(name)) != NULL) {
105 #ifndef h_addr
106                 hlist[0] = (bpf_u_int32 *)hp->h_addr;
107                 NTOHL(hp->h_addr);
108                 return hlist;
109 #else
110                 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
111                         NTOHL(**p);
112                 return (bpf_u_int32 **)hp->h_addr_list;
113 #endif
114         }
115         else
116                 return 0;
117 }
118
119 #ifdef INET6
120 struct addrinfo *
121 pcap_nametoaddrinfo(const char *name)
122 {
123         struct addrinfo hints, *res;
124         int error;
125
126         memset(&hints, 0, sizeof(hints));
127         hints.ai_family = PF_UNSPEC;
128         hints.ai_socktype = SOCK_STREAM;        /*not really*/
129         hints.ai_protocol = IPPROTO_TCP;        /*not really*/
130         error = getaddrinfo(name, NULL, &hints, &res);
131         if (error)
132                 return NULL;
133         else
134                 return res;
135 }
136 #endif /*INET6*/
137
138 /*
139  *  Convert net name to internet address.
140  *  Return 0 upon failure.
141  */
142 bpf_u_int32
143 pcap_nametonetaddr(const char *name)
144 {
145 #ifndef WIN32
146         struct netent *np;
147
148         if ((np = getnetbyname(name)) != NULL)
149                 return np->n_net;
150         else
151                 return 0;
152 #else
153         /*
154          * There's no "getnetbyname()" on Windows.
155          */
156         return 0;
157 #endif
158 }
159
160 /*
161  * Convert a port name to its port and protocol numbers.
162  * We assume only TCP or UDP.
163  * Return 0 upon failure.
164  */
165 int
166 pcap_nametoport(const char *name, int *port, int *proto)
167 {
168         struct servent *sp;
169         int tcp_port = -1;
170         int udp_port = -1;
171
172         /*
173          * We need to check /etc/services for ambiguous entries.
174          * If we find the ambiguous entry, and it has the
175          * same port number, change the proto to PROTO_UNDEF
176          * so both TCP and UDP will be checked.
177          */
178         sp = getservbyname(name, "tcp");
179         if (sp != NULL) tcp_port = ntohs(sp->s_port);
180         sp = getservbyname(name, "udp");
181         if (sp != NULL) udp_port = ntohs(sp->s_port);
182         if (tcp_port >= 0) {
183                 *port = tcp_port;
184                 *proto = IPPROTO_TCP;
185                 if (udp_port >= 0) {
186                         if (udp_port == tcp_port)
187                                 *proto = PROTO_UNDEF;
188 #ifdef notdef
189                         else
190                                 /* Can't handle ambiguous names that refer
191                                    to different port numbers. */
192                                 warning("ambiguous port %s in /etc/services",
193                                         name);
194 #endif
195                 }
196                 return 1;
197         }
198         if (udp_port >= 0) {
199                 *port = udp_port;
200                 *proto = IPPROTO_UDP;
201                 return 1;
202         }
203 #if defined(ultrix) || defined(__osf__)
204         /* Special hack in case NFS isn't in /etc/services */
205         if (strcmp(name, "nfs") == 0) {
206                 *port = 2049;
207                 *proto = PROTO_UNDEF;
208                 return 1;
209         }
210 #endif
211         return 0;
212 }
213
214 /*
215  * Convert a string in the form PPP-PPP, where correspond to ports, to
216  * a starting and ending port in a port range.
217  * Return 0 on failure.
218  */
219 int
220 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
221 {
222         u_int p1, p2;
223         char *off, *cpy;
224         int save_proto;
225
226         if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
227                 if ((cpy = strdup(name)) == NULL)
228                         return 0;
229
230                 if ((off = strchr(cpy, '-')) == NULL) {
231                         free(cpy);
232                         return 0;
233                 }
234
235                 *off = '\0';
236
237                 if (pcap_nametoport(cpy, port1, proto) == 0) {
238                         free(cpy);
239                         return 0;
240                 }
241                 save_proto = *proto;
242
243                 if (pcap_nametoport(off + 1, port2, proto) == 0) {
244                         free(cpy);
245                         return 0;
246                 }
247                 free(cpy);
248
249                 if (*proto != save_proto)
250                         *proto = PROTO_UNDEF;
251         } else {
252                 *port1 = p1;
253                 *port2 = p2;
254                 *proto = PROTO_UNDEF;
255         }
256
257         return 1;
258 }
259
260 int
261 pcap_nametoproto(const char *str)
262 {
263         struct protoent *p;
264
265         p = getprotobyname(str);
266         if (p != 0)
267                 return p->p_proto;
268         else
269                 return PROTO_UNDEF;
270 }
271
272 #include "ethertype.h"
273
274 struct eproto {
275         const char *s;
276         u_short p;
277 };
278
279 /* Static data base of ether protocol types. */
280 struct eproto eproto_db[] = {
281 #if 0
282         /* The FreeBSD elf linker generates a request to copy this array
283          * (including its size) when you link with -lpcap.  In order to
284          * not bump the major version number of this libpcap.so, we need
285          * to ensure that the array stays the same size.  Since PUP is
286          * likely never seen in real life any more, it's the first to
287          * be sacrificed (in favor of ip6).
288          */
289         { "pup", ETHERTYPE_PUP },
290 #endif
291         { "xns", ETHERTYPE_NS },
292         { "ip", ETHERTYPE_IP },
293 #ifdef INET6
294         { "ip6", ETHERTYPE_IPV6 },
295 #endif
296         { "arp", ETHERTYPE_ARP },
297         { "rarp", ETHERTYPE_REVARP },
298         { "sprite", ETHERTYPE_SPRITE },
299         { "mopdl", ETHERTYPE_MOPDL },
300         { "moprc", ETHERTYPE_MOPRC },
301         { "decnet", ETHERTYPE_DN },
302         { "lat", ETHERTYPE_LAT },
303         { "sca", ETHERTYPE_SCA },
304         { "lanbridge", ETHERTYPE_LANBRIDGE },
305         { "vexp", ETHERTYPE_VEXP },
306         { "vprod", ETHERTYPE_VPROD },
307         { "atalk", ETHERTYPE_ATALK },
308         { "atalkarp", ETHERTYPE_AARP },
309         { "loopback", ETHERTYPE_LOOPBACK },
310         { "decdts", ETHERTYPE_DECDTS },
311         { "decdns", ETHERTYPE_DECDNS },
312         { (char *)0, 0 }
313 };
314
315 int
316 pcap_nametoeproto(const char *s)
317 {
318         struct eproto *p = eproto_db;
319
320         while (p->s != 0) {
321                 if (strcmp(p->s, s) == 0)
322                         return p->p;
323                 p += 1;
324         }
325         return PROTO_UNDEF;
326 }
327
328 #include "llc.h"
329
330 /* Static data base of LLC values. */
331 static struct eproto llc_db[] = {
332         { "iso", LLCSAP_ISONS },
333         { "stp", LLCSAP_8021D },
334         { "ipx", LLCSAP_IPX },
335         { "netbeui", LLCSAP_NETBEUI },
336         { (char *)0, 0 }
337 };
338
339 int
340 pcap_nametollc(const char *s)
341 {
342         struct eproto *p = llc_db;
343
344         while (p->s != 0) {
345                 if (strcmp(p->s, s) == 0)
346                         return p->p;
347                 p += 1;
348         }
349         return PROTO_UNDEF;
350 }
351
352 /* Hex digit to integer. */
353 static inline int
354 xdtoi(c)
355         register int c;
356 {
357         if (isdigit(c))
358                 return c - '0';
359         else if (islower(c))
360                 return c - 'a' + 10;
361         else
362                 return c - 'A' + 10;
363 }
364
365 int
366 __pcap_atoin(const char *s, bpf_u_int32 *addr)
367 {
368         u_int n;
369         int len;
370
371         *addr = 0;
372         len = 0;
373         while (1) {
374                 n = 0;
375                 while (*s && *s != '.')
376                         n = n * 10 + *s++ - '0';
377                 *addr <<= 8;
378                 *addr |= n & 0xff;
379                 len += 8;
380                 if (*s == '\0')
381                         return len;
382                 ++s;
383         }
384         /* NOTREACHED */
385 }
386
387 int
388 __pcap_atodn(const char *s, bpf_u_int32 *addr)
389 {
390 #define AREASHIFT 10
391 #define AREAMASK 0176000
392 #define NODEMASK 01777
393
394         u_int node, area;
395
396         if (sscanf(s, "%d.%d", &area, &node) != 2)
397                 bpf_error("malformed decnet address '%s'", s);
398
399         *addr = (area << AREASHIFT) & AREAMASK;
400         *addr |= (node & NODEMASK);
401
402         return(32);
403 }
404
405 /*
406  * Convert 's', which can have the one of the forms:
407  *
408  *      "xx:xx:xx:xx:xx:xx"
409  *      "xx.xx.xx.xx.xx.xx"
410  *      "xx-xx-xx-xx-xx-xx"
411  *      "xxxx.xxxx.xxxx"
412  *      "xxxxxxxxxxxx"
413  *
414  * (or various mixes of ':', '.', and '-') into a new
415  * ethernet address.  Assumes 's' is well formed.
416  */
417 u_char *
418 pcap_ether_aton(const char *s)
419 {
420         register u_char *ep, *e;
421         register u_int d;
422
423         e = ep = (u_char *)malloc(6);
424         if (e == NULL)
425                 return (NULL);
426
427         while (*s) {
428                 if (*s == ':' || *s == '.' || *s == '-')
429                         s += 1;
430                 d = xdtoi(*s++);
431                 if (isxdigit((unsigned char)*s)) {
432                         d <<= 4;
433                         d |= xdtoi(*s++);
434                 }
435                 *ep++ = d;
436         }
437
438         return (e);
439 }
440
441 #ifndef HAVE_ETHER_HOSTTON
442 /* Roll our own */
443 u_char *
444 pcap_ether_hostton(const char *name)
445 {
446         register struct pcap_etherent *ep;
447         register u_char *ap;
448         static FILE *fp = NULL;
449         static int init = 0;
450
451         if (!init) {
452                 fp = fopen(PCAP_ETHERS_FILE, "r");
453                 ++init;
454                 if (fp == NULL)
455                         return (NULL);
456         } else if (fp == NULL)
457                 return (NULL);
458         else
459                 rewind(fp);
460
461         while ((ep = pcap_next_etherent(fp)) != NULL) {
462                 if (strcmp(ep->name, name) == 0) {
463                         ap = (u_char *)malloc(6);
464                         if (ap != NULL) {
465                                 memcpy(ap, ep->addr, 6);
466                                 return (ap);
467                         }
468                         break;
469                 }
470         }
471         return (NULL);
472 }
473 #else
474
475 #if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON
476 #ifndef HAVE_STRUCT_ETHER_ADDR
477 struct ether_addr {
478         unsigned char ether_addr_octet[6];
479 };
480 #endif
481 extern int ether_hostton(const char *, struct ether_addr *);
482 #endif
483
484 /* Use the os supplied routines */
485 u_char *
486 pcap_ether_hostton(const char *name)
487 {
488         register u_char *ap;
489         u_char a[6];
490
491         ap = NULL;
492         if (ether_hostton(name, (struct ether_addr *)a) == 0) {
493                 ap = (u_char *)malloc(6);
494                 if (ap != NULL)
495                         memcpy((char *)ap, (char *)a, 6);
496         }
497         return (ap);
498 }
499 #endif
500
501 u_short
502 __pcap_nametodnaddr(const char *name)
503 {
504 #ifdef  DECNETLIB
505         struct nodeent *getnodebyname();
506         struct nodeent *nep;
507         unsigned short res;
508
509         nep = getnodebyname(name);
510         if (nep == ((struct nodeent *)0))
511                 bpf_error("unknown decnet host name '%s'\n", name);
512
513         memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
514         return(res);
515 #else
516         bpf_error("decnet name support not included, '%s' cannot be translated\n",
517                 name);
518         return(0);
519 #endif
520 }