1Starting with version 2.3.10, pppd includes support for `plugins' - 2pieces of code which can be loaded into pppd at runtime and which can 3affect its behaviour in various ways. The idea of plugins is to 4provide a way for people to customize the behaviour of pppd without 5having to either apply local patches to each version or get their 6patches accepted into the standard distribution. 7 8A plugin is a standard shared library object, typically with a name 9ending in .so. They are loaded using the standard dlopen() library 10call, so plugins are only supported on systems which support shared 11libraries and the dlopen call. At present pppd is compiled with 12plugin support only under Linux and Solaris. 13 14Plugins are loaded into pppd using the `plugin' option, which takes 15one argument, the name of a shared object file. The plugin option is 16a privileged option. If the name given does not contain a slash, pppd 17will look in the /usr/lib/pppd/<version> directory for the file, where 18<version> is the version number of pppd, for example, 2.4.2. I 19suggest that you either give the full path name of the shared object 20file or just the base name; if you don't, it may be possible for 21unscrupulous users to substitute another shared object file for the 22one you mean to load, e.g. by setting the LD_LIBRARY_PATH variable. 23 24Plugins are usually written in C and compiled and linked to a shared 25object file in the appropriate manner for your platform. Using gcc 26under Linux, a plugin called `xyz' could be compiled and linked with 27the following commands: 28 29 gcc -c -O xyz.c 30 gcc -shared -o xyz.so xyz.o 31 32There are some example plugins in the pppd/plugins directory in the 33ppp distribution. Currently there is one example, minconn.c, which 34implements a `minconnect' option, which specifies a minimum connect 35time before the idle timeout applies. 36 37Plugins can access global variables within pppd, so it is useful for 38them to #include "pppd.h" from the pppd source directory. Other 39header files can be included such as chap.h, mppe.h, and upap.h as 40needed per project. 41 42Every plugin must contain a global procedure called `plugin_init'. 43This procedure will get called (with no arguments) immediately after 44the plugin is loaded. Every plugin should also contain a variable 45called pppd_version declared as follows: 46 47char pppd_version[] = PPPD_VERSION; 48 49If this declaration is included, pppd will not load the module if its 50version number differs from that compiled into the plugin binary. 51 52Plugins can affect the behaviour of pppd in at least four ways: 53 541. They can add extra options which pppd will then recognize. This is 55 done by calling the ppp_add_options() procedure with a pointer to an 56 array of option_t structures. The last entry in the array must 57 have its name field set to NULL. 58 592. Pppd contains `hook' variables which are procedure pointers. If a 60 given hook is not NULL, pppd will call the procedure it points to 61 at the appropriate point in its processing. The plugin can set any 62 of these hooks to point to its own procedures. See below for a 63 description of the hooks which are currently implemented. 64 653. Plugin code can call any global procedures and access any global 66 variables in pppd. 67 684. Plugins can register procedures to be called when particular events 69 occur, using the `notifier' mechanism in pppd. The differences 70 between hooks and notifiers are that a hook will only call one 71 function, whereas a notifier can call an arbitrary number, and that 72 a hook usually returns some value to pppd, whereas a notifier 73 function returns nothing. 74 75Here is a list of the currently implemented hooks in pppd. 76 77 78int (*idle_time_hook)(struct ppp_idle *idlep); 79 80The idle_time_hook is called when the link first comes up (i.e. when 81the first network protocol comes up) and at intervals thereafter. On 82the first call, the idlep parameter is NULL, and the return value is 83the number of seconds before pppd should check the link activity, or 0 84if there is to be no idle timeout. 85 86On subsequent calls, idlep points to a structure giving the number of 87seconds since the last packets were sent and received. If the return 88value is > 0, pppd will wait that many seconds before checking again. 89If it is <= 0, that indicates that the link should be terminated due 90to lack of activity. 91 92 93int (*holdoff_hook)(void); 94 95The holdoff_hook is called when an attempt to bring up the link fails, 96or the link is terminated, and the persist or demand option was used. 97It returns the number of seconds that pppd should wait before trying 98to reestablish the link (0 means immediately). 99 100 101int (*pap_check_hook)(void); 102int (*pap_passwd_hook)(char *user, char *passwd); 103int (*pap_auth_hook)(char *user, char *passwd, char **msgp, 104 struct wordlist **paddrs, 105 struct wordlist **popts); 106void (*pap_logout_hook)(void); 107 108These hooks are designed to allow a plugin to replace the normal PAP 109password processing in pppd with something different (e.g. contacting 110an external server). 111 112The pap_check_hook is called to check whether there is any possibility 113that the peer could authenticate itself to us. If it returns 1, pppd 114will ask the peer to authenticate itself. If it returns 0, pppd will 115not ask the peer to authenticate itself (but if authentication is 116required, pppd may exit, or terminate the link before network protocol 117negotiation). If it returns -1, pppd will look in the pap-secrets 118file as it would normally. 119 120The pap_passwd_hook is called to determine what username and password 121pppd should use in authenticating itself to the peer with PAP. The 122user string will already be initialized, by the `user' option, the 123`name' option, or from the hostname, but can be changed if necessary. 124MAXNAMELEN bytes of space are available at *user, and MAXSECRETLEN 125bytes of space at *passwd. If this hook returns 0, pppd will use the 126values at *user and *passwd; if it returns -1, pppd will look in the 127pap-secrets file, or use the value from the +ua or password option, as 128it would normally. 129 130The pap_auth_hook is called to determine whether the username and 131password supplied by the peer are valid. user and passwd point to 132null-terminated strings containing the username and password supplied 133by the peer, with non-printable characters converted to a printable 134form. The pap_auth_hook function should set msg to a string to be 135returned to the peer and return 1 if the username/password was valid 136and 0 if not. If the hook returns -1, pppd will look in the 137pap-secrets file as usual. 138 139If the username/password was valid, the hook can set *paddrs to point 140to a wordlist containing the IP address(es) which the peer is 141permitted to use, formatted as in the pap-secrets file. It can also 142set *popts to a wordlist containing any extra options for this user 143which pppd should apply at this point. 144 145The pap_logout_hook is called when the link is terminated, instead of 146pppd's internal `plogout' function. It can be used for accounting 147purposes. This hook is deprecated and will be replaced by a notifier. 148 149 150int (*chap_check_hook)(void); 151int (*chap_passwd_hook)(char *user, char *passwd); 152int (*chap_verify_hook)(char *name, char *ourname, int id, 153 struct chap_digest_type *digest, 154 unsigned char *challenge, unsigned char *response, 155 char *message, int message_space) 156 157These hooks are designed to allow a plugin to replace the normal CHAP 158password processing in pppd with something different (e.g. contacting 159an external server). 160 161The chap_check_hook is called to check whether there is any possibility 162that the peer could authenticate itself to us. If it returns 1, pppd 163will ask the peer to authenticate itself. If it returns 0, pppd will 164not ask the peer to authenticate itself (but if authentication is 165required, pppd may exit, or terminate the link before network protocol 166negotiation). If it returns -1, pppd will look in the chap-secrets 167file as it would normally. 168 169The chap_passwd_hook is called to determine what password 170pppd should use in authenticating itself to the peer with CHAP. The 171user string will already be initialized, by the `user' option, the 172`name' option, or from the hostname, but can be changed if necessary. 173This hook is called only if pppd is a client, not if it is a server. 174 175MAXSECRETLEN bytes of space are available at *passwd. If this hook 176returns 0, pppd will use the value *passwd; if it returns -1, pppd 177will fail to authenticate. 178 179The chap_verify_hook is called to determine whether the peer's 180response to our CHAP challenge is valid -- it should return 1 if valid 181or 0 if not. The parameters are: 182 183* name points to a null-terminated string containing the username 184 supplied by the peer, or the remote name specified with the 185 "remotename" option. 186* ourname points to a null-terminated string containing the name of 187 the local machine (the hostname, or the name specified with the 188 "name" option). 189* id is the value of the id field from the challenge. 190* digest points to a chap_digest_type struct, which contains an 191 identifier for the type of digest in use plus function pointers for 192 functions for dealing with digests of that type. 193* challenge points to the challenge as a counted string (length byte 194 followed by the actual challenge bytes). 195* response points to the response as a counted string. 196* message points to an area of message_space bytes in which to store 197 any message that should be returned to the peer. 198 199 200int (*null_auth_hook)(struct wordlist **paddrs, 201 struct wordlist **popts); 202 203This hook allows a plugin to determine what the policy should be if 204the peer refuses to authenticate when it is requested to. If the 205return value is 0, the link will be terminated; if it is 1, the 206connection is allowed to proceed, and in this case *paddrs and *popts 207can be set as for pap_auth_hook, to specify what IP addresses are 208permitted and any extra options to be applied. If the return value is 209-1, pppd will look in the pap-secrets file as usual. 210 211 212void (*ip_choose_hook)(u_int32_t *addrp); 213 214This hook is called at the beginning of IPCP negotiation. It gives a 215plugin the opportunity to set the IP address for the peer; the address 216should be stored in *addrp. If nothing is stored in *addrp, pppd will 217determine the peer's address in the usual manner. 218 219 220int (*allowed_address_hook)(u_int32_t addr) 221 222This hook is called to see if a peer is allowed to use the specified 223address. If the hook returns 1, the address is accepted. If it returns 2240, the address is rejected. If it returns -1, the address is verified 225in the normal away against the appropriate options and secrets files. 226 227 228void (*snoop_recv_hook)(unsigned char *p, int len) 229void (*snoop_send_hook)(unsigned char *p, int len) 230 231These hooks are called whenever pppd receives or sends a packet. The 232packet is in p; its length is len. This allows plugins to "snoop in" 233on the pppd conversation. The hooks may prove useful in implmenting 234L2TP. 235 236 237void (*multilink_join_hook)(); 238 239This is called whenever a new link completes LCP negotiation and joins 240the bundle, if we are doing multilink. 241 242 243A plugin registers itself with a notifier by declaring a procedure of 244the form: 245 246void (ppp_notify_fn)(void *opaque, int arg); 247 248and then registering the procedure with the appropriate notifier with 249a call of the form 250 251 ppp_add_notify(ppp_notify_t, ppp_notify_fn, opaque); 252 253The ppp_notify_t is an enumerated type that describes which notifier 254to attach the function to. Example: NF_EXIT, NF_SIGNALED, NF_IP_UP 255 256The `opaque' parameter in the add_notifier call will be passed to 257my_notify_proc every time it is called. The `arg' parameter to 258my_notify_proc depends on the notifier. 259 260A notify procedure can be removed from the list for a notifier with a 261call of the form 262 263 ppp_del_notify(ppp_notify_t, ppp_notify_fn, opaque); 264 265Here is a list of the currently-implemented notifiers in pppd. 266 267* NF_PID_CHANGE. This notifier is called in the parent when pppd has 268 forked and the child is continuing pppd's processing, i.e. when pppd 269 detaches from its controlling terminal. The argument is the pid of 270 the child. 271 272* NF_PHASE_CHANGE. This is called when pppd moves from one phase of 273 operation to another. The argument is the new phase number. 274 275* NF_EXIT. This is called just before pppd exits. The argument is 276 the status with which pppd will exit (i.e. the argument to exit()). 277 278* NF_SIGNALED. This is called when a signal is received, from within 279 the signal handler. The argument is the signal number. 280 281* NF_IP_UP. This is called when IPCP has come up. 282 283* NF_IP_DOWN. This is called when IPCP goes down. 284 285* NF_IPV6_UP. This is called when IP6CP has come up. 286 287* NF_IPV6_DOWN. This is called when IP6CP goes down. 288 289* NF_AUTH_UP. This is called when the peer has successfully 290 authenticated itself. 291 292* NF_LINK_DOWN. This is called when the link goes down. 293 294* NF_FORK. Called for each time pppd exists as a new process (child). 295 296 297Regarding MPPE keys and key-material for 2.5.0 release 298 299Sometimes it is necessary for a plugin to access details related to 300the authentication process. The NF_AUTH_UP callback notifier (client only) 301allows a plugin to inspect e.g. key details after authentication has been 302completed, but before the key material is cleared from memory for security 303reasons. 304 305There are in particularly 3 functions that allow one to inspect these 306keys: 307 308* bool mppe_keys_isset() 309* int mppe_get_recv_key(unsigned char *key, int length) 310* int mppe_get_send_key(unsigned char *key, int length) 311 312The first function indicates whether or not the key material is set and 313is valid. The two latter functions will allow one to obtain a copy 314of the respective receive and send keys. The return value of these 315functions is the length of the valid key material. For security reasons, 316one should take care to clear these copies when work is complete. The 317max length of MPPE receive ands send keys are up to 32 bytes long, or 318of MPPE_MAX_KEY_SIZE length. 319 320The previous definitions of MPPE_MAX_KEY_LEN is the maximum length in 321which the Linux kernel will accept for MPPE key lengths. Plugins would 322access the MPPE keys directly via the: 323 324 extern u_char mppe_send_key[MPPE_MAX_KEY_LEN] 325 extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN] 326 327variables. The 2.5.0 release prohibits the direct access of these 328variables by making them static and private in favor of using the new 329API. 330