Libinfo-278.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_network.c
1 /*
2 * Copyright (c) 1999-2002 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 * network 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 <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <pthread.h>
37 #include "lu_utils.h"
38
39 static pthread_mutex_t _network_lock = PTHREAD_MUTEX_INITIALIZER;
40
41 #define N_GET_NAME 1
42 #define N_GET_ADDR 2
43 #define N_GET_ENT 3
44
45 extern struct netent *_res_getnetbyaddr();
46 extern struct netent *_res_getnetbyname();
47 extern struct netent *_old_getnetbyaddr();
48 extern struct netent *_old_getnetbyname();
49 extern struct netent *_old_getnetent();
50 extern void _old_setnetent();
51 extern void _old_endnetent();
52
53 #define ENTRY_SIZE sizeof(struct netent)
54 #define ENTRY_KEY _li_data_key_network
55
56 static struct netent *
57 copy_network(struct netent *in)
58 {
59 if (in == NULL) return NULL;
60
61 return (struct netent *)LI_ils_create("s*44", in->n_name, in->n_aliases, in->n_addrtype, in->n_net);
62 }
63
64 /*
65 * Extract the next network entry from a kvarray.
66 */
67 static void *
68 extract_network(kvarray_t *in)
69 {
70 struct netent tmp;
71 uint32_t d, k, kcount;
72 char *empty[1];
73
74 if (in == NULL) return NULL;
75
76 d = in->curr;
77 in->curr++;
78
79 if (d >= in->count) return NULL;
80
81 empty[0] = NULL;
82 memset(&tmp, 0, ENTRY_SIZE);
83
84 tmp.n_addrtype = AF_INET;
85
86 kcount = in->dict[d].kcount;
87
88 for (k = 0; k < kcount; k++)
89 {
90 if (!strcmp(in->dict[d].key[k], "n_name"))
91 {
92 if (tmp.n_name != NULL) continue;
93 if (in->dict[d].vcount[k] == 0) continue;
94
95 tmp.n_name = (char *)in->dict[d].val[k][0];
96 }
97 else if (!strcmp(in->dict[d].key[k], "n_net"))
98 {
99 if (in->dict[d].vcount[k] == 0) continue;
100 tmp.n_net = inet_network(in->dict[d].val[k][0]);
101 }
102 else if (!strcmp(in->dict[d].key[k], "n_addrtype"))
103 {
104 if (in->dict[d].vcount[k] == 0) continue;
105 tmp.n_addrtype = atoi(in->dict[d].val[k][0]);
106 }
107 else if (!strcmp(in->dict[d].key[k], "n_aliases"))
108 {
109 if (tmp.n_aliases != NULL) continue;
110 if (in->dict[d].vcount[k] == 0) continue;
111
112 tmp.n_aliases = (char **)in->dict[d].val[k];
113 }
114 }
115
116 if (tmp.n_name == NULL) tmp.n_name = "";
117 if (tmp.n_aliases == NULL) tmp.n_aliases = empty;
118
119 return copy_network(&tmp);
120 }
121
122 static struct netent *
123 ds_getnetbyaddr(uint32_t addr, int type)
124 {
125 static int proc = -1;
126 unsigned char f1, f2, f3;
127 char val[64];
128
129 if (type != AF_INET) return NULL;
130
131 f1 = addr & 0xff;
132 addr >>= 8;
133 f2 = addr & 0xff;
134 addr >>= 8;
135 f3 = addr & 0xff;
136
137 if (f3 != 0) snprintf(val, sizeof(val), "%u.%u.%u", f3, f2, f1);
138 else if (f2 != 0) snprintf(val, sizeof(val), "%u.%u", f2, f1);
139 else snprintf(val, sizeof(val), "%u", f1);
140
141 return (struct netent *)LI_getone("getnetbyaddr", &proc, extract_network, "net", val);
142 }
143
144 static struct netent *
145 ds_getnetbyname(const char *name)
146 {
147 static int proc = -1;
148
149 return (struct netent *)LI_getone("getnetbyname", &proc, extract_network, "name", name);
150 }
151
152 static void
153 ds_endnetent()
154 {
155 LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY));
156 }
157
158 static void
159 ds_setnetent()
160 {
161 ds_endnetent();
162 }
163
164 static struct netent *
165 ds_getnetent()
166 {
167 static int proc = -1;
168
169 return (struct netent *)LI_getent("getnetent", &proc, extract_network, ENTRY_KEY, ENTRY_SIZE);
170 }
171
172 static struct netent *
173 getnet(const char *name, uint32_t addr, int type, int source)
174 {
175 struct netent *res = NULL;
176 struct li_thread_info *tdata;
177
178 tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
179 if (tdata == NULL) return NULL;
180
181 if (_ds_running())
182 {
183 switch (source)
184 {
185 case N_GET_NAME:
186 res = ds_getnetbyname(name);
187 break;
188 case N_GET_ADDR:
189 res = ds_getnetbyaddr(addr, type);
190 break;
191 case N_GET_ENT:
192 res = ds_getnetent();
193 break;
194 default: res = NULL;
195 }
196 }
197 else
198 {
199 pthread_mutex_lock(&_network_lock);
200
201 switch (source)
202 {
203 case N_GET_NAME:
204 res = copy_network(_old_getnetbyname(name));
205 break;
206 case N_GET_ADDR:
207 res = copy_network(_old_getnetbyaddr(addr, type));
208 break;
209 case N_GET_ENT:
210 res = copy_network(_old_getnetent());
211 break;
212 default: res = NULL;
213 }
214
215 pthread_mutex_unlock(&_network_lock);
216 }
217
218 LI_data_recycle(tdata, res, ENTRY_SIZE);
219 return (struct netent *)tdata->li_entry;
220 }
221
222 struct netent *
223 getnetbyaddr(uint32_t addr, int type)
224 {
225 return getnet(NULL, addr, type, N_GET_ADDR);
226 }
227
228 struct netent *
229 getnetbyname(const char *name)
230 {
231 return getnet(name, 0, 0, N_GET_NAME);
232 }
233
234 struct netent *
235 getnetent(void)
236 {
237 return getnet(NULL, 0, 0, N_GET_ENT);
238 }
239
240 void
241 setnetent(int stayopen)
242 {
243 if (_ds_running()) ds_setnetent();
244 else _old_setnetent(stayopen);
245 }
246
247 void
248 endnetent(void)
249 {
250 if (_ds_running()) ds_endnetent();
251 else _old_endnetent();
252 }