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. 39 40Every plugin must contain a global procedure called `plugin_init'. 41This procedure will get called (with no arguments) immediately after 42the plugin is loaded. Every plugin should also contain a variable 43called pppd_version declared as follows: 44 45char pppd_version[] = VERSION; 46 47If this declaration is included, pppd will not load the module if its 48version number differs from that compiled into the plugin binary. 49 50Plugins can affect the behaviour of pppd in at least four ways: 51 521. They can add extra options which pppd will then recognize. This is 53 done by calling the add_options() procedure with a pointer to an 54 array of option_t structures. The last entry in the array must 55 have its name field set to NULL. 56 572. Pppd contains `hook' variables which are procedure pointers. If a 58 given hook is not NULL, pppd will call the procedure it points to 59 at the appropriate point in its processing. The plugin can set any 60 of these hooks to point to its own procedures. See below for a 61 description of the hooks which are currently implemented. 62 633. Plugin code can call any global procedures and access any global 64 variables in pppd. 65 664. Plugins can register procedures to be called when particular events 67 occur, using the `notifier' mechanism in pppd. The differences 68 between hooks and notifiers are that a hook will only call one 69 function, whereas a notifier can call an arbitrary number, and that 70 a hook usually returns some value to pppd, whereas a notifier 71 function returns nothing. 72 73Here is a list of the currently implemented hooks in pppd. 74 75 76int (*idle_time_hook)(struct ppp_idle *idlep); 77 78The idle_time_hook is called when the link first comes up (i.e. when 79the first network protocol comes up) and at intervals thereafter. On 80the first call, the idlep parameter is NULL, and the return value is 81the number of seconds before pppd should check the link activity, or 0 82if there is to be no idle timeout. 83 84On subsequent calls, idlep points to a structure giving the number of 85seconds since the last packets were sent and received. If the return 86value is > 0, pppd will wait that many seconds before checking again. 87If it is <= 0, that indicates that the link should be terminated due 88to lack of activity. 89 90 91int (*holdoff_hook)(void); 92 93The holdoff_hook is called when an attempt to bring up the link fails, 94or the link is terminated, and the persist or demand option was used. 95It returns the number of seconds that pppd should wait before trying 96to reestablish the link (0 means immediately). 97 98 99int (*pap_check_hook)(void); 100int (*pap_passwd_hook)(char *user, char *passwd); 101int (*pap_auth_hook)(char *user, char *passwd, char **msgp, 102 struct wordlist **paddrs, 103 struct wordlist **popts); 104void (*pap_logout_hook)(void); 105 106These hooks are designed to allow a plugin to replace the normal PAP 107password processing in pppd with something different (e.g. contacting 108an external server). 109 110The pap_check_hook is called to check whether there is any possibility 111that the peer could authenticate itself to us. If it returns 1, pppd 112will ask the peer to authenticate itself. If it returns 0, pppd will 113not ask the peer to authenticate itself (but if authentication is 114required, pppd may exit, or terminate the link before network protocol 115negotiation). If it returns -1, pppd will look in the pap-secrets 116file as it would normally. 117 118The pap_passwd_hook is called to determine what username and password 119pppd should use in authenticating itself to the peer with PAP. The 120user string will already be initialized, by the `user' option, the 121`name' option, or from the hostname, but can be changed if necessary. 122MAXNAMELEN bytes of space are available at *user, and MAXSECRETLEN 123bytes of space at *passwd. If this hook returns 0, pppd will use the 124values at *user and *passwd; if it returns -1, pppd will look in the 125pap-secrets file, or use the value from the +ua or password option, as 126it would normally. 127 128The pap_auth_hook is called to determine whether the username and 129password supplied by the peer are valid. user and passwd point to 130null-terminated strings containing the username and password supplied 131by the peer, with non-printable characters converted to a printable 132form. The pap_auth_hook function should set msg to a string to be 133returned to the peer and return 1 if the username/password was valid 134and 0 if not. If the hook returns -1, pppd will look in the 135pap-secrets file as usual. 136 137If the username/password was valid, the hook can set *paddrs to point 138to a wordlist containing the IP address(es) which the peer is 139permitted to use, formatted as in the pap-secrets file. It can also 140set *popts to a wordlist containing any extra options for this user 141which pppd should apply at this point. 142 143The pap_logout_hook is called when the link is terminated, instead of 144pppd's internal `plogout' function. It can be used for accounting 145purposes. This hook is deprecated and will be replaced by a notifier. 146 147 148int (*chap_check_hook)(void); 149int (*chap_passwd_hook)(char *user, char *passwd); 150int (*chap_verify_hook)(char *name, char *ourname, int id, 151 struct chap_digest_type *digest, 152 unsigned char *challenge, unsigned char *response, 153 char *message, int message_space) 154 155These hooks are designed to allow a plugin to replace the normal CHAP 156password processing in pppd with something different (e.g. contacting 157an external server). 158 159The chap_check_hook is called to check whether there is any possibility 160that the peer could authenticate itself to us. If it returns 1, pppd 161will ask the peer to authenticate itself. If it returns 0, pppd will 162not ask the peer to authenticate itself (but if authentication is 163required, pppd may exit, or terminate the link before network protocol 164negotiation). If it returns -1, pppd will look in the chap-secrets 165file as it would normally. 166 167The chap_passwd_hook is called to determine what password 168pppd should use in authenticating itself to the peer with CHAP. The 169user string will already be initialized, by the `user' option, the 170`name' option, or from the hostname, but can be changed if necessary. 171This hook is called only if pppd is a client, not if it is a server. 172 173MAXSECRETLEN bytes of space are available at *passwd. If this hook 174returns 0, pppd will use the value *passwd; if it returns -1, pppd 175will fail to authenticate. 176 177The chap_verify_hook is called to determine whether the peer's 178response to our CHAP challenge is valid -- it should return 1 if valid 179or 0 if not. The parameters are: 180 181* name points to a null-terminated string containing the username 182 supplied by the peer, or the remote name specified with the 183 "remotename" option. 184* ourname points to a null-terminated string containing the name of 185 the local machine (the hostname, or the name specified with the 186 "name" option). 187* id is the value of the id field from the challenge. 188* digest points to a chap_digest_type struct, which contains an 189 identifier for the type of digest in use plus function pointers for 190 functions for dealing with digests of that type. 191* challenge points to the challenge as a counted string (length byte 192 followed by the actual challenge bytes). 193* response points to the response as a counted string. 194* message points to an area of message_space bytes in which to store 195 any message that should be returned to the peer. 196 197 198int (*null_auth_hook)(struct wordlist **paddrs, 199 struct wordlist **popts); 200 201This hook allows a plugin to determine what the policy should be if 202the peer refuses to authenticate when it is requested to. If the 203return value is 0, the link will be terminated; if it is 1, the 204connection is allowed to proceed, and in this case *paddrs and *popts 205can be set as for pap_auth_hook, to specify what IP addresses are 206permitted and any extra options to be applied. If the return value is 207-1, pppd will look in the pap-secrets file as usual. 208 209 210void (*ip_choose_hook)(u_int32_t *addrp); 211 212This hook is called at the beginning of IPCP negotiation. It gives a 213plugin the opportunity to set the IP address for the peer; the address 214should be stored in *addrp. If nothing is stored in *addrp, pppd will 215determine the peer's address in the usual manner. 216 217 218int (*allowed_address_hook)(u_int32_t addr) 219 220This hook is called to see if a peer is allowed to use the specified 221address. If the hook returns 1, the address is accepted. If it returns 2220, the address is rejected. If it returns -1, the address is verified 223in the normal away against the appropriate options and secrets files. 224 225 226void (*snoop_recv_hook)(unsigned char *p, int len) 227void (*snoop_send_hook)(unsigned char *p, int len) 228 229These hooks are called whenever pppd receives or sends a packet. The 230packet is in p; its length is len. This allows plugins to "snoop in" 231on the pppd conversation. The hooks may prove useful in implmenting 232L2TP. 233 234A plugin registers itself with a notifier by declaring a procedure of 235the form: 236 237void my_notify_proc(void *opaque, int arg); 238 239and then registering the procedure with the appropriate notifier with 240a call of the form 241 242 add_notifier(&interesting_notifier, my_notify_proc, opaque); 243 244The `opaque' parameter in the add_notifier call will be passed to 245my_notify_proc every time it is called. The `arg' parameter to 246my_notify_proc depends on the notifier. 247 248A notify procedure can be removed from the list for a notifier with a 249call of the form 250 251 remove_notifier(&interesting_notifier, my_notify_proc, opaque); 252 253Here is a list of the currently-implemented notifiers in pppd. 254 255* pidchange. This notifier is called in the parent when pppd has 256 forked and the child is continuing pppd's processing, i.e. when pppd 257 detaches from its controlling terminal. The argument is the pid of 258 the child. 259 260* phasechange. This is called when pppd moves from one phase of 261 operation to another. The argument is the new phase number. 262 263* exitnotify. This is called just before pppd exits. The argument is 264 the status with which pppd will exit (i.e. the argument to exit()). 265 266* sigreceived. This is called when a signal is received, from within 267 the signal handler. The argument is the signal number. 268 269* ip_up_notifier. This is called when IPCP has come up. 270 271* ip_down_notifier. This is called when IPCP goes down. 272 273* auth_up_notifier. This is called when the peer has successfully 274 authenticated itself. 275 276* link_down_notifier. This is called when the link goes down. 277 278 279 280## $Id: PLUGINS,v 1.7 2005/07/12 08:56:07 paulus Exp $ ## 281