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