Libinfo-278.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_protocol.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Protocol lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28 #include <stdlib.h>
29 #include <mach/mach.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <netdb.h>
33 #include <netinet/in.h>
34 #include <pthread.h>
35 #include "lu_utils.h"
36
37 extern struct protoent *_old_getprotobynumber();
38 extern struct protoent *_old_getprotobyname();
39 extern struct protoent *_old_getprotoent();
40 extern void _old_setprotoent();
41 extern void _old_endprotoent();
42
43 static pthread_mutex_t _protocol_lock = PTHREAD_MUTEX_INITIALIZER;
44
45 #define PROTO_GET_NAME 1
46 #define PROTO_GET_NUM 2
47 #define PROTO_GET_ENT 3
48
49 #define ENTRY_SIZE sizeof(struct protoent)
50 #define ENTRY_KEY _li_data_key_protocol
51
52 static struct protoent *
53 copy_protocol(struct protoent *in)
54 {
55 if (in == NULL) return NULL;
56
57 return (struct protoent *)LI_ils_create("s*4", in->p_name, in->p_aliases, in->p_proto);
58 }
59
60 /*
61 * Extract the next protocol entry from a kvarray.
62 */
63 static void *
64 extract_protocol(kvarray_t *in)
65 {
66 struct protoent tmp;
67 uint32_t d, k, kcount;
68 char *empty[1];
69
70 if (in == NULL) return NULL;
71
72 d = in->curr;
73 in->curr++;
74
75 if (d >= in->count) return NULL;
76
77 empty[0] = NULL;
78 memset(&tmp, 0, ENTRY_SIZE);
79
80 kcount = in->dict[d].kcount;
81
82 for (k = 0; k < kcount; k++)
83 {
84 if (!strcmp(in->dict[d].key[k], "p_name"))
85 {
86 if (tmp.p_name != NULL) continue;
87 if (in->dict[d].vcount[k] == 0) continue;
88
89 tmp.p_name = (char *)in->dict[d].val[k][0];
90 }
91 else if (!strcmp(in->dict[d].key[k], "p_proto"))
92 {
93 if (in->dict[d].vcount[k] == 0) continue;
94 tmp.p_proto = atoi(in->dict[d].val[k][0]);
95 }
96 else if (!strcmp(in->dict[d].key[k], "p_aliases"))
97 {
98 if (tmp.p_aliases != NULL) continue;
99 if (in->dict[d].vcount[k] == 0) continue;
100
101 tmp.p_aliases = (char **)in->dict[d].val[k];
102 }
103 }
104
105 if (tmp.p_name == NULL) tmp.p_name = "";
106 if (tmp.p_aliases == NULL) tmp.p_aliases = empty;
107
108 return copy_protocol(&tmp);
109 }
110
111 /*
112 * Send a query to the system information daemon.
113 */
114 static struct protoent *
115 ds_getprotobynumber(uint32_t number)
116 {
117 static int proc = -1;
118 char val[16];
119
120 snprintf(val, sizeof(val), "%u", number);
121 return (struct protoent *)LI_getone("getprotobynumber", &proc, extract_protocol, "number", val);
122 }
123
124 /*
125 * Send a query to the system information daemon.
126 */
127 static struct protoent *
128 ds_getprotobyname(const char *name)
129 {
130 static int proc = -1;
131
132 return (struct protoent *)LI_getone("getprotobyname", &proc, extract_protocol, "name", name);
133 }
134
135 /*
136 * Clean up / initialize / reinitialize the kvarray used to hold a list of all protocol entries.
137 */
138 static void
139 ds_endprotoent()
140 {
141 LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY));
142 }
143
144 static void
145 ds_setprotoent()
146 {
147 ds_endprotoent();
148 }
149
150 static struct protoent *
151 ds_getprotoent()
152 {
153 static int proc = -1;
154
155 return (struct protoent *)LI_getent("getprotoent", &proc, extract_protocol, ENTRY_KEY, ENTRY_SIZE);
156 }
157
158 static struct protoent *
159 getproto(const char *name, int number, int source)
160 {
161 struct protoent *res = NULL;
162 struct li_thread_info *tdata;
163
164 tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
165 if (tdata == NULL) return NULL;
166
167 if (_ds_running())
168 {
169 switch (source)
170 {
171 case PROTO_GET_NAME:
172 res = ds_getprotobyname(name);
173 break;
174 case PROTO_GET_NUM:
175 res = ds_getprotobynumber(number);
176 break;
177 case PROTO_GET_ENT:
178 res = ds_getprotoent();
179 break;
180 default: res = NULL;
181 }
182 }
183 else
184 {
185 pthread_mutex_lock(&_protocol_lock);
186
187 switch (source)
188 {
189 case PROTO_GET_NAME:
190 res = copy_protocol(_old_getprotobyname(name));
191 break;
192 case PROTO_GET_NUM:
193 res = copy_protocol(_old_getprotobynumber(number));
194 break;
195 case PROTO_GET_ENT:
196 res = copy_protocol(_old_getprotoent());
197 break;
198 default: res = NULL;
199 }
200
201 pthread_mutex_unlock(&_protocol_lock);
202 }
203
204 LI_data_recycle(tdata, res, ENTRY_SIZE);
205 return (struct protoent *)tdata->li_entry;
206 }
207
208 struct protoent *
209 getprotobyname(const char *name)
210 {
211 return getproto(name, -2, PROTO_GET_NAME);
212 }
213
214 struct protoent *
215 getprotobynumber(int number)
216 {
217 return getproto(NULL, number, PROTO_GET_NUM);
218 }
219
220 struct protoent *
221 getprotoent(void)
222 {
223 return getproto(NULL, -2, PROTO_GET_ENT);
224 }
225
226 void
227 setprotoent(int stayopen)
228 {
229 if (_ds_running()) ds_setprotoent();
230 else _old_setprotoent(stayopen);
231 }
232
233 void
234 endprotoent(void)
235 {
236 if (_ds_running()) ds_endprotoent();
237 else _old_endprotoent();
238 }