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