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