« Using Apple's PPP Library
// What's That?
This tutorial is about how to control the PPP-connection. It might not be very interesting to most programmers, but maybe some people can use this information for making the life better for dialup users.
// What It Can Do For You
The PPP-library Apple provides you to connect to a PPP-server, disconnect, set and get some connection information (connection time, data transferred...) and receive events. Note that this is a C-API, but it works fine in Objective C.
// What You Need
First you have to get some code from Darwin's cvs (see Apple's site for information how to get access). The module is called "ppp":
cvs -z3 -d :pserver:user@anoncvs.publicsource.apple.com:/cvs/Darwin co ppp
Now go into the directory "SampleCode/ClientAPI". Copy ppplib.h and ppplib.c to your project. Then go into "Controller". Pick up ppp_msg.h and copy that one, too.
Add those to your project (don't forget into insert them into the proper target).
// Extending
To add the ability to receive events, add the following to ppplib.c (those are additions by me):
/* ----------------------------------------------------------------------------- enable receiving of events parameters : ref : reference for this client return code errPPPNoError : ----------------------------------------------------------------------------- */ int PPPEnableEvent(int ref) { struct ppp_msg_hdr msg; bzero(&msg, sizeof(msg)); msg.m_type = PPP_ENABLE_EVENT; if(write(ref, &msg, sizeof(msg)) != sizeof(msg)) { return errno; } if (read(ref, &msg, sizeof(msg)) != sizeof(msg)) { // always expect a reply return errno; } return msg.m_result; } /* ----------------------------------------------------------------------------- disable receiving of events parameters : ref : reference for this client return code errPPPNoError : ----------------------------------------------------------------------------- */ int PPPDisableEvent(int ref) { struct ppp_msg_hdr msg; bzero(&msg, sizeof(msg)); msg.m_type = PPP_DISABLE_EVENT; if(write(ref, &msg, sizeof(msg)) != sizeof(msg)) { return errno; } if (read(ref, &msg, sizeof(msg)) != sizeof(msg)) { // always expect a reply return errno; } return msg.m_result; } /* ----------------------------------------------------------------------------- wait for an event (blocks) parameters : ref : reference for this client msg : the returned event message (reference) return code errPPPNoError : ----------------------------------------------------------------------------- */ int PPPWaitForEvent(int ref, struct ppp_msg_hdr *msg) { fd_set read_set; FD_ZERO(&read_set); FD_SET(ref,&read_set); if(select(ref+1, &read_set, NULL, NULL, NULL)<0) return errno; if(read(ref,msg,sizeof(*msg))!=sizeof(*msg)) return errno; return 0; }
And the following to ppplib.h:
int PPPEnableEvent(int ref); int PPPDisableEvent(int ref); int PPPWaitForEvent(int ref, struct ppp_msg_hdr *msg);
And replace the #include-line with #include "ppp_msg.h".
// Using ppplib
First, you have to establish a connection to the PPP-controller:
#include "ppplib.h" int ref; PPPInit(&ref,0,0);
"ref" is the reference to your connection. You need this for all commands. The other two parameters aren't used and are here for compatibility reasons.
Now you can send commands. For instance, to connect use the following:
PPPConnect(ref);
To disconnect:
PPPDisonnect(ref);
The status information is pretty interesting:
struct ppp_status state; PPPStatus(ref,&state);
The struct that is used here is defined in ppp_msg.h:
struct ppp_status { // connection stats u_int32_t status; union { struct connected { u_int32_t timeElapsed; u_int32_t timeRemaining; // bytes stats u_int32_t inBytes; u_int32_t inPackets; u_int32_t inErrors; u_int32_t outBytes; u_int32_t outPackets; u_int32_t outErrors; } run; struct disconnected { u_int32_t lastDiscCause; } disc; } s; };
To get a clue what constants are used (for instance for ppp_status.status), take a look at ppp_msg.h:
// state machine enum { PPP_IDLE = 0, PPP_INITIALIZE, PPP_CONNECTLINK, PPP_STATERESERVED, PPP_ESTABLISH, PPP_AUTHENTICATE, PPP_CALLBACK, PPP_NETWORK, PPP_RUNNING, PPP_TERMINATE, PPP_DISCONNECTLINK };
Don't forget to dispose the reference when done:
PPPDispose(ref);
// Events
You might want to know when a connection is established and closed. One way to do this is to constantly poll using PPPStatus(ref);, but that's not very efficient.
The best (maybe not the easiest) way is to use my additions, PPPEnableEvent/PPPDisableEvent/PPPWaitForEvent. To enable and disable receiving events:
PPPEnableEvent(ref); PPPDisableEvent(ref);
When receiving events is enabled, you can wait for an event using PPPWaitForEvent. Note that this function blocks until something is received, so it's wise to put it into a separate thread.
struct ppp_msg_hdr msg; PPPWaitForEvent(ref, &msg);
To get the information what event has happend, read the struct ppp_msg_hdr:
struct ppp_msg_hdr { u_int32_t m_type; // type of the message u_int32_t m_result; // error code of notification message u_int32_t m_cookie; // user param u_int32_t m_link; // link for this message u_int32_t m_len; // len of the following data }; // events enum { PPP_EVT_DISCONNECTED = 1, PPP_EVT_CONNSCRIPT_STARTED, PPP_EVT_CONNSCRIPT_FINISHED, PPP_EVT_TERMSCRIPT_STARTED, PPP_EVT_TERMSCRIPT_FINISHED, PPP_EVT_LOWERLAYER_UP, PPP_EVT_LOWERLAYER_DOWN, PPP_EVT_LCP_UP, PPP_EVT_LCP_DOWN, PPP_EVT_IPCP_UP, PPP_EVT_IPCP_DOWN, PPP_EVT_AUTH_STARTED, PPP_EVT_AUTH_FAILED, PPP_EVT_AUTH_SUCCEDED };
// Conclusion
There are some more options, for example you can set the modem script used or get your IP address. Take a look at ppplib.h and ppp_msg.h for more information.
The ppplib Apple provides is pretty easy to use, so I'm waiting for you programmers helping those poor dialup users!
Hello,
Please tell me where is the PPP-library. I didn't found the source.
Thanks.
hello,
I'd like to use the PPP library to configure and run a DSL connection using PPPoE protocol. Is there a function call like PPPConnect to do that. Maybe that's just an option I have to specify but I don't kown which one nor how to do that.
regards
mathieu
Posted by: mamat on November 12, 2003 10:40 AM