1 /** $MirOS: src/lib/libpcap/nametoaddr.c,v 1.4 2007/03/09 13:05:08 tg Exp $ */
2 /* $OpenBSD: nametoaddr.c,v 1.13 2006/01/11 07:31:46 jaredy Exp $ */
3
4 /*
5 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
6 * The Regents of the University of California. All rights reserved.
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 #include <sys/param.h>
29 #include <sys/socket.h>
30 #include <sys/time.h>
31
32 struct mbuf;
33 struct rtentry;
34
35 #include <net/if.h>
36 #include <netinet/in.h>
37 #include <netinet/if_ether.h>
38 #include <arpa/inet.h>
39 #ifdef INET6
40 #include <netdb.h>
41 #include <sys/socket.h>
42 #endif /*INET6*/
43
44 #include <ctype.h>
45 #include <errno.h>
46 #include <stdlib.h>
47 #include <memory.h>
48 #include <netdb.h>
49 #include <stdio.h>
50
51 #include "pcap-int.h"
52
53 #include "gencode.h"
54 #include <pcap-namedb.h>
55
56 #ifdef HAVE_OS_PROTO_H
57 #include "os-proto.h"
58 #endif
59
60 #ifndef NTOHL
61 #define NTOHL(x) (x) = ntohl(x)
62 #define NTOHS(x) (x) = ntohs(x)
63 #endif
64
65 static __inline int xdtoi(int);
66
67 /*
68 * Convert host name to internet address.
69 * Return 0 upon failure.
70 */
71 bpf_u_int32 **
pcap_nametoaddr(const char * name)72 pcap_nametoaddr(const char *name)
73 {
74 #ifndef h_addr
75 static bpf_u_int32 *hlist[2];
76 #endif
77 bpf_u_int32 **p;
78 struct hostent *hp;
79
80 if ((hp = gethostbyname(name)) != NULL) {
81 #ifndef h_addr
82 hlist[0] = (bpf_u_int32 *)hp->h_addr;
83 NTOHL(hp->h_addr);
84 return hlist;
85 #else
86 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
87 NTOHL(**p);
88 return (bpf_u_int32 **)hp->h_addr_list;
89 #endif
90 }
91 else
92 return 0;
93 }
94
95 #ifdef INET6
96 struct addrinfo *
pcap_nametoaddrinfo(const char * name)97 pcap_nametoaddrinfo(const char *name)
98 {
99 struct addrinfo hints, *res;
100 int error;
101
102 memset(&hints, 0, sizeof(hints));
103 hints.ai_family = PF_UNSPEC;
104 hints.ai_socktype = SOCK_STREAM; /*not really*/
105 error = getaddrinfo(name, NULL, &hints, &res);
106 if (error)
107 return NULL;
108 else
109 return res;
110 }
111 #endif /*INET6*/
112
113 /*
114 * Convert net name to internet address.
115 * Return 0 upon failure.
116 */
117 bpf_u_int32
pcap_nametonetaddr(const char * name)118 pcap_nametonetaddr(const char *name)
119 {
120 struct netent *np;
121
122 if ((np = getnetbyname(name)) != NULL)
123 return np->n_net;
124 else
125 return 0;
126 }
127
128 /*
129 * Convert a port name to its port and protocol numbers.
130 * We assume only TCP or UDP.
131 * Return 0 upon failure.
132 */
133 int
pcap_nametoport(const char * name,int * port,int * proto)134 pcap_nametoport(const char *name, int *port, int *proto)
135 {
136 struct servent *sp;
137 char *other;
138
139 sp = getservbyname(name, (char *)0);
140 if (sp != NULL) {
141 NTOHS(sp->s_port);
142 *port = sp->s_port;
143 *proto = pcap_nametoproto(sp->s_proto);
144 /*
145 * We need to check /etc/services for ambiguous entries.
146 * If we find the ambiguous entry, and it has the
147 * same port number, change the proto to PROTO_UNDEF
148 * so both TCP and UDP will be checked.
149 */
150 if (*proto == IPPROTO_TCP)
151 other = "udp";
152 else
153 other = "tcp";
154
155 sp = getservbyname(name, other);
156 if (sp != 0) {
157 NTOHS(sp->s_port);
158 #ifdef notdef
159 if (*port != sp->s_port)
160 /* Can't handle ambiguous names that refer
161 to different port numbers. */
162 warning("ambiguous port %s in /etc/services",
163 name);
164 #endif
165 *proto = PROTO_UNDEF;
166 }
167 return 1;
168 }
169 #if defined(ultrix) || defined(__osf__)
170 /* Special hack in case NFS isn't in /etc/services */
171 if (strcmp(name, "nfs") == 0) {
172 *port = 2049;
173 *proto = PROTO_UNDEF;
174 return 1;
175 }
176 #endif
177 return 0;
178 }
179
180 int
pcap_nametoproto(const char * str)181 pcap_nametoproto(const char *str)
182 {
183 struct protoent *p;
184
185 p = getprotobyname(str);
186 if (p != 0)
187 return p->p_proto;
188 else
189 return PROTO_UNDEF;
190 }
191
192 #include "ethertype.h"
193
194 struct eproto {
195 char *s;
196 u_short p;
197 };
198
199 /* Static data base of ether protocol types. */
200 struct eproto eproto_db[] = {
201 { "pup", ETHERTYPE_PUP },
202 { "xns", ETHERTYPE_NS },
203 { "ip", ETHERTYPE_IP },
204 #ifdef INET6
205 { "ip6", ETHERTYPE_IPV6 },
206 #endif
207 { "arp", ETHERTYPE_ARP },
208 { "rarp", ETHERTYPE_REVARP },
209 { "sprite", ETHERTYPE_SPRITE },
210 { "mopdl", ETHERTYPE_MOPDL },
211 { "moprc", ETHERTYPE_MOPRC },
212 { "decnet", ETHERTYPE_DN },
213 { "lat", ETHERTYPE_LAT },
214 { "sca", ETHERTYPE_SCA },
215 { "lanbridge", ETHERTYPE_LANBRIDGE },
216 { "vexp", ETHERTYPE_VEXP },
217 { "vprod", ETHERTYPE_VPROD },
218 { "atalk", ETHERTYPE_ATALK },
219 { "atalkarp", ETHERTYPE_AARP },
220 { "loopback", ETHERTYPE_LOOPBACK },
221 { "decdts", ETHERTYPE_DECDTS },
222 { "decdns", ETHERTYPE_DECDNS },
223 { (char *)0, 0 }
224 };
225
226 int
pcap_nametoeproto(const char * s)227 pcap_nametoeproto(const char *s)
228 {
229 struct eproto *p = eproto_db;
230
231 while (p->s != 0) {
232 if (strcmp(p->s, s) == 0)
233 return p->p;
234 p += 1;
235 }
236 return PROTO_UNDEF;
237 }
238
239 #include "llc.h"
240
241 /* Static data base of LLC values. */
242 static struct eproto llc_db[] = {
243 { "stp", LLCSAP_8021D },
244 { (char *)0, 0 }
245 };
246
247 int
pcap_nametollc(const char * s)248 pcap_nametollc(const char *s)
249 {
250 struct eproto *p = llc_db;
251
252 while (p->s != 0) {
253 if (strcmp(p->s, s) == 0)
254 return p->p;
255 p += 1;
256 }
257 return PROTO_UNDEF;
258 }
259
260 /* Hex digit to integer. */
261 static __inline int
xdtoi(c)262 xdtoi(c)
263 register int c;
264 {
265 if (isdigit(c))
266 return c - '0';
267 else if (islower(c))
268 return c - 'a' + 10;
269 else
270 return c - 'A' + 10;
271 }
272
273 int
__pcap_atoin(const char * s,bpf_u_int32 * addr)274 __pcap_atoin(const char *s, bpf_u_int32 *addr)
275 {
276 u_int n;
277 int len;
278
279 *addr = 0;
280 len = 0;
281 while (1) {
282 n = 0;
283 while (*s && *s != '.')
284 n = n * 10 + *s++ - '0';
285 *addr <<= 8;
286 *addr |= n & 0xff;
287 len += 8;
288 if (*s == '\0')
289 return len;
290 ++s;
291 }
292 /* NOTREACHED */
293 }
294
295 int
__pcap_atodn(const char * s,bpf_u_int32 * addr)296 __pcap_atodn(const char *s, bpf_u_int32 *addr)
297 {
298 #define AREASHIFT 10
299 #define AREAMASK 0176000
300 #define NODEMASK 01777
301
302 u_int node, area;
303
304 if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
305 bpf_error("malformed decnet address '%s'", s);
306
307 *addr = (area << AREASHIFT) & AREAMASK;
308 *addr |= (node & NODEMASK);
309
310 return(32);
311 }
312
313 /*
314 * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
315 * ethernet address. Assumes 's' is well formed.
316 */
317 u_char *
pcap_ether_aton(const char * s)318 pcap_ether_aton(const char *s)
319 {
320 register u_char *ep, *e;
321 register u_int d;
322
323 e = ep = (u_char *)malloc(6);
324 if (e == NULL)
325 bpf_error("malloc");
326
327 while (*s) {
328 if (*s == ':')
329 s += 1;
330 d = xdtoi(*s++);
331 if (isxdigit(*s)) {
332 d <<= 4;
333 d |= xdtoi(*s++);
334 }
335 *ep++ = d;
336 }
337
338 return (e);
339 }
340
341 #ifndef HAVE_ETHER_HOSTTON
342 /* Roll our own */
343 u_char *
pcap_ether_hostton(const char * name)344 pcap_ether_hostton(const char *name)
345 {
346 register struct pcap_etherent *ep;
347 register u_char *ap;
348 static FILE *fp = NULL;
349 static init = 0;
350
351 if (!init) {
352 fp = fopen(PCAP_ETHERS_FILE, "r");
353 ++init;
354 if (fp == NULL)
355 return (NULL);
356 } else if (fp == NULL)
357 return (NULL);
358 else
359 rewind(fp);
360
361 while ((ep = pcap_next_etherent(fp)) != NULL) {
362 if (strcmp(ep->name, name) == 0) {
363 ap = (u_char *)malloc(6);
364 if (ap != NULL) {
365 memcpy(ap, ep->addr, 6);
366 return (ap);
367 }
368 break;
369 }
370 }
371 return (NULL);
372 }
373 #else
374
375 /* Use the os supplied routines */
376 u_char *
pcap_ether_hostton(const char * name)377 pcap_ether_hostton(const char *name)
378 {
379 register u_char *ap;
380 u_char a[6];
381
382 ap = NULL;
383 if (ether_hostton(name, (struct ether_addr *)a) == 0) {
384 ap = (u_char *)malloc(6);
385 if (ap != NULL)
386 memcpy((char *)ap, (char *)a, 6);
387 }
388 return (ap);
389 }
390 #endif
391
392 u_short
__pcap_nametodnaddr(const char * name)393 __pcap_nametodnaddr(const char *name)
394 {
395 #ifdef DECNETLIB
396 struct nodeent *getnodebyname();
397 struct nodeent *nep;
398 unsigned short res;
399
400 nep = getnodebyname(name);
401 if (nep == ((struct nodeent *)0))
402 bpf_error("unknown decnet host name '%s'\n", name);
403
404 memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
405 return(res);
406 #else
407 bpf_error("decnet name support not included, '%s' cannot be translated\n",
408 name);
409 /* NOTREACHED */
410 #ifdef lint
411 /*
412 * Arguably, lint should assume that functions which don't return
413 * (i.e. that contain no return statements and whose ends are
414 * unreachable) actually return a value, so callers won't get
415 * warnings for using that value (since they won't actually
416 * be doing so). However, most lints don't seem to do that...
417 */
418 return (0);
419 #endif
420 #endif
421 }
422