Libinfo-222.3.6.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 * 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 * Bootp lookup - netinfo only
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28 #include <mach/mach.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <rpc/types.h>
33 #include <rpc/xdr.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <net/if.h>
38 #include <netinet/if_ether.h>
39 #include <net/ethernet.h>
40 #include <pthread.h>
41
42 #include "_lu_types.h"
43 #include "lookup.h"
44 #include "lu_utils.h"
45
46 static pthread_mutex_t _bootp_lock = PTHREAD_MUTEX_INITIALIZER;
47
48 struct bootpent
49 {
50 char *b_name;
51 struct ether_addr b_enaddr;
52 struct in_addr b_ipaddr;
53 char *b_bootfile;
54 };
55
56 static void
57 free_bootp(struct bootpent *b)
58 {
59 if (b == NULL) return;
60
61 if (b->b_name != NULL) free(b->b_name);
62 if (b->b_bootfile != NULL) free(b->b_bootfile);
63
64 free(b);
65 }
66
67 static struct bootpent *
68 extract_bootp(XDR *xdr)
69 {
70 struct bootpent *b;
71 struct ether_addr *e;
72 int i, j, nvals, nkeys, status;
73 char *key, **vals;
74
75 if (xdr == NULL) return NULL;
76
77 if (!xdr_int(xdr, &nkeys)) return NULL;
78
79 b = (struct bootpent *)calloc(1, sizeof(struct bootpent));
80
81 for (i = 0; i < nkeys; i++)
82 {
83 key = NULL;
84 vals = NULL;
85 nvals = 0;
86
87 status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
88 if (status < 0)
89 {
90 free_bootp(b);
91 return NULL;
92 }
93
94 if (nvals == 0)
95 {
96 free(key);
97 continue;
98 }
99
100 j = 0;
101
102 if ((b->b_name == NULL) && (!strcmp("name", key)))
103 {
104 b->b_name = vals[0];
105 j = 1;
106 }
107 if ((b->b_name == NULL) && (!strcmp("bootfile", key)))
108 {
109 b->b_bootfile = vals[0];
110 j = 1;
111 }
112 else if (!strcmp("ip_address", key))
113 {
114 b->b_ipaddr.s_addr = inet_addr(vals[0]);
115 }
116 else if (!strcmp("en_address", key))
117 {
118 pthread_mutex_lock(&_bootp_lock);
119 e = ether_aton(vals[0]);
120 if (e != NULL) memcpy(&(b->b_enaddr), e, sizeof(struct ether_addr));
121 pthread_mutex_unlock(&_bootp_lock);
122 j = 1;
123 }
124
125 free(key);
126 if (vals != NULL)
127 {
128 for (; j < nvals; j++) free(vals[j]);
129 free(vals);
130 }
131 }
132
133 if (b->b_name == NULL) b->b_name = strdup("");
134 if (b->b_bootfile == NULL) b->b_bootfile = strdup("");
135
136 return b;
137 }
138
139 static int
140 lu_bootp_getbyether(struct ether_addr *enaddr, char **name,
141 struct in_addr *ipaddr, char **bootfile)
142 {
143 unsigned datalen;
144 XDR inxdr;
145 struct bootpent *b;
146 static int proc = -1;
147 char *lookup_buf;
148 int count;
149
150 if (proc < 0)
151 {
152 if (_lookup_link(_lu_port, "bootp_getbyether", &proc) != KERN_SUCCESS)
153 {
154 return 0;
155 }
156 }
157
158 datalen = 0;
159 lookup_buf = NULL;
160
161 if (_lookup_all(_lu_port, proc, (unit *)enaddr, ((sizeof(*enaddr) + sizeof(unit) - 1) / sizeof(unit)), &lookup_buf, &datalen) != KERN_SUCCESS)
162 {
163 return 0;
164 }
165
166 datalen *= BYTES_PER_XDR_UNIT;
167 if ((lookup_buf == NULL) || (datalen == 0)) return 0;
168
169 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
170
171 count = 0;
172 if (!xdr_int(&inxdr, &count))
173 {
174 xdr_destroy(&inxdr);
175 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
176 return 0;
177 }
178
179 if (count == 0)
180 {
181 xdr_destroy(&inxdr);
182 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
183 return 0;
184 }
185
186 b = extract_bootp(&inxdr);
187 xdr_destroy(&inxdr);
188
189 *name = b->b_name;
190 *bootfile = b->b_bootfile;
191 ipaddr->s_addr = b->b_ipaddr.s_addr;
192
193 free(b);
194 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
195
196 return 1;
197 }
198
199 static int
200 lu_bootp_getbyip(struct ether_addr *enaddr, char **name,
201 struct in_addr *ipaddr, char **bootfile)
202 {
203 unsigned datalen;
204 XDR inxdr;
205 struct bootpent *b;
206 static int proc = -1;
207 char *lookup_buf;
208 int count;
209
210 if (proc < 0)
211 {
212 if (_lookup_link(_lu_port, "bootp_getbyip", &proc) != KERN_SUCCESS)
213 {
214 return 0;
215 }
216 }
217
218 datalen = 0;
219 lookup_buf = NULL;
220
221 if (_lookup_all(_lu_port, proc, (unit *)ipaddr, ((sizeof(*ipaddr) + sizeof(unit) - 1) / sizeof(unit)), &lookup_buf, &datalen) != KERN_SUCCESS)
222 {
223 return 0;
224 }
225
226 datalen *= BYTES_PER_XDR_UNIT;
227 if ((lookup_buf == NULL) || (datalen == 0)) return 0;
228
229 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
230
231 count = 0;
232 if (!xdr_int(&inxdr, &count))
233 {
234 xdr_destroy(&inxdr);
235 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
236 return 0;
237 }
238
239 if (count == 0)
240 {
241 xdr_destroy(&inxdr);
242 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
243 return 0;
244 }
245
246 b = extract_bootp(&inxdr);
247 xdr_destroy(&inxdr);
248
249 *name = b->b_name;
250 *bootfile = b->b_bootfile;
251 memcpy(enaddr, &(b->b_enaddr), sizeof(struct ether_addr));
252
253 free(b);
254 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
255
256 return 1;
257 }
258
259 int
260 bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
261 {
262 if (_lu_running())
263 {
264 return (lu_bootp_getbyether(enaddr, name, ipaddr, bootfile));
265 }
266 return 0;
267 }
268
269 int
270 bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
271 {
272 if (_lu_running())
273 {
274 return (lu_bootp_getbyip(enaddr, name, ipaddr, bootfile));
275 }
276 return 0;
277 }
278