xref: /illumos-gate/usr/src/cmd/fs.d/nfs/nfslog/nfslog_ipaddr.c (revision 6dde88b51419b99fe0aab8e56184c693945826b8)
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