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