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 * files/getservent.c -- "files" backend for nsswitch "services" database 26 */ 27 28 #include <netdb.h> 29 #include "files_common.h" 30 #include <sys/types.h> 31 #include <netinet/in.h> 32 #include <inttypes.h> 33 #include <strings.h> 34 #include <ctype.h> 35 #include <stdlib.h> 36 37 static int 38 check_name(nss_XbyY_args_t *argp, const char *line, int linelen) 39 { 40 const char *limit, *linep, *keyp; 41 int name_match = 0; 42 43 linep = line; 44 limit = line + linelen; 45 keyp = argp->key.serv.serv.name; 46 47 /* compare name */ 48 while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 49 keyp++; 50 linep++; 51 } 52 if (*keyp == '\0' && linep < limit && isspace(*linep)) { 53 if (argp->key.serv.proto == NULL) 54 return (1); 55 else 56 name_match = 1; 57 } 58 59 /* skip remainder of the name, if any */ 60 while (linep < limit && !isspace(*linep)) 61 linep++; 62 /* skip the delimiting spaces */ 63 while (linep < limit && isspace(*linep)) 64 linep++; 65 /* skip port number */ 66 while (linep < limit && !isspace(*linep) && *linep != '/') 67 linep++; 68 if (linep == limit || *linep != '/') 69 return (0); 70 71 linep++; 72 if ((keyp = argp->key.serv.proto) == NULL) { 73 /* skip protocol */ 74 while (linep < limit && !isspace(*linep)) 75 linep++; 76 } else { 77 /* compare protocol */ 78 while (*keyp && linep < limit && !isspace(*linep) && 79 *keyp == *linep) { 80 keyp++; 81 linep++; 82 } 83 /* no protocol match */ 84 if (*keyp || (linep < limit && !isspace(*linep))) 85 return (0); 86 /* protocol and name match, return */ 87 if (name_match) 88 return (1); 89 /* protocol match but name yet to be matched, so continue */ 90 } 91 92 /* compare with the aliases */ 93 while (linep < limit) { 94 /* skip the delimiting spaces */ 95 while (linep < limit && isspace(*linep)) 96 linep++; 97 98 /* compare with the alias name */ 99 keyp = argp->key.serv.serv.name; 100 while (*keyp && linep < limit && !isspace(*linep) && 101 *keyp == *linep) { 102 keyp++; 103 linep++; 104 } 105 if (*keyp == '\0' && (linep == limit || isspace(*linep))) 106 return (1); 107 108 /* skip remainder of the alias name, if any */ 109 while (linep < limit && !isspace(*linep)) 110 linep++; 111 } 112 return (0); 113 } 114 115 static nss_status_t 116 getbyname(be, a) 117 files_backend_ptr_t be; 118 void *a; 119 { 120 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 121 122 return (_nss_files_XY_all(be, argp, 1, 123 argp->key.serv.serv.name, check_name)); 124 } 125 126 static int 127 check_port(nss_XbyY_args_t *argp, const char *line, int linelen) 128 { 129 const char *limit, *linep, *keyp, *numstart; 130 int numlen, s_port; 131 char numbuf[12], *numend; 132 133 linep = line; 134 limit = line + linelen; 135 136 /* skip name */ 137 while (linep < limit && !isspace(*linep)) 138 linep++; 139 /* skip the delimiting spaces */ 140 while (linep < limit && isspace(*linep)) 141 linep++; 142 143 /* compare port num */ 144 numstart = linep; 145 while (linep < limit && !isspace(*linep) && *linep != '/') 146 linep++; 147 if (linep == limit || *linep != '/') 148 return (0); 149 numlen = linep - numstart; 150 if (numlen == 0 || numlen >= sizeof (numbuf)) 151 return (0); 152 (void) memcpy(numbuf, numstart, numlen); 153 numbuf[numlen] = '\0'; 154 s_port = htons((int)strtol(numbuf, &numend, 10)); 155 if (*numend != '\0') 156 return (0); 157 if (s_port == argp->key.serv.serv.port) { 158 if ((keyp = argp->key.serv.proto) == NULL) 159 return (1); 160 } else 161 return (0); 162 163 /* compare protocol */ 164 linep++; 165 while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 166 keyp++; 167 linep++; 168 } 169 return (*keyp == '\0' && (linep == limit || isspace(*linep))); 170 } 171 172 static nss_status_t 173 getbyport(be, a) 174 files_backend_ptr_t be; 175 void *a; 176 { 177 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 178 char portstr[12]; 179 180 (void) snprintf(portstr, 12, "%d", ntohs(argp->key.serv.serv.port)); 181 return (_nss_files_XY_all(be, argp, 1, portstr, check_port)); 182 } 183 184 static files_backend_op_t serv_ops[] = { 185 _nss_files_destr, 186 _nss_files_endent, 187 _nss_files_setent, 188 _nss_files_getent_netdb, 189 getbyname, 190 getbyport 191 }; 192 193 /*ARGSUSED*/ 194 nss_backend_t * 195 _nss_files_services_constr(dummy1, dummy2, dummy3) 196 const char *dummy1, *dummy2, *dummy3; 197 { 198 return (_nss_files_constr(serv_ops, 199 sizeof (serv_ops) / sizeof (serv_ops[0]), 200 _PATH_SERVICES, 201 NSS_LINELEN_SERVICES, 202 NULL)); 203 } 204