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