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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <libintl.h>
35 #include <locale.h>
36 #include <libdscp.h>
37 
38 #if	!defined(TEXT_DOMAIN)
39 #define	TEXT_DOMAIN "SYS_TEST"
40 #endif
41 
42 #define	OPT_SP		1
43 #define	OPT_DOMAIN	2
44 
45 static void	usage(void);
46 static void	parse_options(int, char **, int *);
47 static int	get_address(int, char *);
48 static void	trace(char *, ...);
49 static void	err(char *, ...);
50 static char	*dscp_strerror(int);
51 
52 static int	verbose = 0;
53 
54 int
main(int argc,char ** argv)55 main(int argc, char **argv)
56 {
57 	int	options;
58 	char	saddr[INET_ADDRSTRLEN];
59 	char	daddr[INET_ADDRSTRLEN];
60 
61 	(void) setlocale(LC_ALL, "");
62 	(void) textdomain(TEXT_DOMAIN);
63 
64 	parse_options(argc, argv, &options);
65 
66 	/*
67 	 * Get the desired IP addresses.
68 	 */
69 	if ((options & OPT_SP) != 0) {
70 		trace(gettext("Looking up SP address...\n"));
71 		if (get_address(DSCP_ADDR_REMOTE, saddr) < 0) {
72 			err(gettext("SP Address lookup failed. Aborting.\n"));
73 			exit(-1);
74 		}
75 	}
76 	if ((options & OPT_DOMAIN) != 0) {
77 		trace(gettext("Looking up domain address...\n"));
78 		if (get_address(DSCP_ADDR_LOCAL, daddr) < 0) {
79 			err(gettext("Domain Address lookup failed. "
80 			    "Aborting.\n"));
81 			exit(-1);
82 		}
83 	}
84 
85 	/*
86 	 * Print the IP addresses.
87 	 */
88 	if (options == OPT_SP) {
89 		(void) printf("%s\n", saddr);
90 	} else if (options == OPT_DOMAIN) {
91 		(void) printf("%s\n", daddr);
92 	} else {
93 		(void) printf(gettext("Domain Address: %s\n"), daddr);
94 		(void) printf(gettext("SP Address: %s\n"), saddr);
95 	}
96 
97 	return (0);
98 }
99 
100 /*
101  * parse_options()
102  *
103  *	Parse the commandline options.
104  */
105 static void
parse_options(int argc,char ** argv,int * options)106 parse_options(int argc, char **argv, int *options)
107 {
108 	int		i;
109 	int		c;
110 	extern int	opterr;
111 	extern int	optopt;
112 
113 	/*
114 	 * Unless told otherwise, print everything.
115 	 */
116 	*options = (OPT_SP | OPT_DOMAIN);
117 
118 	/*
119 	 * Skip this routine if no options exist.
120 	 */
121 	if (argc == 1) {
122 		return;
123 	}
124 
125 	/*
126 	 * Scan for the -h option separately, so that
127 	 * other commandline options are ignored.
128 	 */
129 	for (i = 1; i < argc; i++) {
130 		if (strcmp(argv[i], "-h") == 0) {
131 			usage();
132 			exit(0);
133 		}
134 	}
135 
136 	/*
137 	 * Disable the built-in error reporting, so that
138 	 * error messages can be properly internationalized.
139 	 */
140 	opterr = 0;
141 
142 	/*
143 	 * The main loop for parsing options.
144 	 */
145 	while ((c = getopt(argc, argv, "vsd")) != -1) {
146 		switch (c) {
147 		case 'v':
148 			verbose = 1;
149 			break;
150 		case 's':
151 			if (*options == OPT_DOMAIN) {
152 				err(gettext("cannot use -s and -d together"));
153 				usage();
154 				exit(-1);
155 			}
156 			*options = OPT_SP;
157 			break;
158 		case 'd':
159 			if (*options == OPT_SP) {
160 				err(gettext("cannot use -s and -d together"));
161 				usage();
162 				exit(-1);
163 			}
164 			*options = OPT_DOMAIN;
165 			break;
166 		default:
167 			err(gettext("invalid option -%c"), optopt);
168 			usage();
169 			exit(-1);
170 		}
171 	}
172 }
173 
174 /*
175  * usage()
176  *
177  *	Print a brief synopsis of the program's usage.
178  */
179 static void
usage(void)180 usage(void)
181 {
182 	(void) printf(gettext("Usage:  prtdscp -h \n"));
183 	(void) printf(gettext("        prtdscp [-v] [-s|-d]\n"));
184 }
185 
186 /*
187  * get_address()
188  *
189  *	Retrieve a DSCP IP address using libdscp.
190  */
191 static int
get_address(int which,char * addr)192 get_address(int which, char *addr)
193 {
194 	int			len;
195 	int			error;
196 	struct sockaddr_in	*sin;
197 	struct sockaddr		saddr;
198 
199 	error = dscpAddr(0, which, &saddr, &len);
200 	if (error != DSCP_OK) {
201 		trace(gettext("dscpAddr() failed: %s"), dscp_strerror(error));
202 		return (-1);
203 	}
204 
205 	/* LINTED pointer cast may result in improper alignment */
206 	sin = (struct sockaddr_in *)&saddr;
207 	if (inet_ntop(AF_INET, &(sin->sin_addr), addr, sizeof (*sin)) == NULL) {
208 		trace(gettext("address string conversion failed."));
209 		return (-1);
210 	}
211 
212 	return (0);
213 }
214 
215 /*
216  * trace()
217  *
218  *	Print tracing statements to stderr when in verbose mode.
219  */
220 /*PRINTFLIKE1*/
221 static void
trace(char * fmt,...)222 trace(char *fmt, ...)
223 {
224 	va_list	args;
225 
226 	if (verbose != 0) {
227 		va_start(args, fmt);
228 		(void) vfprintf(stderr, fmt, args);
229 		va_end(args);
230 	}
231 }
232 
233 /*
234  * err()
235  *
236  *	Print error messages to stderr.
237  */
238 /*PRINTFLIKE1*/
239 static void
err(char * fmt,...)240 err(char *fmt, ...)
241 {
242 	va_list	args;
243 
244 	va_start(args, fmt);
245 
246 	(void) fprintf(stderr, gettext("ERROR: "));
247 	(void) vfprintf(stderr, fmt, args);
248 	(void) fprintf(stderr, "\n");
249 
250 	va_end(args);
251 }
252 
253 /*
254  * dscp_strerror()
255  *
256  *	Convert a DSCP error value into a localized string.
257  */
258 static char *
dscp_strerror(int error)259 dscp_strerror(int error)
260 {
261 	switch (error) {
262 	case DSCP_OK:
263 		return (gettext("Success."));
264 	case DSCP_ERROR:
265 		return (gettext("General error."));
266 	case DSCP_ERROR_ALREADY:
267 		return (gettext("Socket already bound."));
268 	case DSCP_ERROR_INVALID:
269 		return (gettext("Invalid arguments."));
270 	case DSCP_ERROR_NOENT:
271 		return (gettext("No entry found."));
272 	case DSCP_ERROR_DB:
273 		return (gettext("Error reading database."));
274 	case DSCP_ERROR_REJECT:
275 		return (gettext("Connection rejected."));
276 	default:
277 		return (gettext("Unknown failure."));
278 	}
279 }
280