lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame^] | 1 | Starting with version 2.3.10, pppd includes support for `plugins' - |
| 2 | pieces of code which can be loaded into pppd at runtime and which can |
| 3 | affect its behaviour in various ways. The idea of plugins is to |
| 4 | provide a way for people to customize the behaviour of pppd without |
| 5 | having to either apply local patches to each version or get their |
| 6 | patches accepted into the standard distribution. |
| 7 | |
| 8 | A plugin is a standard shared library object, typically with a name |
| 9 | ending in .so. They are loaded using the standard dlopen() library |
| 10 | call, so plugins are only supported on systems which support shared |
| 11 | libraries and the dlopen call. At present pppd is compiled with |
| 12 | plugin support only under Linux and Solaris. |
| 13 | |
| 14 | Plugins are loaded into pppd using the `plugin' option, which takes |
| 15 | one argument, the name of a shared object file. The plugin option is |
| 16 | a privileged option. If the name given does not contain a slash, pppd |
| 17 | will 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 |
| 19 | suggest that you either give the full path name of the shared object |
| 20 | file or just the base name; if you don't, it may be possible for |
| 21 | unscrupulous users to substitute another shared object file for the |
| 22 | one you mean to load, e.g. by setting the LD_LIBRARY_PATH variable. |
| 23 | |
| 24 | Plugins are usually written in C and compiled and linked to a shared |
| 25 | object file in the appropriate manner for your platform. Using gcc |
| 26 | under Linux, a plugin called `xyz' could be compiled and linked with |
| 27 | the following commands: |
| 28 | |
| 29 | gcc -c -O xyz.c |
| 30 | gcc -shared -o xyz.so xyz.o |
| 31 | |
| 32 | There are some example plugins in the pppd/plugins directory in the |
| 33 | ppp distribution. Currently there is one example, minconn.c, which |
| 34 | implements a `minconnect' option, which specifies a minimum connect |
| 35 | time before the idle timeout applies. |
| 36 | |
| 37 | Plugins can access global variables within pppd, so it is useful for |
| 38 | them to #include "pppd.h" from the pppd source directory. |
| 39 | |
| 40 | Every plugin must contain a global procedure called `plugin_init'. |
| 41 | This procedure will get called (with no arguments) immediately after |
| 42 | the plugin is loaded. Every plugin should also contain a variable |
| 43 | called pppd_version declared as follows: |
| 44 | |
| 45 | char pppd_version[] = VERSION; |
| 46 | |
| 47 | If this declaration is included, pppd will not load the module if its |
| 48 | version number differs from that compiled into the plugin binary. |
| 49 | |
| 50 | Plugins can affect the behaviour of pppd in at least four ways: |
| 51 | |
| 52 | 1. 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 | |
| 57 | 2. 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 | |
| 63 | 3. Plugin code can call any global procedures and access any global |
| 64 | variables in pppd. |
| 65 | |
| 66 | 4. 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 | |
| 73 | Here is a list of the currently implemented hooks in pppd. |
| 74 | |
| 75 | |
| 76 | int (*idle_time_hook)(struct ppp_idle *idlep); |
| 77 | |
| 78 | The idle_time_hook is called when the link first comes up (i.e. when |
| 79 | the first network protocol comes up) and at intervals thereafter. On |
| 80 | the first call, the idlep parameter is NULL, and the return value is |
| 81 | the number of seconds before pppd should check the link activity, or 0 |
| 82 | if there is to be no idle timeout. |
| 83 | |
| 84 | On subsequent calls, idlep points to a structure giving the number of |
| 85 | seconds since the last packets were sent and received. If the return |
| 86 | value is > 0, pppd will wait that many seconds before checking again. |
| 87 | If it is <= 0, that indicates that the link should be terminated due |
| 88 | to lack of activity. |
| 89 | |
| 90 | |
| 91 | int (*holdoff_hook)(void); |
| 92 | |
| 93 | The holdoff_hook is called when an attempt to bring up the link fails, |
| 94 | or the link is terminated, and the persist or demand option was used. |
| 95 | It returns the number of seconds that pppd should wait before trying |
| 96 | to reestablish the link (0 means immediately). |
| 97 | |
| 98 | |
| 99 | int (*pap_check_hook)(void); |
| 100 | int (*pap_passwd_hook)(char *user, char *passwd); |
| 101 | int (*pap_auth_hook)(char *user, char *passwd, char **msgp, |
| 102 | struct wordlist **paddrs, |
| 103 | struct wordlist **popts); |
| 104 | void (*pap_logout_hook)(void); |
| 105 | |
| 106 | These hooks are designed to allow a plugin to replace the normal PAP |
| 107 | password processing in pppd with something different (e.g. contacting |
| 108 | an external server). |
| 109 | |
| 110 | The pap_check_hook is called to check whether there is any possibility |
| 111 | that the peer could authenticate itself to us. If it returns 1, pppd |
| 112 | will ask the peer to authenticate itself. If it returns 0, pppd will |
| 113 | not ask the peer to authenticate itself (but if authentication is |
| 114 | required, pppd may exit, or terminate the link before network protocol |
| 115 | negotiation). If it returns -1, pppd will look in the pap-secrets |
| 116 | file as it would normally. |
| 117 | |
| 118 | The pap_passwd_hook is called to determine what username and password |
| 119 | pppd should use in authenticating itself to the peer with PAP. The |
| 120 | user string will already be initialized, by the `user' option, the |
| 121 | `name' option, or from the hostname, but can be changed if necessary. |
| 122 | MAXNAMELEN bytes of space are available at *user, and MAXSECRETLEN |
| 123 | bytes of space at *passwd. If this hook returns 0, pppd will use the |
| 124 | values at *user and *passwd; if it returns -1, pppd will look in the |
| 125 | pap-secrets file, or use the value from the +ua or password option, as |
| 126 | it would normally. |
| 127 | |
| 128 | The pap_auth_hook is called to determine whether the username and |
| 129 | password supplied by the peer are valid. user and passwd point to |
| 130 | null-terminated strings containing the username and password supplied |
| 131 | by the peer, with non-printable characters converted to a printable |
| 132 | form. The pap_auth_hook function should set msg to a string to be |
| 133 | returned to the peer and return 1 if the username/password was valid |
| 134 | and 0 if not. If the hook returns -1, pppd will look in the |
| 135 | pap-secrets file as usual. |
| 136 | |
| 137 | If the username/password was valid, the hook can set *paddrs to point |
| 138 | to a wordlist containing the IP address(es) which the peer is |
| 139 | permitted to use, formatted as in the pap-secrets file. It can also |
| 140 | set *popts to a wordlist containing any extra options for this user |
| 141 | which pppd should apply at this point. |
| 142 | |
| 143 | The pap_logout_hook is called when the link is terminated, instead of |
| 144 | pppd's internal `plogout' function. It can be used for accounting |
| 145 | purposes. This hook is deprecated and will be replaced by a notifier. |
| 146 | |
| 147 | |
| 148 | int (*chap_check_hook)(void); |
| 149 | int (*chap_passwd_hook)(char *user, char *passwd); |
| 150 | int (*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 | |
| 155 | These hooks are designed to allow a plugin to replace the normal CHAP |
| 156 | password processing in pppd with something different (e.g. contacting |
| 157 | an external server). |
| 158 | |
| 159 | The chap_check_hook is called to check whether there is any possibility |
| 160 | that the peer could authenticate itself to us. If it returns 1, pppd |
| 161 | will ask the peer to authenticate itself. If it returns 0, pppd will |
| 162 | not ask the peer to authenticate itself (but if authentication is |
| 163 | required, pppd may exit, or terminate the link before network protocol |
| 164 | negotiation). If it returns -1, pppd will look in the chap-secrets |
| 165 | file as it would normally. |
| 166 | |
| 167 | The chap_passwd_hook is called to determine what password |
| 168 | pppd should use in authenticating itself to the peer with CHAP. The |
| 169 | user string will already be initialized, by the `user' option, the |
| 170 | `name' option, or from the hostname, but can be changed if necessary. |
| 171 | This hook is called only if pppd is a client, not if it is a server. |
| 172 | |
| 173 | MAXSECRETLEN bytes of space are available at *passwd. If this hook |
| 174 | returns 0, pppd will use the value *passwd; if it returns -1, pppd |
| 175 | will fail to authenticate. |
| 176 | |
| 177 | The chap_verify_hook is called to determine whether the peer's |
| 178 | response to our CHAP challenge is valid -- it should return 1 if valid |
| 179 | or 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 | |
| 198 | int (*null_auth_hook)(struct wordlist **paddrs, |
| 199 | struct wordlist **popts); |
| 200 | |
| 201 | This hook allows a plugin to determine what the policy should be if |
| 202 | the peer refuses to authenticate when it is requested to. If the |
| 203 | return value is 0, the link will be terminated; if it is 1, the |
| 204 | connection is allowed to proceed, and in this case *paddrs and *popts |
| 205 | can be set as for pap_auth_hook, to specify what IP addresses are |
| 206 | permitted 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 | |
| 210 | void (*ip_choose_hook)(u_int32_t *addrp); |
| 211 | |
| 212 | This hook is called at the beginning of IPCP negotiation. It gives a |
| 213 | plugin the opportunity to set the IP address for the peer; the address |
| 214 | should be stored in *addrp. If nothing is stored in *addrp, pppd will |
| 215 | determine the peer's address in the usual manner. |
| 216 | |
| 217 | |
| 218 | int (*allowed_address_hook)(u_int32_t addr) |
| 219 | |
| 220 | This hook is called to see if a peer is allowed to use the specified |
| 221 | address. If the hook returns 1, the address is accepted. If it returns |
| 222 | 0, the address is rejected. If it returns -1, the address is verified |
| 223 | in the normal away against the appropriate options and secrets files. |
| 224 | |
| 225 | |
| 226 | void (*snoop_recv_hook)(unsigned char *p, int len) |
| 227 | void (*snoop_send_hook)(unsigned char *p, int len) |
| 228 | |
| 229 | These hooks are called whenever pppd receives or sends a packet. The |
| 230 | packet is in p; its length is len. This allows plugins to "snoop in" |
| 231 | on the pppd conversation. The hooks may prove useful in implmenting |
| 232 | L2TP. |
| 233 | |
| 234 | |
| 235 | void (*multilink_join_hook)(); |
| 236 | |
| 237 | This is called whenever a new link completes LCP negotiation and joins |
| 238 | the bundle, if we are doing multilink. |
| 239 | |
| 240 | |
| 241 | A plugin registers itself with a notifier by declaring a procedure of |
| 242 | the form: |
| 243 | |
| 244 | void my_notify_proc(void *opaque, int arg); |
| 245 | |
| 246 | and then registering the procedure with the appropriate notifier with |
| 247 | a call of the form |
| 248 | |
| 249 | add_notifier(&interesting_notifier, my_notify_proc, opaque); |
| 250 | |
| 251 | The `opaque' parameter in the add_notifier call will be passed to |
| 252 | my_notify_proc every time it is called. The `arg' parameter to |
| 253 | my_notify_proc depends on the notifier. |
| 254 | |
| 255 | A notify procedure can be removed from the list for a notifier with a |
| 256 | call of the form |
| 257 | |
| 258 | remove_notifier(&interesting_notifier, my_notify_proc, opaque); |
| 259 | |
| 260 | Here is a list of the currently-implemented notifiers in pppd. |
| 261 | |
| 262 | * pidchange. This notifier is called in the parent when pppd has |
| 263 | forked and the child is continuing pppd's processing, i.e. when pppd |
| 264 | detaches from its controlling terminal. The argument is the pid of |
| 265 | the child. |
| 266 | |
| 267 | * phasechange. This is called when pppd moves from one phase of |
| 268 | operation to another. The argument is the new phase number. |
| 269 | |
| 270 | * exitnotify. This is called just before pppd exits. The argument is |
| 271 | the status with which pppd will exit (i.e. the argument to exit()). |
| 272 | |
| 273 | * sigreceived. This is called when a signal is received, from within |
| 274 | the signal handler. The argument is the signal number. |
| 275 | |
| 276 | * ip_up_notifier. This is called when IPCP has come up. |
| 277 | |
| 278 | * ip_down_notifier. This is called when IPCP goes down. |
| 279 | |
| 280 | * auth_up_notifier. This is called when the peer has successfully |
| 281 | authenticated itself. |
| 282 | |
| 283 | * link_down_notifier. This is called when the link goes down. |
| 284 | |
| 285 | |
| 286 | |
| 287 | ## $Id: PLUGINS,v 1.8 2008/06/15 07:02:18 paulus Exp $ ## |