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