1*8823STruong.Q.Nguyen@Sun.COM /*
2*8823STruong.Q.Nguyen@Sun.COM * CDDL HEADER START
3*8823STruong.Q.Nguyen@Sun.COM *
4*8823STruong.Q.Nguyen@Sun.COM * The contents of this file are subject to the terms of the
5*8823STruong.Q.Nguyen@Sun.COM * Common Development and Distribution License (the "License").
6*8823STruong.Q.Nguyen@Sun.COM * You may not use this file except in compliance with the License.
7*8823STruong.Q.Nguyen@Sun.COM *
8*8823STruong.Q.Nguyen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8823STruong.Q.Nguyen@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*8823STruong.Q.Nguyen@Sun.COM * See the License for the specific language governing permissions
11*8823STruong.Q.Nguyen@Sun.COM * and limitations under the License.
12*8823STruong.Q.Nguyen@Sun.COM *
13*8823STruong.Q.Nguyen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*8823STruong.Q.Nguyen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8823STruong.Q.Nguyen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*8823STruong.Q.Nguyen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*8823STruong.Q.Nguyen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*8823STruong.Q.Nguyen@Sun.COM *
19*8823STruong.Q.Nguyen@Sun.COM * CDDL HEADER END
20*8823STruong.Q.Nguyen@Sun.COM */
21*8823STruong.Q.Nguyen@Sun.COM
22*8823STruong.Q.Nguyen@Sun.COM /*
23*8823STruong.Q.Nguyen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*8823STruong.Q.Nguyen@Sun.COM * Use is subject to license terms.
25*8823STruong.Q.Nguyen@Sun.COM */
26*8823STruong.Q.Nguyen@Sun.COM
27*8823STruong.Q.Nguyen@Sun.COM /*
28*8823STruong.Q.Nguyen@Sun.COM * This file delivers /usr/lib/servinfo which provides description for
29*8823STruong.Q.Nguyen@Sun.COM * IANA and running RPC services. Given a IANA name or RPC program name
30*8823STruong.Q.Nguyen@Sun.COM * or number, the program uses getservbyname(3SOCKET) and rpcbind(3NSL)
31*8823STruong.Q.Nguyen@Sun.COM * to obtain port and proto information for the specified service.
32*8823STruong.Q.Nguyen@Sun.COM */
33*8823STruong.Q.Nguyen@Sun.COM
34*8823STruong.Q.Nguyen@Sun.COM #include <stdio.h>
35*8823STruong.Q.Nguyen@Sun.COM #include <stdlib.h>
36*8823STruong.Q.Nguyen@Sun.COM #include <strings.h>
37*8823STruong.Q.Nguyen@Sun.COM #include <netconfig.h>
38*8823STruong.Q.Nguyen@Sun.COM #include <netdb.h>
39*8823STruong.Q.Nguyen@Sun.COM #include <rpc/rpc.h>
40*8823STruong.Q.Nguyen@Sun.COM #include <rpc/rpcent.h>
41*8823STruong.Q.Nguyen@Sun.COM #include <sys/types.h>
42*8823STruong.Q.Nguyen@Sun.COM #include <netinet/in.h>
43*8823STruong.Q.Nguyen@Sun.COM #include <netdir.h>
44*8823STruong.Q.Nguyen@Sun.COM #include <inttypes.h>
45*8823STruong.Q.Nguyen@Sun.COM #include <limits.h>
46*8823STruong.Q.Nguyen@Sun.COM #include <libintl.h>
47*8823STruong.Q.Nguyen@Sun.COM #include <locale.h>
48*8823STruong.Q.Nguyen@Sun.COM
49*8823STruong.Q.Nguyen@Sun.COM #ifndef TEXT_DOMAIN
50*8823STruong.Q.Nguyen@Sun.COM #define TEXT_DOMAIN "SUNW_OST_OSCMD"
51*8823STruong.Q.Nguyen@Sun.COM #endif /* TEXT_DOMAIN */
52*8823STruong.Q.Nguyen@Sun.COM
53*8823STruong.Q.Nguyen@Sun.COM #define TCP "tcp"
54*8823STruong.Q.Nguyen@Sun.COM #define TCP6 "tcp6"
55*8823STruong.Q.Nguyen@Sun.COM #define UDP "udp"
56*8823STruong.Q.Nguyen@Sun.COM #define UDP6 "udp6"
57*8823STruong.Q.Nguyen@Sun.COM
58*8823STruong.Q.Nguyen@Sun.COM #define DEFAULT 0x1
59*8823STruong.Q.Nguyen@Sun.COM #define PORT 0x2
60*8823STruong.Q.Nguyen@Sun.COM #define PROTO 0x4
61*8823STruong.Q.Nguyen@Sun.COM
62*8823STruong.Q.Nguyen@Sun.COM #define NETID_LEN 12 /* length for a netid or 2^16 port value */
63*8823STruong.Q.Nguyen@Sun.COM
64*8823STruong.Q.Nguyen@Sun.COM static void
usage(char * arg0)65*8823STruong.Q.Nguyen@Sun.COM usage(char *arg0)
66*8823STruong.Q.Nguyen@Sun.COM {
67*8823STruong.Q.Nguyen@Sun.COM (void) fprintf(stderr, gettext("Usage: %s [-R] [-Pp] [-tu[6]] "
68*8823STruong.Q.Nguyen@Sun.COM "-s service_name\n"), arg0);
69*8823STruong.Q.Nguyen@Sun.COM }
70*8823STruong.Q.Nguyen@Sun.COM
71*8823STruong.Q.Nguyen@Sun.COM static rpcport_t
uaddr2port(char * addr)72*8823STruong.Q.Nguyen@Sun.COM uaddr2port(char *addr)
73*8823STruong.Q.Nguyen@Sun.COM {
74*8823STruong.Q.Nguyen@Sun.COM rpcport_t port = 0;
75*8823STruong.Q.Nguyen@Sun.COM char *dot, *p;
76*8823STruong.Q.Nguyen@Sun.COM
77*8823STruong.Q.Nguyen@Sun.COM if ((dot = strrchr(addr, '.')) == 0) {
78*8823STruong.Q.Nguyen@Sun.COM return (0);
79*8823STruong.Q.Nguyen@Sun.COM } else {
80*8823STruong.Q.Nguyen@Sun.COM if (dot == addr)
81*8823STruong.Q.Nguyen@Sun.COM return (0);
82*8823STruong.Q.Nguyen@Sun.COM
83*8823STruong.Q.Nguyen@Sun.COM p = dot - 1;
84*8823STruong.Q.Nguyen@Sun.COM while (*p != '.') {
85*8823STruong.Q.Nguyen@Sun.COM /*
86*8823STruong.Q.Nguyen@Sun.COM * If the first dot hasn't been seen, it's a
87*8823STruong.Q.Nguyen@Sun.COM * malformed universal address.
88*8823STruong.Q.Nguyen@Sun.COM */
89*8823STruong.Q.Nguyen@Sun.COM if (p == addr)
90*8823STruong.Q.Nguyen@Sun.COM return (0);
91*8823STruong.Q.Nguyen@Sun.COM p--;
92*8823STruong.Q.Nguyen@Sun.COM }
93*8823STruong.Q.Nguyen@Sun.COM
94*8823STruong.Q.Nguyen@Sun.COM port = strtol(p + 1, &dot, 10) << 8;
95*8823STruong.Q.Nguyen@Sun.COM port = port | strtol(dot + 1, (char **)NULL, 10);
96*8823STruong.Q.Nguyen@Sun.COM }
97*8823STruong.Q.Nguyen@Sun.COM
98*8823STruong.Q.Nguyen@Sun.COM return (port);
99*8823STruong.Q.Nguyen@Sun.COM }
100*8823STruong.Q.Nguyen@Sun.COM
101*8823STruong.Q.Nguyen@Sun.COM static int
svc_getrpcinfo(char * sname,char * sproto,int options)102*8823STruong.Q.Nguyen@Sun.COM svc_getrpcinfo(char *sname, char *sproto, int options)
103*8823STruong.Q.Nguyen@Sun.COM {
104*8823STruong.Q.Nguyen@Sun.COM struct netconfig *nconf;
105*8823STruong.Q.Nguyen@Sun.COM struct rpcblist *blist;
106*8823STruong.Q.Nguyen@Sun.COM int prognum = -1;
107*8823STruong.Q.Nguyen@Sun.COM rpcport_t rpc_port;
108*8823STruong.Q.Nguyen@Sun.COM struct rpcent rentry;
109*8823STruong.Q.Nguyen@Sun.COM struct rpcent *rpc;
110*8823STruong.Q.Nguyen@Sun.COM char line[LINE_MAX] = "";
111*8823STruong.Q.Nguyen@Sun.COM int line_len = LINE_MAX - 1;
112*8823STruong.Q.Nguyen@Sun.COM char buf[NETID_LEN];
113*8823STruong.Q.Nguyen@Sun.COM
114*8823STruong.Q.Nguyen@Sun.COM prognum = atoi(sname);
115*8823STruong.Q.Nguyen@Sun.COM if (prognum > 0)
116*8823STruong.Q.Nguyen@Sun.COM rpc = (struct rpcent *)getrpcbynumber(prognum);
117*8823STruong.Q.Nguyen@Sun.COM else
118*8823STruong.Q.Nguyen@Sun.COM rpc = (struct rpcent *)getrpcbyname(sname);
119*8823STruong.Q.Nguyen@Sun.COM
120*8823STruong.Q.Nguyen@Sun.COM /*
121*8823STruong.Q.Nguyen@Sun.COM * If an entry doesn't exist, it could be a running program
122*8823STruong.Q.Nguyen@Sun.COM * without a registered RPC entry.
123*8823STruong.Q.Nguyen@Sun.COM */
124*8823STruong.Q.Nguyen@Sun.COM if (rpc == NULL) {
125*8823STruong.Q.Nguyen@Sun.COM if (prognum <= 0) {
126*8823STruong.Q.Nguyen@Sun.COM (void) fprintf(stderr,
127*8823STruong.Q.Nguyen@Sun.COM gettext("Can't get rpc entry\n"));
128*8823STruong.Q.Nguyen@Sun.COM return (1);
129*8823STruong.Q.Nguyen@Sun.COM }
130*8823STruong.Q.Nguyen@Sun.COM
131*8823STruong.Q.Nguyen@Sun.COM rpc = &rentry;
132*8823STruong.Q.Nguyen@Sun.COM rpc->r_number = prognum;
133*8823STruong.Q.Nguyen@Sun.COM rpc->r_name = sname;
134*8823STruong.Q.Nguyen@Sun.COM }
135*8823STruong.Q.Nguyen@Sun.COM
136*8823STruong.Q.Nguyen@Sun.COM if (setnetconfig() == NULL) {
137*8823STruong.Q.Nguyen@Sun.COM (void) fprintf(stderr, gettext("setnetconfig failed\n"));
138*8823STruong.Q.Nguyen@Sun.COM return (1);
139*8823STruong.Q.Nguyen@Sun.COM }
140*8823STruong.Q.Nguyen@Sun.COM
141*8823STruong.Q.Nguyen@Sun.COM if ((nconf = getnetconfigent(TCP)) == NULL) {
142*8823STruong.Q.Nguyen@Sun.COM (void) fprintf(stderr, gettext("getnetconfig failed\n"));
143*8823STruong.Q.Nguyen@Sun.COM return (1);
144*8823STruong.Q.Nguyen@Sun.COM }
145*8823STruong.Q.Nguyen@Sun.COM
146*8823STruong.Q.Nguyen@Sun.COM if ((blist = (struct rpcblist *)rpcb_getmaps(nconf, "localhost"))
147*8823STruong.Q.Nguyen@Sun.COM == NULL) {
148*8823STruong.Q.Nguyen@Sun.COM (void) fprintf(stderr,
149*8823STruong.Q.Nguyen@Sun.COM gettext("Failed: rpcb_getmaps failed\n"));
150*8823STruong.Q.Nguyen@Sun.COM return (1);
151*8823STruong.Q.Nguyen@Sun.COM }
152*8823STruong.Q.Nguyen@Sun.COM
153*8823STruong.Q.Nguyen@Sun.COM for (; blist != NULL; blist = blist->rpcb_next) {
154*8823STruong.Q.Nguyen@Sun.COM if (blist->rpcb_map.r_prog != rpc->r_number)
155*8823STruong.Q.Nguyen@Sun.COM continue;
156*8823STruong.Q.Nguyen@Sun.COM
157*8823STruong.Q.Nguyen@Sun.COM if (sproto) {
158*8823STruong.Q.Nguyen@Sun.COM if (strcmp(blist->rpcb_map.r_netid, sproto) != 0)
159*8823STruong.Q.Nguyen@Sun.COM continue;
160*8823STruong.Q.Nguyen@Sun.COM } else {
161*8823STruong.Q.Nguyen@Sun.COM if (strcmp(blist->rpcb_map.r_netid, UDP) &&
162*8823STruong.Q.Nguyen@Sun.COM strcmp(blist->rpcb_map.r_netid, UDP6) &&
163*8823STruong.Q.Nguyen@Sun.COM strcmp(blist->rpcb_map.r_netid, TCP) &&
164*8823STruong.Q.Nguyen@Sun.COM strcmp(blist->rpcb_map.r_netid, TCP6))
165*8823STruong.Q.Nguyen@Sun.COM continue;
166*8823STruong.Q.Nguyen@Sun.COM }
167*8823STruong.Q.Nguyen@Sun.COM rpc_port = uaddr2port(blist->rpcb_map.r_addr);
168*8823STruong.Q.Nguyen@Sun.COM
169*8823STruong.Q.Nguyen@Sun.COM if (options & DEFAULT) {
170*8823STruong.Q.Nguyen@Sun.COM (void) printf("Program %ld\n", blist->rpcb_map.r_prog);
171*8823STruong.Q.Nguyen@Sun.COM (void) printf("Protocol %s\n", blist->rpcb_map.r_netid);
172*8823STruong.Q.Nguyen@Sun.COM (void) printf("Port %ld\n", rpc_port);
173*8823STruong.Q.Nguyen@Sun.COM (void) printf("Version %ld\n", blist->rpcb_map.r_vers);
174*8823STruong.Q.Nguyen@Sun.COM (void) printf("Name %s\n", rpc->r_name);
175*8823STruong.Q.Nguyen@Sun.COM
176*8823STruong.Q.Nguyen@Sun.COM } else if (options & PROTO) {
177*8823STruong.Q.Nguyen@Sun.COM if (strstr(line, blist->rpcb_map.r_netid))
178*8823STruong.Q.Nguyen@Sun.COM continue;
179*8823STruong.Q.Nguyen@Sun.COM
180*8823STruong.Q.Nguyen@Sun.COM (void) snprintf(buf, sizeof (buf), "%5s ",
181*8823STruong.Q.Nguyen@Sun.COM blist->rpcb_map.r_netid);
182*8823STruong.Q.Nguyen@Sun.COM
183*8823STruong.Q.Nguyen@Sun.COM if (strlen(buf) > line_len)
184*8823STruong.Q.Nguyen@Sun.COM continue;
185*8823STruong.Q.Nguyen@Sun.COM
186*8823STruong.Q.Nguyen@Sun.COM line_len = line_len - strlen(buf);
187*8823STruong.Q.Nguyen@Sun.COM (void) strlcat(line, buf, sizeof (line));
188*8823STruong.Q.Nguyen@Sun.COM } else {
189*8823STruong.Q.Nguyen@Sun.COM (void) snprintf(buf, sizeof (buf), "%-7ld ", rpc_port);
190*8823STruong.Q.Nguyen@Sun.COM
191*8823STruong.Q.Nguyen@Sun.COM if (strstr(line, buf) || strlen(buf) > line_len)
192*8823STruong.Q.Nguyen@Sun.COM continue;
193*8823STruong.Q.Nguyen@Sun.COM
194*8823STruong.Q.Nguyen@Sun.COM line_len = line_len - strlen(buf);
195*8823STruong.Q.Nguyen@Sun.COM (void) strlcat(line, buf, sizeof (line));
196*8823STruong.Q.Nguyen@Sun.COM }
197*8823STruong.Q.Nguyen@Sun.COM }
198*8823STruong.Q.Nguyen@Sun.COM
199*8823STruong.Q.Nguyen@Sun.COM /*
200*8823STruong.Q.Nguyen@Sun.COM * Print the concatenated output if options is PROTO or PORT.
201*8823STruong.Q.Nguyen@Sun.COM */
202*8823STruong.Q.Nguyen@Sun.COM if (options & (PROTO | PORT))
203*8823STruong.Q.Nguyen@Sun.COM (void) puts(line);
204*8823STruong.Q.Nguyen@Sun.COM
205*8823STruong.Q.Nguyen@Sun.COM return (0);
206*8823STruong.Q.Nguyen@Sun.COM }
207*8823STruong.Q.Nguyen@Sun.COM
208*8823STruong.Q.Nguyen@Sun.COM int
main(int argc,char * argv[])209*8823STruong.Q.Nguyen@Sun.COM main(int argc, char *argv[])
210*8823STruong.Q.Nguyen@Sun.COM {
211*8823STruong.Q.Nguyen@Sun.COM struct servent *service;
212*8823STruong.Q.Nguyen@Sun.COM char *sname = NULL;
213*8823STruong.Q.Nguyen@Sun.COM char *sproto = NULL;
214*8823STruong.Q.Nguyen@Sun.COM int options = DEFAULT;
215*8823STruong.Q.Nguyen@Sun.COM int c, isrpc = 0, v6_flag = 0;
216*8823STruong.Q.Nguyen@Sun.COM
217*8823STruong.Q.Nguyen@Sun.COM (void) setlocale(LC_ALL, "");
218*8823STruong.Q.Nguyen@Sun.COM (void) textdomain(TEXT_DOMAIN);
219*8823STruong.Q.Nguyen@Sun.COM
220*8823STruong.Q.Nguyen@Sun.COM optind = 1;
221*8823STruong.Q.Nguyen@Sun.COM opterr = 1;
222*8823STruong.Q.Nguyen@Sun.COM while ((c = getopt(argc, argv, "s:PplRtu6?")) != -1) {
223*8823STruong.Q.Nguyen@Sun.COM switch (c) {
224*8823STruong.Q.Nguyen@Sun.COM case 's':
225*8823STruong.Q.Nguyen@Sun.COM sname = optarg;
226*8823STruong.Q.Nguyen@Sun.COM break;
227*8823STruong.Q.Nguyen@Sun.COM case 't':
228*8823STruong.Q.Nguyen@Sun.COM sproto = TCP;
229*8823STruong.Q.Nguyen@Sun.COM break;
230*8823STruong.Q.Nguyen@Sun.COM case 'u':
231*8823STruong.Q.Nguyen@Sun.COM sproto = UDP;
232*8823STruong.Q.Nguyen@Sun.COM break;
233*8823STruong.Q.Nguyen@Sun.COM case '6':
234*8823STruong.Q.Nguyen@Sun.COM v6_flag = 1;
235*8823STruong.Q.Nguyen@Sun.COM break;
236*8823STruong.Q.Nguyen@Sun.COM case 'P':
237*8823STruong.Q.Nguyen@Sun.COM options = PROTO;
238*8823STruong.Q.Nguyen@Sun.COM break;
239*8823STruong.Q.Nguyen@Sun.COM case 'p':
240*8823STruong.Q.Nguyen@Sun.COM options = PORT;
241*8823STruong.Q.Nguyen@Sun.COM break;
242*8823STruong.Q.Nguyen@Sun.COM case 'R':
243*8823STruong.Q.Nguyen@Sun.COM isrpc = 1;
244*8823STruong.Q.Nguyen@Sun.COM break;
245*8823STruong.Q.Nguyen@Sun.COM default:
246*8823STruong.Q.Nguyen@Sun.COM usage(argv[0]);
247*8823STruong.Q.Nguyen@Sun.COM return (1);
248*8823STruong.Q.Nguyen@Sun.COM }
249*8823STruong.Q.Nguyen@Sun.COM }
250*8823STruong.Q.Nguyen@Sun.COM if (sname == NULL) {
251*8823STruong.Q.Nguyen@Sun.COM usage(argv[0]);
252*8823STruong.Q.Nguyen@Sun.COM return (1);
253*8823STruong.Q.Nguyen@Sun.COM }
254*8823STruong.Q.Nguyen@Sun.COM
255*8823STruong.Q.Nguyen@Sun.COM /*
256*8823STruong.Q.Nguyen@Sun.COM * Specified service is an RPC service.
257*8823STruong.Q.Nguyen@Sun.COM */
258*8823STruong.Q.Nguyen@Sun.COM if (isrpc) {
259*8823STruong.Q.Nguyen@Sun.COM if (sproto && v6_flag) {
260*8823STruong.Q.Nguyen@Sun.COM if (strcmp(sproto, TCP) == 0)
261*8823STruong.Q.Nguyen@Sun.COM sproto = TCP6;
262*8823STruong.Q.Nguyen@Sun.COM if (strcmp(sproto, UDP) == 0)
263*8823STruong.Q.Nguyen@Sun.COM sproto = UDP6;
264*8823STruong.Q.Nguyen@Sun.COM }
265*8823STruong.Q.Nguyen@Sun.COM
266*8823STruong.Q.Nguyen@Sun.COM return (svc_getrpcinfo(sname, sproto, options));
267*8823STruong.Q.Nguyen@Sun.COM }
268*8823STruong.Q.Nguyen@Sun.COM
269*8823STruong.Q.Nguyen@Sun.COM if ((service = getservbyname(sname, sproto)) == NULL) {
270*8823STruong.Q.Nguyen@Sun.COM (void) fprintf(stderr, gettext(
271*8823STruong.Q.Nguyen@Sun.COM "Failed to get information for %s\n"), sname);
272*8823STruong.Q.Nguyen@Sun.COM return (1);
273*8823STruong.Q.Nguyen@Sun.COM }
274*8823STruong.Q.Nguyen@Sun.COM
275*8823STruong.Q.Nguyen@Sun.COM if (options & DEFAULT) {
276*8823STruong.Q.Nguyen@Sun.COM (void) printf("Name %s\n", service->s_name);
277*8823STruong.Q.Nguyen@Sun.COM (void) printf("Protocol %s\n", service->s_proto);
278*8823STruong.Q.Nguyen@Sun.COM (void) printf("Port %d\n", htons(service->s_port));
279*8823STruong.Q.Nguyen@Sun.COM } else if (options & PROTO)
280*8823STruong.Q.Nguyen@Sun.COM (void) printf("%s\n", service->s_proto);
281*8823STruong.Q.Nguyen@Sun.COM else
282*8823STruong.Q.Nguyen@Sun.COM (void) printf("%d\n", htons(service->s_port));
283*8823STruong.Q.Nguyen@Sun.COM
284*8823STruong.Q.Nguyen@Sun.COM return (0);
285*8823STruong.Q.Nguyen@Sun.COM }
286