1 /* $OpenBSD: nametoaddr.c,v 1.7 1999/07/20 04:49:55 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * Name to id translation routines used by the scanner. 24 * These functions are not time critical. 25 */ 26 27 #ifndef lint 28 static const char rcsid[] = 29 "@(#) $Header: /home/cvs/src/lib/libpcap/nametoaddr.c,v 1.7 1999/07/20 04:49:55 deraadt Exp $ (LBL)"; 30 #endif 31 32 #include <sys/param.h> 33 #include <sys/types.h> /* concession to AIX */ 34 #include <sys/socket.h> 35 #include <sys/time.h> 36 37 #ifdef __STDC__ 38 struct mbuf; 39 struct rtentry; 40 #endif 41 42 #include <net/if.h> 43 #include <netinet/in.h> 44 #include <netinet/if_ether.h> 45 #include <arpa/inet.h> 46 47 #include <ctype.h> 48 #include <errno.h> 49 #include <stdlib.h> 50 #include <memory.h> 51 #include <netdb.h> 52 #include <stdio.h> 53 54 #include "pcap-int.h" 55 56 #include "gencode.h" 57 #include <pcap-namedb.h> 58 59 #ifdef HAVE_OS_PROTO_H 60 #include "os-proto.h" 61 #endif 62 63 #ifndef NTOHL 64 #define NTOHL(x) (x) = ntohl(x) 65 #define NTOHS(x) (x) = ntohs(x) 66 #endif 67 68 static __inline int xdtoi(int); 69 70 /* 71 * Convert host name to internet address. 72 * Return 0 upon failure. 73 */ 74 bpf_u_int32 ** 75 pcap_nametoaddr(const char *name) 76 { 77 #ifndef h_addr 78 static bpf_u_int32 *hlist[2]; 79 #endif 80 bpf_u_int32 **p; 81 struct hostent *hp; 82 83 if ((hp = gethostbyname(name)) != NULL) { 84 #ifndef h_addr 85 hlist[0] = (bpf_u_int32 *)hp->h_addr; 86 NTOHL(hp->h_addr); 87 return hlist; 88 #else 89 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) 90 NTOHL(**p); 91 return (bpf_u_int32 **)hp->h_addr_list; 92 #endif 93 } 94 else 95 return 0; 96 } 97 98 /* 99 * Convert net name to internet address. 100 * Return 0 upon failure. 101 */ 102 bpf_u_int32 103 pcap_nametonetaddr(const char *name) 104 { 105 struct netent *np; 106 107 if ((np = getnetbyname(name)) != NULL) 108 return np->n_net; 109 else 110 return 0; 111 } 112 113 /* 114 * Convert a port name to its port and protocol numbers. 115 * We assume only TCP or UDP. 116 * Return 0 upon failure. 117 */ 118 int 119 pcap_nametoport(const char *name, int *port, int *proto) 120 { 121 struct servent *sp; 122 char *other; 123 124 sp = getservbyname(name, (char *)0); 125 if (sp != NULL) { 126 NTOHS(sp->s_port); 127 *port = sp->s_port; 128 *proto = pcap_nametoproto(sp->s_proto); 129 /* 130 * We need to check /etc/services for ambiguous entries. 131 * If we find the ambiguous entry, and it has the 132 * same port number, change the proto to PROTO_UNDEF 133 * so both TCP and UDP will be checked. 134 */ 135 if (*proto == IPPROTO_TCP) 136 other = "udp"; 137 else 138 other = "tcp"; 139 140 sp = getservbyname(name, other); 141 if (sp != 0) { 142 NTOHS(sp->s_port); 143 #ifdef notdef 144 if (*port != sp->s_port) 145 /* Can't handle ambiguous names that refer 146 to different port numbers. */ 147 warning("ambiguous port %s in /etc/services", 148 name); 149 #endif 150 *proto = PROTO_UNDEF; 151 } 152 return 1; 153 } 154 #if defined(ultrix) || defined(__osf__) 155 /* Special hack in case NFS isn't in /etc/services */ 156 if (strcmp(name, "nfs") == 0) { 157 *port = 2049; 158 *proto = PROTO_UNDEF; 159 return 1; 160 } 161 #endif 162 return 0; 163 } 164 165 int 166 pcap_nametoproto(const char *str) 167 { 168 struct protoent *p; 169 170 p = getprotobyname(str); 171 if (p != 0) 172 return p->p_proto; 173 else 174 return PROTO_UNDEF; 175 } 176 177 #include "ethertype.h" 178 179 struct eproto { 180 char *s; 181 u_short p; 182 }; 183 184 /* Static data base of ether protocol types. */ 185 struct eproto eproto_db[] = { 186 { "pup", ETHERTYPE_PUP }, 187 { "xns", ETHERTYPE_NS }, 188 { "ip", ETHERTYPE_IP }, 189 { "arp", ETHERTYPE_ARP }, 190 { "rarp", ETHERTYPE_REVARP }, 191 { "sprite", ETHERTYPE_SPRITE }, 192 { "mopdl", ETHERTYPE_MOPDL }, 193 { "moprc", ETHERTYPE_MOPRC }, 194 { "decnet", ETHERTYPE_DN }, 195 { "lat", ETHERTYPE_LAT }, 196 { "sca", ETHERTYPE_SCA }, 197 { "lanbridge", ETHERTYPE_LANBRIDGE }, 198 { "vexp", ETHERTYPE_VEXP }, 199 { "vprod", ETHERTYPE_VPROD }, 200 { "atalk", ETHERTYPE_ATALK }, 201 { "atalkarp", ETHERTYPE_AARP }, 202 { "loopback", ETHERTYPE_LOOPBACK }, 203 { "decdts", ETHERTYPE_DECDTS }, 204 { "decdns", ETHERTYPE_DECDNS }, 205 { (char *)0, 0 } 206 }; 207 208 int 209 pcap_nametoeproto(const char *s) 210 { 211 struct eproto *p = eproto_db; 212 213 while (p->s != 0) { 214 if (strcmp(p->s, s) == 0) 215 return p->p; 216 p += 1; 217 } 218 return PROTO_UNDEF; 219 } 220 221 /* Hex digit to integer. */ 222 static __inline int 223 xdtoi(c) 224 register int c; 225 { 226 if (isdigit(c)) 227 return c - '0'; 228 else if (islower(c)) 229 return c - 'a' + 10; 230 else 231 return c - 'A' + 10; 232 } 233 234 int 235 __pcap_atoin(const char *s, bpf_u_int32 *addr) 236 { 237 u_int n; 238 int len; 239 240 *addr = 0; 241 len = 0; 242 while (1) { 243 n = 0; 244 while (*s && *s != '.') 245 n = n * 10 + *s++ - '0'; 246 *addr <<= 8; 247 *addr |= n & 0xff; 248 len += 8; 249 if (*s == '\0') 250 return len; 251 ++s; 252 } 253 /* NOTREACHED */ 254 } 255 256 int 257 __pcap_atodn(const char *s, bpf_u_int32 *addr) 258 { 259 #define AREASHIFT 10 260 #define AREAMASK 0176000 261 #define NODEMASK 01777 262 263 u_int node, area; 264 265 if (sscanf((char *)s, "%d.%d", &area, &node) != 2) 266 bpf_error("malformed decnet address '%s'", s); 267 268 *addr = (area << AREASHIFT) & AREAMASK; 269 *addr |= (node & NODEMASK); 270 271 return(32); 272 } 273 274 /* 275 * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new 276 * ethernet address. Assumes 's' is well formed. 277 */ 278 u_char * 279 pcap_ether_aton(const char *s) 280 { 281 register u_char *ep, *e; 282 register u_int d; 283 284 e = ep = (u_char *)malloc(6); 285 286 while (*s) { 287 if (*s == ':') 288 s += 1; 289 d = xdtoi(*s++); 290 if (isxdigit(*s)) { 291 d <<= 4; 292 d |= xdtoi(*s++); 293 } 294 *ep++ = d; 295 } 296 297 return (e); 298 } 299 300 #ifndef HAVE_ETHER_HOSTTON 301 /* Roll our own */ 302 u_char * 303 pcap_ether_hostton(const char *name) 304 { 305 register struct pcap_etherent *ep; 306 register u_char *ap; 307 static FILE *fp = NULL; 308 static init = 0; 309 310 if (!init) { 311 fp = fopen(PCAP_ETHERS_FILE, "r"); 312 ++init; 313 if (fp == NULL) 314 return (NULL); 315 } else if (fp == NULL) 316 return (NULL); 317 else 318 rewind(fp); 319 320 while ((ep = pcap_next_etherent(fp)) != NULL) { 321 if (strcmp(ep->name, name) == 0) { 322 ap = (u_char *)malloc(6); 323 if (ap != NULL) { 324 memcpy(ap, ep->addr, 6); 325 return (ap); 326 } 327 break; 328 } 329 } 330 return (NULL); 331 } 332 #else 333 334 #ifndef sgi 335 extern int ether_hostton(char *, struct ether_addr *); 336 #endif 337 338 /* Use the os supplied routines */ 339 u_char * 340 pcap_ether_hostton(const char *name) 341 { 342 register u_char *ap; 343 u_char a[6]; 344 345 ap = NULL; 346 if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) { 347 ap = (u_char *)malloc(6); 348 if (ap != NULL) 349 memcpy((char *)ap, (char *)a, 6); 350 } 351 return (ap); 352 } 353 #endif 354 355 u_short 356 __pcap_nametodnaddr(const char *name) 357 { 358 #ifdef DECNETLIB 359 struct nodeent *getnodebyname(); 360 struct nodeent *nep; 361 unsigned short res; 362 363 nep = getnodebyname(name); 364 if (nep == ((struct nodeent *)0)) 365 bpf_error("unknown decnet host name '%s'\n", name); 366 367 memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); 368 return(res); 369 #else 370 bpf_error("decnet name support not included, '%s' cannot be translated\n", 371 name); 372 #ifdef lint 373 return 0; 374 #endif 375 #endif 376 } 377