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) 1986-1992 by Sun Microsystems Inc. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <ctype.h> 29 #include <netdb.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <nss_dbdefs.h> 33 34 static int str2protoent(const char *, int, void *, 35 char *, int); 36 37 static int proto_stayopen; 38 /* 39 * Unsynchronized, but it affects only 40 * efficiency, not correctness 41 */ 42 43 static DEFINE_NSS_DB_ROOT(db_root); 44 static DEFINE_NSS_GETENT(context); 45 46 static void 47 _nss_initf_proto(nss_db_params_t *p) 48 { 49 p->name = NSS_DBNAM_PROTOCOLS; 50 p->default_config = NSS_DEFCONF_PROTOCOLS; 51 } 52 53 struct protoent * 54 getprotobyname_r(const char *name, struct protoent *result, 55 char *buffer, int buflen) 56 { 57 nss_XbyY_args_t arg; 58 nss_status_t res; 59 60 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent); 61 arg.key.name = name; 62 arg.stayopen = proto_stayopen; 63 res = nss_search(&db_root, _nss_initf_proto, 64 NSS_DBOP_PROTOCOLS_BYNAME, &arg); 65 arg.status = res; 66 (void) NSS_XbyY_FINI(&arg); 67 return ((struct protoent *)arg.returnval); 68 } 69 70 struct protoent * 71 getprotobynumber_r(int proto, struct protoent *result, char *buffer, int buflen) 72 { 73 nss_XbyY_args_t arg; 74 nss_status_t res; 75 76 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent); 77 arg.key.number = proto; 78 arg.stayopen = proto_stayopen; 79 res = nss_search(&db_root, _nss_initf_proto, 80 NSS_DBOP_PROTOCOLS_BYNUMBER, &arg); 81 arg.status = res; 82 (void) NSS_XbyY_FINI(&arg); 83 return ((struct protoent *)arg.returnval); 84 } 85 86 int 87 setprotoent(int stay) 88 { 89 proto_stayopen = stay; 90 nss_setent(&db_root, _nss_initf_proto, &context); 91 return (0); 92 } 93 94 int 95 endprotoent() 96 { 97 proto_stayopen = 0; 98 nss_endent(&db_root, _nss_initf_proto, &context); 99 nss_delete(&db_root); 100 return (0); 101 } 102 103 struct protoent * 104 getprotoent_r(struct protoent *result, char *buffer, int buflen) 105 { 106 nss_XbyY_args_t arg; 107 nss_status_t res; 108 109 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2protoent); 110 /* No stayopen flag; of course you stay open for iteration */ 111 res = nss_getent(&db_root, _nss_initf_proto, &context, &arg); 112 arg.status = res; 113 (void) NSS_XbyY_FINI(&arg); 114 return ((struct protoent *)arg.returnval); 115 } 116 117 /* 118 * Return values: 0 = success, 1 = parse error, 2 = erange ... 119 * The structure pointer passed in is a structure in the caller's space 120 * wherein the field pointers would be set to areas in the buffer if 121 * need be. instring and buffer should be separate areas. Let's not 122 * fight over crumbs. 123 */ 124 static int 125 str2protoent(const char *instr, int lenstr, 126 void *ent /* it is really (struct protoent *) */, 127 char *buffer, int buflen) 128 { 129 struct protoent *proto = (struct protoent *)ent; 130 const char *p, *numstart, *namestart, *limit; 131 int numlen, namelen = 0; 132 char numbuf[16]; 133 char *numend; 134 135 if ((instr >= buffer && (buffer + buflen) > instr) || 136 (buffer >= instr && (instr + lenstr) > buffer)) { 137 return (NSS_STR_PARSE_PARSE); 138 } 139 140 p = instr; 141 limit = p + lenstr; 142 143 while (p < limit && isspace(*p)) { 144 p++; 145 } 146 namestart = p; 147 while (p < limit && !isspace(*p)) { 148 p++; /* Skip over the canonical name */ 149 } 150 namelen = (int)(p - namestart); 151 152 if (buflen <= namelen) { /* not enough buffer */ 153 return (NSS_STR_PARSE_ERANGE); 154 } 155 (void) memcpy(buffer, namestart, namelen); 156 buffer[namelen] = '\0'; 157 proto->p_name = buffer; 158 159 while (p < limit && isspace(*p)) { 160 p++; 161 } 162 if (p >= limit) { 163 /* Syntax error -- no proto number */ 164 return (NSS_STR_PARSE_PARSE); 165 } 166 numstart = p; 167 do { 168 p++; /* Find the end of the proto number */ 169 } while (p < limit && !isspace(*p)); 170 numlen = (int)(p - numstart); 171 if (numlen >= (int)sizeof (numbuf)) { 172 /* Syntax error -- supposed number is too long */ 173 return (NSS_STR_PARSE_PARSE); 174 } 175 (void) memcpy(numbuf, numstart, (size_t)numlen); 176 numbuf[numlen] = '\0'; 177 proto->p_proto = (int)strtol(numbuf, &numend, 10); 178 if (*numend != '\0') { 179 /* Syntax error -- protocol number isn't a number */ 180 return (NSS_STR_PARSE_PARSE); 181 } 182 183 while (p < limit && isspace(*p)) { 184 p++; 185 } 186 /* 187 * Although nss_files_XY_all calls us with # stripped, 188 * we should be able to deal with it here in order to 189 * be more useful. 190 */ 191 if (p >= limit || *p == '#') { /* no aliases, no problem */ 192 char **ptr; 193 194 ptr = (char **)ROUND_UP(buffer + namelen + 1, 195 sizeof (char *)); 196 if ((char *)ptr >= buffer + buflen) { 197 /* hope they don't try to peek in */ 198 proto->p_aliases = 0; 199 return (NSS_STR_PARSE_ERANGE); 200 } else { 201 *ptr = 0; 202 proto->p_aliases = ptr; 203 return (NSS_STR_PARSE_SUCCESS); 204 } 205 } 206 proto->p_aliases = _nss_netdb_aliases(p, lenstr - (int)(p - instr), 207 buffer + namelen + 1, buflen - namelen - 1); 208 return (NSS_STR_PARSE_SUCCESS); 209 } 210