Libinfo-173.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_bootp.c
1 /*
2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Bootp lookup - netinfo only
27 * Copyright (C) 1989 by NeXT, Inc.
28 */
29 #include <mach/mach.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <rpc/types.h>
34 #include <rpc/xdr.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <net/if.h>
39 #include <netinet/if_ether.h>
40 #include <net/ethernet.h>
41 #include <pthread.h>
42
43 #include "_lu_types.h"
44 #include "lookup.h"
45 #include "lu_utils.h"
46
47 extern struct ether_addr *ether_aton(char *);
48
49 static pthread_mutex_t _bootp_lock = PTHREAD_MUTEX_INITIALIZER;
50
51 struct bootpent
52 {
53 char *b_name;
54 struct ether_addr b_enaddr;
55 struct in_addr b_ipaddr;
56 char *b_bootfile;
57 };
58
59 static void
60 free_bootp(struct bootpent *b)
61 {
62 if (b == NULL) return;
63
64 if (b->b_name != NULL) free(b->b_name);
65 if (b->b_bootfile != NULL) free(b->b_bootfile);
66
67 free(b);
68 }
69
70 static struct bootpent *
71 extract_bootp(XDR *xdr)
72 {
73 struct bootpent *b;
74 struct ether_addr *e;
75 int i, j, nvals, nkeys, status;
76 char *key, **vals;
77
78 if (xdr == NULL) return NULL;
79
80 if (!xdr_int(xdr, &nkeys)) return NULL;
81
82 b = (struct bootpent *)calloc(1, sizeof(struct bootpent));
83
84 for (i = 0; i < nkeys; i++)
85 {
86 key = NULL;
87 vals = NULL;
88 nvals = 0;
89
90 status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
91 if (status < 0)
92 {
93 free_bootp(b);
94 return NULL;
95 }
96
97 if (nvals == 0)
98 {
99 free(key);
100 continue;
101 }
102
103 j = 0;
104
105 if ((b->b_name == NULL) && (!strcmp("name", key)))
106 {
107 b->b_name = vals[0];
108 j = 1;
109 }
110 if ((b->b_name == NULL) && (!strcmp("bootfile", key)))
111 {
112 b->b_bootfile = vals[0];
113 j = 1;
114 }
115 else if (!strcmp("ip_address", key))
116 {
117 b->b_ipaddr.s_addr = inet_addr(vals[0]);
118 }
119 else if (!strcmp("en_address", key))
120 {
121 pthread_mutex_lock(&_bootp_lock);
122 e = ether_aton(vals[0]);
123 if (e != NULL) memcpy(&(b->b_enaddr), e, sizeof(struct ether_addr));
124 pthread_mutex_unlock(&_bootp_lock);
125 j = 1;
126 }
127
128 free(key);
129 if (vals != NULL)
130 {
131 for (; j < nvals; j++) free(vals[j]);
132 free(vals);
133 }
134 }
135
136 if (b->b_name == NULL) b->b_name = strdup("");
137 if (b->b_bootfile == NULL) b->b_bootfile = strdup("");
138
139 return b;
140 }
141
142 static int
143 lu_bootp_getbyether(struct ether_addr *enaddr, char **name,
144 struct in_addr *ipaddr, char **bootfile)
145 {
146 unsigned datalen;
147 XDR inxdr;
148 struct bootpent *b;
149 static int proc = -1;
150 char *lookup_buf;
151 int count;
152
153 if (proc < 0)
154 {
155 if (_lookup_link(_lu_port, "bootp_getbyether", &proc) != KERN_SUCCESS)
156 {
157 return 0;
158 }
159 }
160
161 datalen = 0;
162 lookup_buf = NULL;
163
164 if (_lookup_all(_lu_port, proc, (unit *)enaddr, ((sizeof(*enaddr) + sizeof(unit) - 1) / sizeof(unit)), &lookup_buf, &datalen) != KERN_SUCCESS)
165 {
166 return 0;
167 }
168
169 datalen *= BYTES_PER_XDR_UNIT;
170 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
171
172 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
173
174 count = 0;
175 if (!xdr_int(&inxdr, &count))
176 {
177 xdr_destroy(&inxdr);
178 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
179 return 0;
180 }
181
182 if (count == 0)
183 {
184 xdr_destroy(&inxdr);
185 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
186 return 0;
187 }
188
189 b = extract_bootp(&inxdr);
190 xdr_destroy(&inxdr);
191
192 *name = b->b_name;
193 *bootfile = b->b_bootfile;
194 ipaddr->s_addr = b->b_ipaddr.s_addr;
195
196 free(b);
197 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
198
199 return 1;
200 }
201
202 static int
203 lu_bootp_getbyip(struct ether_addr *enaddr, char **name,
204 struct in_addr *ipaddr, char **bootfile)
205 {
206 unsigned datalen;
207 XDR inxdr;
208 struct bootpent *b;
209 static int proc = -1;
210 char *lookup_buf;
211 int count;
212
213 if (proc < 0)
214 {
215 if (_lookup_link(_lu_port, "bootp_getbyip", &proc) != KERN_SUCCESS)
216 {
217 return 0;
218 }
219 }
220
221 datalen = 0;
222 lookup_buf = NULL;
223
224 if (_lookup_all(_lu_port, proc, (unit *)ipaddr, ((sizeof(*ipaddr) + sizeof(unit) - 1) / sizeof(unit)), &lookup_buf, &datalen) != KERN_SUCCESS)
225 {
226 return 0;
227 }
228
229 datalen *= BYTES_PER_XDR_UNIT;
230 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
231
232 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
233
234 count = 0;
235 if (!xdr_int(&inxdr, &count))
236 {
237 xdr_destroy(&inxdr);
238 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
239 return 0;
240 }
241
242 if (count == 0)
243 {
244 xdr_destroy(&inxdr);
245 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
246 return 0;
247 }
248
249 b = extract_bootp(&inxdr);
250 xdr_destroy(&inxdr);
251
252 *name = b->b_name;
253 *bootfile = b->b_bootfile;
254 memcpy(enaddr, &(b->b_enaddr), sizeof(struct ether_addr));
255
256 free(b);
257 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
258
259 return 1;
260 }
261
262 int
263 bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
264 {
265 if (_lu_running())
266 {
267 return (lu_bootp_getbyether(enaddr, name, ipaddr, bootfile));
268 }
269 return 0;
270 }
271
272 int
273 bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
274 {
275 if (_lu_running())
276 {
277 return (lu_bootp_getbyip(enaddr, name, ipaddr, bootfile));
278 }
279 return 0;
280 }
281