2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * Nov 7, 2002 Allan Nathanson <ajn@apple.com>
30 * - use ServiceID *or* LinkID
32 * Oct 25, 2002 Christophe Allie <callie@apple.com>
33 * - use ServiceID instead of LinkID
35 * Feb 28, 2002 Christophe Allie <callie@apple.com>
38 * Feb 10, 2001 Allan Nathanson <ajn@apple.com>
41 * Feb 2000 Christophe Allie <callie@apple.com>
47 #include <sys/types.h>
48 #include <sys/errno.h>
49 #include <sys/socket.h>
51 #include <CoreFoundation/CoreFoundation.h>
53 #include <SystemConfiguration/SystemConfiguration.h>
54 #include <SystemConfiguration/SCPrivate.h>
56 #include <ppp/ppp_msg.h>
61 readn(int ref
, void *data
, int len
)
68 if ((n
= read(ref
, p
, left
)) < 0) {
85 writen(int ref
, void *data
, int len
)
92 if ((n
= write(ref
, p
, left
)) <= 0) {
111 struct sockaddr_un sun
;
113 sock
= socket(AF_LOCAL
, SOCK_STREAM
, 0);
115 bzero(&sun
, sizeof(sun
));
116 sun
.sun_family
= AF_LOCAL
;
117 strncpy(sun
.sun_path
, PPP_PATH
, sizeof(sun
.sun_path
));
119 status
= connect(sock
, (struct sockaddr
*)&sun
, sizeof(sun
));
133 if (close(ref
) < 0) {
142 CFStringRef serviceID
,
151 struct ppp_msg_hdr msg
;
154 CFDataRef sID
= NULL
;
156 bzero(&msg
, sizeof(msg
));
158 // first send request, if necessary
163 sID
= CFStringCreateExternalRepresentation(NULL
,
165 kCFStringEncodingUTF8
,
167 // serviceID is present, use it
168 msg
.m_flags
|= USE_SERVICEID
;
169 msg
.m_link
= CFDataGetLength(sID
);
171 // no service ID, use the requested link
174 msg
.m_len
= ((request
!= NULL
) && (requestLen
> 0)) ? requestLen
: 0;
177 if (writen(ref
, &msg
, sizeof(msg
)) < 0) {
178 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec write() failed: %s"), strerror(errno
));
179 if (sID
) CFRelease(sID
);
184 if (writen(ref
, (void *)CFDataGetBytePtr(sID
), msg
.m_link
) < 0) {
185 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec write() failed: %s"), strerror(errno
));
192 if ((request
!= NULL
) && (requestLen
> 0)) {
193 if (writen(ref
, request
, requestLen
) < 0) {
194 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec write() failed: %s"), strerror(errno
));
200 // then read replies or incoming message
201 n
= readn(ref
, &msg
, sizeof(msg
));
203 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno
));
205 } else if (n
!= sizeof(msg
)) {
206 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n
);
210 if ((msg
.m_flags
& USE_SERVICEID
) && msg
.m_link
) {
211 buf
= CFAllocatorAllocate(NULL
, msg
.m_link
, 0);
214 n
= readn(ref
, buf
, msg
.m_link
);
216 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno
));
217 CFAllocatorDeallocate(NULL
, buf
);
219 } else if (n
!= (ssize_t
)msg
.m_link
) {
220 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno
));
221 CFAllocatorDeallocate(NULL
, buf
);
224 // buf contains the service id we passed in the request
225 CFAllocatorDeallocate(NULL
, buf
);
231 buf
= CFAllocatorAllocate(NULL
, msg
.m_len
, 0);
234 n
= readn(ref
, buf
, msg
.m_len
);
236 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno
));
237 CFAllocatorDeallocate(NULL
, buf
);
239 } else if (n
!= (ssize_t
)msg
.m_len
) {
240 SCLog(_sc_verbose
, LOG_ERR
, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n
);
241 CFAllocatorDeallocate(NULL
, buf
);
247 if (reply
&& replyLen
) {
249 *replyLen
= msg
.m_len
;
251 // if additional returned data is unwanted
252 CFAllocatorDeallocate(NULL
, buf
);
261 PPPGetLinkByInterface(int ref
, char *if_name
, uint32_t *link
)
263 void *replyBuf
= NULL
;
264 uint32_t replyBufLen
= 0;
267 status
= PPPExec(ref
,
280 if (replyBuf
&& (replyBufLen
== sizeof(uint32_t))) {
281 *link
= *(uint32_t *)replyBuf
;
283 status
= -2; /* if not found */
285 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
293 PPPConnect(int ref
, CFStringRef serviceID
, uint32_t link
, void *data
, uint32_t dataLen
, int linger
)
297 status
= PPPExec(ref
,
301 CONNECT_ARBITRATED_FLAG
+ (linger
? 0 : CONNECT_AUTOCLOSE_FLAG
),
312 PPPDisconnect(int ref
, CFStringRef serviceID
, uint32_t link
, int force
)
316 status
= PPPExec(ref
,
320 force
? 0 : DISCONNECT_ARBITRATED_FLAG
,
331 PPPSuspend(int ref
, CFStringRef serviceID
, uint32_t link
)
335 status
= PPPExec(ref
,
350 PPPResume(int ref
, CFStringRef serviceID
, uint32_t link
)
354 status
= PPPExec(ref
,
369 PPPGetOption(int ref
, CFStringRef serviceID
, uint32_t link
, uint32_t option
, void **data
, uint32_t *dataLen
)
371 struct ppp_opt_hdr opt
;
372 void *replyBuf
= NULL
;
373 uint32_t replyBufLen
= 0;
379 bzero(&opt
, sizeof(opt
));
382 status
= PPPExec(ref
,
395 if (replyBuf
&& (replyBufLen
> sizeof(struct ppp_opt_hdr
))) {
396 *dataLen
= replyBufLen
- sizeof(struct ppp_opt_hdr
);
397 *data
= CFAllocatorAllocate(NULL
, *dataLen
, 0);
398 bcopy(((struct ppp_opt
*)replyBuf
)->o_data
, *data
, *dataLen
);
400 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
408 PPPSetOption(int ref
, CFStringRef serviceID
, uint32_t link
, uint32_t option
, void *data
, uint32_t dataLen
)
414 bufLen
= sizeof(struct ppp_opt_hdr
) + dataLen
;
415 buf
= CFAllocatorAllocate(NULL
, bufLen
, 0);
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
);
421 status
= PPPExec(ref
,
431 CFAllocatorDeallocate(NULL
, buf
);
438 PPPGetConnectData(int ref
, CFStringRef serviceID
, uint32_t link
, void **data
, uint32_t *dataLen
)
445 status
= PPPExec(ref
,
460 PPPStatus(int ref
, CFStringRef serviceID
, uint32_t link
, struct ppp_status
**stat
)
462 void *replyBuf
= NULL
;
463 uint32_t replyBufLen
= 0;
468 status
= PPPExec(ref
,
481 if (replyBuf
&& (replyBufLen
== sizeof(struct ppp_status
))) {
482 *stat
= (struct ppp_status
*)replyBuf
;
484 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
494 PPPExtendedStatus(int ref
, CFStringRef serviceID
, uint32_t link
, void **data
, uint32_t *dataLen
)
501 status
= PPPExec(ref
,
516 PPPEnableEvents(int ref
, CFStringRef serviceID
, uint32_t link
, u_char enable
)
519 uint32_t lval
= 2; // status notifications
521 status
= PPPExec(ref
,
524 enable
? PPP_ENABLE_EVENT
: PPP_DISABLE_EVENT
,
536 PPPReadEvent(int ref
, uint32_t *event
)
539 *event
= PPPExec(ref
, NULL
, 0, 0, 0, NULL
, 0, NULL
, NULL
);
546 PPPSerialize(CFPropertyListRef obj
, void **data
, uint32_t *dataLen
)
550 xml
= CFPropertyListCreateXMLData(NULL
, obj
);
552 *data
= (void*)CFDataGetBytePtr(xml
);
553 *dataLen
= CFDataGetLength(xml
);
561 PPPUnserialize(void *data
, uint32_t dataLen
)
564 CFStringRef xmlError
;
565 CFPropertyListRef ref
= NULL
;
567 xml
= CFDataCreateWithBytesNoCopy(NULL
, data
, dataLen
, kCFAllocatorNull
);
569 ref
= CFPropertyListCreateFromXMLData(NULL
,
571 kCFPropertyListImmutable
,
577 CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),