]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/ppp.c
configd-53.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / ppp.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * Feb 28, 2002 Christophe Allie <callie@apple.com>
27 * - socket API fixes
28 *
29 * Feb 10, 2001 Allan Nathanson <ajn@apple.com>
30 * - cleanup API
31 *
32 * Feb 2000 Christophe Allie <callie@apple.com>
33 * - initial revision (as ppplib.c)
34 */
35
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/errno.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42 #include <CoreFoundation/CoreFoundation.h>
43
44 #include <SystemConfiguration/SystemConfiguration.h>
45 #include <SystemConfiguration/SCPrivate.h>
46
47 #include "ppp_msg.h"
48 #include "ppp.h"
49
50
51 static int
52 readn(int ref, void *data, int len)
53 {
54 int left = len;
55 int n;
56 void *p = data;
57
58 while (left > 0) {
59 if ((n = read(ref, p, left)) < 0) {
60 if (errno != EINTR) {
61 return -1;
62 }
63 n = 0;
64 } else if (n == 0) {
65 break; /* EOF */
66 }
67
68 left -= n;
69 p += n;
70 }
71 return (len - left);
72 }
73
74
75 static int
76 writen(int ref, void *data, int len)
77 {
78 int left = len;
79 int n;
80 void *p = data;
81
82 while (left > 0) {
83 if ((n = write(ref, p, left)) <= 0) {
84 if (errno != EINTR) {
85 return -1;
86 }
87 n = 0;
88 }
89 left -= n;
90 p += n;
91 }
92 return len;
93 }
94
95
96 __private_extern__
97 int
98 PPPInit(int *ref)
99 {
100 int sock;
101 int status;
102 struct sockaddr_un sun;
103
104 sock = socket(AF_LOCAL, SOCK_STREAM, 0);
105
106 bzero(&sun, sizeof(sun));
107 sun.sun_family = AF_LOCAL;
108 strncpy(sun.sun_path, PPP_PATH, sizeof(sun.sun_path));
109
110 status = connect(sock, (struct sockaddr *)&sun, sizeof(sun));
111 if (status < 0) {
112 return errno;
113 }
114
115 *ref = sock;
116 return 0;
117 }
118
119
120 __private_extern__
121 int
122 PPPDispose(int ref)
123 {
124 if (close(ref) < 0) {
125 return errno;
126 }
127 return 0;
128 }
129
130
131 __private_extern__
132 int
133 PPPExec(int ref,
134 u_long link,
135 u_int32_t cmd,
136 void *request,
137 u_long requestLen,
138 void **reply,
139 u_long *replyLen)
140 {
141 struct ppp_msg_hdr msg;
142 char *buf = NULL;
143 ssize_t n;
144
145 bzero(&msg, sizeof(msg));
146 msg.m_type = cmd;
147 msg.m_link = link;
148 msg.m_len = ((request != NULL) && (requestLen > 0)) ? requestLen : 0;
149
150 // send the command
151 if (writen(ref, &msg, sizeof(msg)) < 0) {
152 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
153 return errno;
154 }
155
156 if ((request != NULL) && (requestLen > 0)) {
157 if (writen(ref, request, requestLen) < 0) {
158 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
159 return errno;
160 }
161 }
162
163 // always expect a reply
164 n = readn(ref, &msg, sizeof(msg));
165 if (n == -1) {
166 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
167 return errno;
168 } else if (n != sizeof(msg)) {
169 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n);
170 return -1;
171 }
172
173 if (msg.m_len) {
174 buf = CFAllocatorAllocate(NULL, msg.m_len, 0);
175 if (buf) {
176 // read reply
177 n = readn(ref, buf, msg.m_len);
178 if (n == -1) {
179 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
180 CFAllocatorDeallocate(NULL, buf);
181 return errno;
182 } else if (n != msg.m_len) {
183 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n);
184 CFAllocatorDeallocate(NULL, buf);
185 return -1;
186 }
187 }
188 }
189
190 if (reply && replyLen) {
191 *reply = buf;
192 *replyLen = msg.m_len;
193 } else if (buf) {
194 // if additional returned data is unwanted
195 CFAllocatorDeallocate(NULL, buf);
196 }
197
198 return msg.m_result;
199 }
200
201
202 #ifdef NOT_NEEDED
203 int
204 PPPConnect(int ref, u_long link)
205 {
206 int status;
207
208 status = PPPExec(ref,
209 link,
210 PPP_CONNECT,
211 NULL,
212 0,
213 NULL,
214 NULL);
215 if (status != 0) {
216 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_CONNECT) failed: status = %d"), status);
217 return status;
218 }
219
220 return status;
221 }
222
223
224 int
225 PPPDisconnect(int ref, u_long link)
226 {
227 int status;
228
229 status = PPPExec(ref,
230 link,
231 PPP_DISCONNECT,
232 NULL,
233 0,
234 NULL,
235 NULL);
236 if (status != 0) {
237 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_DISCONNECT) failed: status = %d"), status);
238 return status;
239 }
240
241 return status;
242 }
243 #endif /* NOT_NEEDED */
244
245
246 __private_extern__
247 int
248 PPPGetNumberOfLinks(int ref, u_long *nLinks)
249 {
250 void *replyBuf = NULL;
251 u_long replyBufLen = 0;
252 int status;
253
254 status = PPPExec(ref,
255 -1,
256 PPP_GETNBLINKS,
257 NULL,
258 0,
259 &replyBuf,
260 &replyBufLen);
261 if (status != 0) {
262 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETNBLINKS) failed: status = %d"), status);
263 return status;
264 }
265
266 *nLinks = (replyBufLen == sizeof(u_long)) ? *(u_long *)replyBuf : 0;
267 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
268
269 return status;
270 }
271
272
273 __private_extern__
274 int
275 PPPGetLinkByIndex(int ref, int index, u_int32_t *link)
276 {
277 u_int32_t i = index;
278 void *replyBuf = NULL;
279 u_long replyBufLen = 0;
280 int status;
281
282 status = PPPExec(ref,
283 -1,
284 PPP_GETLINKBYINDEX,
285 (void *)&i,
286 sizeof(i),
287 &replyBuf,
288 &replyBufLen);
289 if (status != 0) {
290 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETLINKBYINDEX) failed: status = %d"), status);
291 return status;
292 }
293
294 if (replyBuf && (replyBufLen == sizeof(u_int32_t))) {
295 *link = *(u_int32_t *)replyBuf;
296 } else {
297 status = -2; /* if not found */
298 }
299 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
300
301 return status;
302 }
303
304
305 __private_extern__
306 int
307 PPPGetLinkByServiceID(int ref, CFStringRef serviceID, u_int32_t *link)
308 {
309 int i;
310 u_long nLinks;
311 int status;
312 CFDataRef sID;
313
314 sID = CFStringCreateExternalRepresentation(NULL,
315 serviceID,
316 kCFStringEncodingMacRoman,
317 0);
318
319 status = PPPGetNumberOfLinks(ref, &nLinks);
320 if (status != 0) {
321 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetNumberOfLinks() failed: %d"), status);
322 goto done;
323 }
324
325 status = -2; /* assume no link */
326
327 for (i=0; i<nLinks; i++) {
328 u_int32_t iLink;
329 void *data = NULL;
330 u_long dataLen = 0;
331
332 status = PPPGetLinkByIndex(ref, i, &iLink);
333 if (status != 0) {
334 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetLinkByIndex() failed: %d"), status);
335 goto done;
336 }
337
338 status = PPPGetOption(ref,
339 iLink,
340 PPP_OPT_SERVICEID,
341 &data,
342 &dataLen);
343 if (status != 0) {
344 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetOption(PPP_OPT_SERVICEID) failed: %d"), status);
345 goto done;
346 }
347
348 if ((dataLen != CFDataGetLength(sID)) ||
349 (strncmp(data, CFDataGetBytePtr(sID), dataLen) != 0)) {
350 /* if link not found */
351 status = -2;
352 }
353
354 CFAllocatorDeallocate(NULL, data);
355 if (status == 0) {
356 *link = iLink;
357 goto done;
358 }
359 }
360
361 done :
362
363 CFRelease(sID);
364 return status;
365 }
366
367
368 __private_extern__
369 int
370 PPPGetOption(int ref, u_long link, u_long option, void **data, u_long *dataLen)
371 {
372 struct ppp_opt_hdr opt;
373 void *replyBuf = NULL;
374 u_long replyBufLen = 0;
375 int status;
376
377 bzero(&opt, sizeof(opt));
378 opt.o_type = option;
379
380 status = PPPExec(ref,
381 link,
382 PPP_GETOPTION,
383 (void *)&opt,
384 sizeof(opt),
385 &replyBuf,
386 &replyBufLen);
387 if (status != 0) {
388 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETOPTION) failed: status = %d"), status);
389 *data = NULL;
390 *dataLen = 0;
391 return status;
392 }
393
394 if (replyBuf && (replyBufLen > sizeof(struct ppp_opt_hdr))) {
395 *dataLen = replyBufLen - sizeof(struct ppp_opt_hdr);
396 *data = CFAllocatorAllocate(NULL, *dataLen, 0);
397 bcopy(((struct ppp_opt *)replyBuf)->o_data, *data, *dataLen);
398 }
399 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
400
401 return status;
402 }
403
404
405 #ifdef NOT_NEEDED
406 __private_extern__
407 int
408 PPPSetOption(int ref, u_long link, u_long option, void *data, u_long dataLen)
409 {
410 void *buf;
411 u_long bufLen;
412 int status;
413
414 bufLen = sizeof(struct ppp_opt_hdr) + dataLen;
415 buf = CFAllocatorAllocate(NULL, bufLen, 0);
416
417 bzero((struct ppp_opt_hdr *)buf, sizeof(struct ppp_opt_hdr));
418 ((struct ppp_opt_hdr *)buf)->o_type = option;
419 bcopy(data, ((struct ppp_opt *)buf)->o_data, dataLen);
420
421 status = PPPExec(ref,
422 link,
423 PPP_SETOPTION,
424 buf,
425 bufLen,
426 NULL,
427 NULL);
428 if (status != 0) {
429 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_SETOPTION) failed: status = %d"), status);
430 }
431
432 CFAllocatorDeallocate(NULL, buf);
433
434 return status;
435 }
436 #endif /* NOT_NEEDED */
437
438
439 __private_extern__
440 int
441 PPPStatus(int ref, u_long link, struct ppp_status **stat)
442 {
443 void *replyBuf = NULL;
444 u_long replyBufLen = 0;
445 int status;
446
447 status = PPPExec(ref,
448 link,
449 PPP_STATUS,
450 NULL,
451 0,
452 &replyBuf,
453 &replyBufLen);
454 if (status != 0) {
455 SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_STATUS) failed: status = %d"), status);
456 return status;
457 }
458
459 if (replyBuf && (replyBufLen == sizeof(struct ppp_status))) {
460 *stat = (struct ppp_status *)replyBuf;
461 } else {
462 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
463 *stat = NULL;
464 status = -1;
465 }
466
467 return status;
468 }
469
470
471 #ifdef NOT_NEEDED
472 __private_extern__
473 int
474 PPPEnableEvents(int ref, u_long link, u_char enable)
475 {
476 int status;
477
478 status = PPPExec(ref,
479 link,
480 enable ? PPP_ENABLE_EVENT : PPP_DISABLE_EVENT,
481 NULL,
482 0,
483 NULL,
484 NULL);
485 if (status != 0) {
486 SCLog(_sc_verbose,
487 LOG_ERR,
488 CFSTR("PPPExec(%s) failed: status = %d"),
489 enable ? "PPP_ENABLE_EVENT" : "PPP_DISABLE_EVENT",
490 status);
491 return status;
492 }
493
494 return status;
495 }
496 #endif /* NOT_NEEDED */