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