1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1991, 1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <ctype.h> 31 #include <sys/types.h> 32 #include <unistd.h> 33 #include <malloc.h> 34 #include <sys/socket.h> 35 #include <sys/sockio.h> 36 #include <arpa/inet.h> 37 #include <net/if.h> 38 #include <netinet/in.h> 39 #include <netinet/in_systm.h> 40 #include <netinet/if_ether.h> 41 #include <netinet/ip.h> 42 #include <netdb.h> 43 #include <string.h> 44 #include <signal.h> 45 #include <setjmp.h> 46 47 /* 48 * Note: If making changes to this file, check also the file 49 * cmd/cmd-inet/usr.sbin/snoop/snoop_ipaddr.c 50 * as it has the same functions there. 51 */ 52 static jmp_buf nisjmp; 53 54 #define MAXHASH 1024 /* must be a power of 2 */ 55 56 struct hostdata { 57 struct hostdata *h_next; 58 char *h_hostname; 59 int h_pktsout; 60 int h_pktsin; 61 }; 62 63 struct hostdata4 { 64 struct hostdata4 *h4_next; 65 char *h4_hostname; 66 int h4_pktsout; 67 int h4_pktsin; 68 struct in_addr h4_addr; 69 }; 70 71 struct hostdata6 { 72 struct hostdata6 *h6_next; 73 char *h6_hostname; 74 int h6_pktsout; 75 int h6_pktsin; 76 struct in6_addr h6_addr; 77 }; 78 79 static struct hostdata *addhost(int, void *, char *); 80 81 static struct hostdata4 *h_table4[MAXHASH]; 82 static struct hostdata6 *h_table6[MAXHASH]; 83 84 #define iphash(e) ((e) & (MAXHASH-1)) 85 86 /* ARGSUSED */ 87 static void 88 wakeup(int n) 89 { 90 longjmp(nisjmp, 1); 91 } 92 93 extern char *inet_ntoa(); 94 95 static struct hostdata * 96 iplookup(ipaddr) 97 struct in_addr *ipaddr; 98 { 99 register struct hostdata4 *h; 100 struct hostent *hp = NULL; 101 struct netent *np; 102 int error_num; 103 104 for (h = h_table4[iphash(ipaddr->s_addr)]; h; h = h->h4_next) { 105 if (h->h4_addr.s_addr == ipaddr->s_addr) 106 return ((struct hostdata *)h); 107 } 108 109 /* not found. Put it in */ 110 111 if (ipaddr->s_addr == htonl(INADDR_BROADCAST)) 112 return (addhost(AF_INET, ipaddr, "BROADCAST")); 113 if (ipaddr->s_addr == htonl(INADDR_ANY)) 114 return (addhost(AF_INET, ipaddr, "OLD-BROADCAST")); 115 116 /* 117 * Set an alarm here so we don't get held up by 118 * an unresponsive name server. 119 * Give it 3 sec to do its work. 120 */ 121 if (setjmp(nisjmp) == 0) { 122 (void) signal(SIGALRM, wakeup); 123 (void) alarm(3); 124 hp = getipnodebyaddr((char *)ipaddr, sizeof (struct in_addr), 125 AF_INET, &error_num); 126 if (hp == NULL && inet_lnaof(*ipaddr) == 0) { 127 np = getnetbyaddr(inet_netof(*ipaddr), AF_INET); 128 if (np) 129 return (addhost(AF_INET, ipaddr, np->n_name)); 130 } 131 (void) alarm(0); 132 } else { 133 hp = NULL; 134 } 135 136 return (addhost(AF_INET, ipaddr, hp ? hp->h_name : inet_ntoa(*ipaddr))); 137 } 138 139 static struct hostdata * 140 ip6lookup(ip6addr) 141 struct in6_addr *ip6addr; 142 { 143 struct hostdata6 *h; 144 struct hostent *hp = NULL; 145 int error_num; 146 char addrstr[INET6_ADDRSTRLEN]; 147 char *addname; 148 struct hostdata *retval; 149 150 for (h = h_table6[iphash(((uint32_t *)ip6addr)[3])]; h; 151 h = h->h6_next) { 152 if (IN6_ARE_ADDR_EQUAL(&h->h6_addr, ip6addr)) 153 return ((struct hostdata *)h); 154 } 155 156 /* not in the hash table, put it in */ 157 if (IN6_IS_ADDR_UNSPECIFIED(ip6addr)) 158 return (addhost(AF_INET6, ip6addr, "UNSPECIFIED")); 159 160 /* 161 * Set an alarm here so we don't get held up by 162 * an unresponsive name server. 163 * Give it 3 sec to do its work. 164 */ 165 if (setjmp(nisjmp) == 0) { 166 (void) signal(SIGALRM, wakeup); 167 (void) alarm(3); 168 hp = getipnodebyaddr(ip6addr, sizeof (struct in6_addr), 169 AF_INET6, &error_num); 170 (void) alarm(0); 171 } else { 172 hp = NULL; 173 } 174 175 if (hp != NULL) 176 addname = hp->h_name; 177 else { 178 (void) inet_ntop(AF_INET6, ip6addr, addrstr, INET6_ADDRSTRLEN); 179 addname = addrstr; 180 } 181 182 retval = addhost(AF_INET6, ip6addr, addname); 183 freehostent(hp); 184 return (retval); 185 } 186 187 static struct hostdata * 188 addhost(family, ipaddr, name) 189 int family; 190 void *ipaddr; 191 char *name; 192 { 193 register struct hostdata **hp, *n; 194 int hashval; 195 196 switch (family) { 197 case AF_INET: 198 n = (struct hostdata *)malloc(sizeof (struct hostdata4)); 199 if (n == NULL) 200 goto alloc_failed; 201 202 (void) memset(n, 0, sizeof (struct hostdata4)); 203 n->h_hostname = strdup(name); 204 if (n->h_hostname == NULL) 205 goto alloc_failed; 206 207 ((struct hostdata4 *)n)->h4_addr = *(struct in_addr *)ipaddr; 208 hashval = ((struct in_addr *)ipaddr)->s_addr; 209 hp = (struct hostdata **)&h_table4[iphash(hashval)]; 210 break; 211 case AF_INET6: 212 n = (struct hostdata *)malloc(sizeof (struct hostdata6)); 213 if (n == NULL) 214 goto alloc_failed; 215 216 (void) memset(n, 0, sizeof (struct hostdata6)); 217 n->h_hostname = strdup(name); 218 if (n->h_hostname == NULL) 219 goto alloc_failed; 220 221 (void) memcpy(&((struct hostdata6 *)n)->h6_addr, ipaddr, 222 sizeof (struct in6_addr)); 223 hashval = ((int *)ipaddr)[3]; 224 hp = (struct hostdata **)&h_table6[iphash(hashval)]; 225 break; 226 default: 227 (void) fprintf(stderr, 228 "nfslog: addhost ERROR: Unknown address family: %d", 229 family); 230 return (NULL); 231 } 232 233 n->h_next = *hp; 234 *hp = n; 235 236 return (n); 237 238 alloc_failed: 239 (void) fprintf(stderr, "addhost: no mem\n"); 240 if (n != NULL) 241 free(n); 242 return (NULL); 243 } 244 245 char * 246 addrtoname(void *sockp) 247 { 248 struct hostdata *hostp; 249 int family = ((struct sockaddr_in *)sockp)->sin_family; 250 251 switch (family) { 252 case AF_INET: 253 hostp = iplookup(&((struct sockaddr_in *)sockp)->sin_addr); 254 break; 255 case AF_INET6: 256 hostp = ip6lookup(&((struct sockaddr_in6 *)sockp)->sin6_addr); 257 break; 258 default: 259 (void) fprintf(stderr, "nfslog: ERROR: unknown address " \ 260 "family: %d\n", family); 261 hostp = NULL; 262 } 263 return ((hostp != NULL) ? hostp->h_hostname : NULL); 264 } 265