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