Watt-32 tcp/ip  2.2 dev-rel.10
ppp.c
Go to the documentation of this file.
1 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <time.h>
31 #include <limits.h>
32 #include <netinet/in.h>
33 
34 #include "wattcp.h"
35 #include "misc.h"
36 #include "strings.h"
37 #include "pcdbug.h"
38 #include "pcqueue.h"
39 #include "pcconfig.h"
40 #include "pcarp.h"
41 #include "pcsed.h"
42 #include "pcpkt.h"
43 #include "pctcp.h"
44 #include "run.h"
45 #include "ip4_in.h"
46 #include "netaddr.h"
47 #include "pppoe.h"
48 #include "ppp.h"
49 
50 #if defined(USE_PPPOE)
51 
52 #define INITIAL_TIMEOUT 2
53 #define MAX_TERMINATE 2
54 #define MAX_CONFIGURE 10
55 #define MAX_FAILURE 5
56 #define MAX_TIMEOUT 8
57 
58 
59 static DWORD remote_ip_base = 0x0A000000;
60 static DWORD remote_ip_mask = 0xFF000000;
61 static int debug = 0;
62 
63 
64 static struct ppp_state mystate;
65 
66 static void ipcp_addr_req (struct ppp_state *state,
67  struct ppp_xcp *xcp, const struct xcp_type *tp,
68  const BYTE *buf, int len);
69 
70 static void ipcp_addr_nak (struct ppp_state *state,
71  struct ppp_xcp *xcp, const struct xcp_type *tp,
72  const BYTE *buf, int len);
73 
74 static void ipcp_addr_show (struct ppp_state *state,
75  struct ppp_xcp *xcp, const struct xcp_type *tp,
76  const BYTE *buf, int len);
77 
78 static void send_event (struct ppp_state *state, struct ppp_xcp *xcp,
79  enum ppp_event event);
80 
81 static void change_phase (struct ppp_state *state, enum ppp_phase phase);
82 
83 
84 static const struct xcp_type lcp_types[] = {
85  { NULL, -1, 0, 0, 0, 0, NULL, NULL, NULL }
86  };
87 
88 static const struct xcp_type ipcp_types[] = {
89  { "IP-Address", 3, 1, 6, 6, 0, ipcp_addr_req,
90  ipcp_addr_nak, ipcp_addr_show },
91  { NULL, -1, 0, 0, 0, 0, NULL, NULL, NULL }
92  };
93 
94 
95 /* Dispatch table from RFC 1661
96  */
97 static const struct ppp_dispatch {
98  enum xcp_state next;
99  enum xcp_action act[3];
100  } ppp_dispatch[10][16] = {
101 
102  { /* stInitial */
103  /* evUp */ { stClosed, { acNull, acNull, acNull } },
104  /* evDown */ { stNoChange, { acNull, acNull, acNull } },
105  /* evOpen */ { stStarting, { acTls, acNull, acNull } },
106  /* evClose */ { stClosed, { acNull, acNull, acNull } },
107  /* evTOp */ { stNoChange, { acNull, acNull, acNull } },
108  /* evTOm */ { stNoChange, { acNull, acNull, acNull } },
109  /* evRCRp */ { stNoChange, { acNull, acNull, acNull } },
110  /* evRCRm */ { stNoChange, { acNull, acNull, acNull } },
111  /* evRCA */ { stNoChange, { acNull, acNull, acNull } },
112  /* evRCN */ { stNoChange, { acNull, acNull, acNull } },
113  /* evRTR */ { stNoChange, { acNull, acNull, acNull } },
114  /* evRTA */ { stNoChange, { acNull, acNull, acNull } },
115  /* evRUC */ { stNoChange, { acNull, acNull, acNull } },
116  /* evRXJp */ { stNoChange, { acNull, acNull, acNull } },
117  /* evRXJm */ { stNoChange, { acNull, acNull, acNull } },
118  /* evRXR */ { stNoChange, { acNull, acNull, acNull } },
119  },
120  { /* stStarting */
121  /* evUp */ { stReqSent, { acIrc, acScr, acNull } },
122  /* evDown */ { stNoChange, { acNull, acNull, acNull } },
123  /* evOpen */ { stStarting, { acNull, acNull, acNull } },
124  /* evClose */ { stInitial, { acTlf, acNull, acNull } },
125  /* evTOp */ { stNoChange, { acNull, acNull, acNull } },
126  /* evTOm */ { stNoChange, { acNull, acNull, acNull } },
127  /* evRCRp */ { stNoChange, { acNull, acNull, acNull } },
128  /* evRCRm */ { stNoChange, { acNull, acNull, acNull } },
129  /* evRCA */ { stNoChange, { acNull, acNull, acNull } },
130  /* evRCN */ { stNoChange, { acNull, acNull, acNull } },
131  /* evRTR */ { stNoChange, { acNull, acNull, acNull } },
132  /* evRTA */ { stNoChange, { acNull, acNull, acNull } },
133  /* evRUC */ { stNoChange, { acNull, acNull, acNull } },
134  /* evRXJp */ { stNoChange, { acNull, acNull, acNull } },
135  /* evRXJm */ { stNoChange, { acNull, acNull, acNull } },
136  /* evRXR */ { stNoChange, { acNull, acNull, acNull } },
137  },
138  { /* stClosed */
139  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
140  /* evDown */ { stInitial, { acNull, acNull, acNull } },
141  /* evOpen */ { stReqSent, { acIrc, acScr, acNull } },
142  /* evClose */ { stClosed, { acNull, acNull, acNull } },
143  /* evTOp */ { stNoChange, { acNull, acNull, acNull } },
144  /* evTOm */ { stNoChange, { acNull, acNull, acNull } },
145  /* evRCRp */ { stClosed, { acSta, acNull, acNull } },
146  /* evRCRm */ { stClosed, { acSta, acNull, acNull } },
147  /* evRCA */ { stClosed, { acSta, acNull, acNull } },
148  /* evRCN */ { stClosed, { acSta, acNull, acNull } },
149  /* evRTR */ { stClosed, { acSta, acNull, acNull } },
150  /* evRTA */ { stClosed, { acNull, acNull, acNull } },
151  /* evRUC */ { stClosed, { acScj, acNull, acNull } },
152  /* evRXJp */ { stClosed, { acNull, acNull, acNull } },
153  /* evRXJm */ { stClosed, { acTlf, acNull, acNull } },
154  /* evRXR */ { stClosed, { acNull, acNull, acNull } },
155  },
156  { /* stStopped */
157  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
158  /* evDown */ { stStarting, { acTls, acNull, acNull } },
159  /* evOpen */ { stStopped, { acNull, acNull, acNull } },
160  /* evClose */ { stClosed, { acNull, acNull, acNull } },
161  /* evTOp */ { stNoChange, { acNull, acNull, acNull } },
162  /* evTOm */ { stNoChange, { acNull, acNull, acNull } },
163  /* evRCRp */ { stAckSent, { acIrc, acScr, acSca } },
164  /* evRCRm */ { stReqSent, { acIrc, acScr, acScn } },
165  /* evRCA */ { stStopped, { acSta, acNull, acNull } },
166  /* evRCN */ { stStopped, { acSta, acNull, acNull } },
167  /* evRTR */ { stStopped, { acSta, acNull, acNull } },
168  /* evRTA */ { stStopped, { acNull, acNull, acNull } },
169  /* evRUC */ { stStopped, { acScj, acNull, acNull } },
170  /* evRXJp */ { stStopped, { acNull, acNull, acNull } },
171  /* evRXJm */ { stStopped, { acTlf, acNull, acNull } },
172  /* evRXR */ { stStopped, { acNull, acNull, acNull } },
173  },
174  { /* stClosing */
175  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
176  /* evDown */ { stInitial, { acNull, acNull, acNull } },
177  /* evOpen */ { stStopping, { acNull, acNull, acNull } },
178  /* evClose */ { stClosing, { acNull, acNull, acNull } },
179  /* evTOp */ { stClosing, { acStr, acNull, acNull } },
180  /* evTOm */ { stClosed, { acTlf, acNull, acNull } },
181  /* evRCRp */ { stClosing, { acNull, acNull, acNull } },
182  /* evRCRm */ { stClosing, { acNull, acNull, acNull } },
183  /* evRCA */ { stClosing, { acNull, acNull, acNull } },
184  /* evRCN */ { stClosing, { acNull, acNull, acNull } },
185  /* evRTR */ { stClosing, { acSta, acNull, acNull } },
186  /* evRTA */ { stClosed, { acTlf, acNull, acNull } },
187  /* evRUC */ { stClosing, { acScj, acNull, acNull } },
188  /* evRXJp */ { stClosing, { acNull, acNull, acNull } },
189  /* evRXJm */ { stClosed, { acTlf, acNull, acNull } },
190  /* evRXR */ { stClosing, { acNull, acNull, acNull } },
191  },
192  { /* stStopping */
193  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
194  /* evDown */ { stInitial, { acNull, acNull, acNull } },
195  /* evOpen */ { stStopping, { acNull, acNull, acNull } },
196  /* evClose */ { stClosing, { acNull, acNull, acNull } },
197  /* evTOp */ { stStopping, { acStr, acNull, acNull } },
198  /* evTOm */ { stStopped, { acTlf, acNull, acNull } },
199  /* evRCRp */ { stStopping, { acNull, acNull, acNull } },
200  /* evRCRm */ { stStopping, { acNull, acNull, acNull } },
201  /* evRCA */ { stStopping, { acNull, acNull, acNull } },
202  /* evRCN */ { stStopping, { acNull, acNull, acNull } },
203  /* evRTR */ { stStopping, { acSta, acNull, acNull } },
204  /* evRTA */ { stStopped, { acTlf, acNull, acNull } },
205  /* evRUC */ { stStopping, { acScj, acNull, acNull } },
206  /* evRXJp */ { stStopping, { acNull, acNull, acNull } },
207  /* evRXJm */ { stStopped, { acTlf, acNull, acNull } },
208  /* evRXR */ { stStopping, { acNull, acNull, acNull } },
209  },
210  { /* stReqSent */
211  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
212  /* evDown */ { stStarting, { acNull, acNull, acNull } },
213  /* evOpen */ { stReqSent, { acNull, acNull, acNull } },
214  /* evClose */ { stClosing, { acIrc, acStr, acNull } },
215  /* evTOp */ { stReqSent, { acScr, acNull, acNull } },
216  /* evTOm */ { stStopped, { acTlf, acNull, acNull } },
217  /* evRCRp */ { stAckSent, { acSca, acNull, acNull } },
218  /* evRCRm */ { stReqSent, { acScn, acNull, acNull } },
219  /* evRCA */ { stAckRcvd, { acIrc, acNull, acNull } },
220  /* evRCN */ { stReqSent, { acIrc, acScr, acNull } },
221  /* evRTR */ { stReqSent, { acSta, acNull, acNull } },
222  /* evRTA */ { stReqSent, { acNull, acNull, acNull } },
223  /* evRUC */ { stReqSent, { acScj, acNull, acNull } },
224  /* evRXJp */ { stReqSent, { acNull, acNull, acNull } },
225  /* evRXJm */ { stStopped, { acTlf, acNull, acNull } },
226  /* evRXR */ { stReqSent, { acNull, acNull, acNull } },
227  },
228  { /* stAckRcvd */
229  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
230  /* evDown */ { stStarting, { acNull, acNull, acNull } },
231  /* evOpen */ { stAckRcvd, { acNull, acNull, acNull } },
232  /* evClose */ { stClosing, { acIrc, acStr, acNull } },
233  /* evTOp */ { stReqSent, { acScr, acNull, acNull } },
234  /* evTOm */ { stStopped, { acTlf, acNull, acNull } },
235  /* evRCRp */ { stOpened, { acSca, acTlu, acNull } },
236  /* evRCRm */ { stAckRcvd, { acScn, acNull, acNull } },
237  /* evRCA */ { stReqSent, { acScr, acNull, acNull } },
238  /* evRCN */ { stReqSent, { acScr, acNull, acNull } },
239  /* evRTR */ { stReqSent, { acSta, acNull, acNull } },
240  /* evRTA */ { stReqSent, { acNull, acNull, acNull } },
241  /* evRUC */ { stAckRcvd, { acScj, acNull, acNull } },
242  /* evRXJp */ { stReqSent, { acNull, acNull, acNull } },
243  /* evRXJm */ { stStopped, { acTlf, acNull, acNull } },
244  /* evRXR */ { stAckRcvd, { acNull, acNull, acNull } },
245  },
246  { /* stAckSent */
247  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
248  /* evDown */ { stStarting, { acNull, acNull, acNull } },
249  /* evOpen */ { stAckSent, { acNull, acNull, acNull } },
250  /* evClose */ { stClosing, { acIrc, acStr, acNull } },
251  /* evTOp */ { stAckSent, { acScr, acNull, acNull } },
252  /* evTOm */ { stStopped, { acTlf, acNull, acNull } },
253  /* evRCRp */ { stAckSent, { acSca, acNull, acNull } },
254  /* evRCRm */ { stReqSent, { acScn, acNull, acNull } },
255  /* evRCA */ { stOpened, { acIrc, acTlu, acNull } },
256  /* evRCN */ { stAckSent, { acIrc, acScr, acNull } },
257  /* evRTR */ { stReqSent, { acSta, acNull, acNull } },
258  /* evRTA */ { stAckSent, { acNull, acNull, acNull } },
259  /* evRUC */ { stAckSent, { acScj, acNull, acNull } },
260  /* evRXJp */ { stAckSent, { acNull, acNull, acNull } },
261  /* evRXJm */ { stStopped, { acTlf, acNull, acNull } },
262  /* evRXR */ { stAckSent, { acNull, acNull, acNull } },
263  },
264  { /* stOpened */
265  /* evUp */ { stNoChange, { acNull, acNull, acNull } },
266  /* evDown */ { stStarting, { acTld, acNull, acNull } },
267  /* evOpen */ { stOpened, { acNull, acNull, acNull } },
268  /* evClose */ { stClosing, { acTld, acIrc, acStr } },
269  /* evTOp */ { stNoChange, { acNull, acNull, acNull } },
270  /* evTOm */ { stNoChange, { acNull, acNull, acNull } },
271  /* evRCRp */ { stAckSent, { acTld, acScr, acSca } },
272  /* evRCRm */ { stReqSent, { acTld, acScr, acScn } },
273  /* evRCA */ { stReqSent, { acTld, acScr, acNull } },
274  /* evRCN */ { stReqSent, { acTld, acScr, acNull } },
275  /* evRTR */ { stStopping, { acTld, acZrc, acSta } },
276  /* evRTA */ { stReqSent, { acTld, acScr, acNull } },
277  /* evRUC */ { stOpened, { acScj, acNull, acNull } },
278  /* evRXJp */ { stOpened, { acNull, acNull, acNull } },
279  /* evRXJm */ { stStopping, { acTld, acIrc, acStr } },
280  /* evRXR */ { stOpened, { acSer, acNull, acNull } },
281  }
282  };
283 
284 
285 #if defined(USE_DEBUG)
286 
287 static const char *ph_str[] = {
288  "Dead", "Establish", "Authenticate",
289  "Network", "Terminate"
290  };
291 
292 static const char *ev_str[] = {
293  "Up", "Down", "Open", "Close", "TO+", "TO-",
294  "RCR+", "RCR-", "RCA", "RCN", "RTR", "RTA",
295  "RUC", "RXJ+", "RXJ-", "RXR"
296  };
297 
298 static const char *st_str[] = {
299  "Initial", "Starting", "Closed", "Stopped",
300  "Closing", "Stopping", "Req-Sent", "Ack-Rcvd",
301  "Ack-Sent", "Opened", "No-Change"
302  };
303 
304 static const char *ac_str[] = {
305  "Null", "irc", "scr", "tls", "tlf", "str", "sta",
306  "sca", "scn", "scj", "tld", "tlu", "zrc", "ser"
307  };
308 
309 /*
310  * Display contents of buffer
311  */
312 static void buffer_print (const char *verb, const BYTE *buf, int len)
313 {
314  int i, j;
315 
316  (*_printf) ("%s %d bytes:\n", verb, len);
317 
318  for (i = 0; i < len; i += 16)
319  {
320  (*_printf) (" %04X: ", i);
321  for (j = i; j < len && j < i + 16; j++)
322  (*_printf) (" %02X", buf[j]);
323  (*_printf) ("\n");
324  }
325 }
326 
327 /*
328  * Print text string safely.
329  */
330 static void safe_string (const BYTE *bp, int len)
331 {
332  (*_printf) ("\"");
333 
334  while (--len >= 0)
335  {
336  char buf[2];
337  int chr = *bp++;
338 
339  buf[0] = chr;
340  buf[1] ='\0';
341  if (isascii(chr) && isprint(chr))
342  (*_printf) (buf);
343  else (*_printf) ("\\%03o", chr);
344  }
345 
346  (*_printf) ("\"");
347 }
348 
349 /*
350  * Show all options in negotiation message.
351  */
352 static void option_show (const struct ppp_state *state,
353  const struct ppp_xcp *xcp,
354  const BYTE *bp, int rlen)
355 {
356  while (rlen > 0)
357  {
358  const struct xcp_type *tp;
359  int i;
360 
361  (*_printf) (" ");
362  if (rlen < 2)
363  {
364  (*_printf) ("[trail %02X]\n", bp[0]);
365  break;
366  }
367  if (bp[1] > rlen)
368  {
369  (*_printf) ("[trunc %02X %d>%d]\n", bp[0], bp[1], rlen);
370  break;
371  }
372  for (tp = xcp->types; tp->type != -1; tp++)
373  if (tp->type == bp[0])
374  break;
375 
376  if (tp->show)
377  {
378  /* Valid option; use defined printing routine
379  */
380  (*tp->show) ((struct ppp_state*)state, (struct ppp_xcp*)xcp,
381  tp, bp + 2, bp[1]);
382  }
383  else
384  {
385  /* Undefined option; just dump contents.
386  */
387  if (tp->name == NULL)
388  (*_printf) ("%02X:", bp[0]);
389  else (*_printf) ("%s:", tp->name);
390  for (i = 2; i < bp[1]; i++)
391  (*_printf) ("%02X", bp[i]);
392  }
393  i = bp[1];
394  if (i < 2)
395  i = 2;
396  rlen -= i;
397  bp += i;
398  }
399 }
400 
401 /*
402  * Show a negotiation packet.
403  * Assumes 'bp' points to the code number (after PPP Protocol ID).
404  */
405 static void show_packet (const char *inout, const struct ppp_state *state,
406  const struct ppp_xcp *xcp, const BYTE *bp, int len)
407 {
408  static const char *code_str[] = {
409  "Vendor", "Configure-Request", "Configure-Ack",
410  "Configure-Nak", "Configure-Reject", "Terminate-Request",
411  "Terminate-Ack", "Code-Reject", "Protocol-Reject",
412  "Echo-Request", "Echo-Reply", "Discard-Request"
413  };
414  int code = *bp++;
415  int id = *bp++;
416  int length = intel16 (*(WORD*)bp);
417 
418  bp += 2;
419  if (len > length)
420  len = length;
421  len -= PPP_HDRLEN;
422 
423  (*_printf) ("%s %s ", inout, xcp->name);
424  if (code < DIM(code_str) && code_str[code])
425  (*_printf) ("%s", code_str[code]);
426  else (*_printf) ("code:%d", code);
427 
428  (*_printf) (" ID:%d", id);
429  if ((code == CODE_CONF_ACK || code == CODE_CONF_NAK ||
430  code == CODE_CONF_REJ || code == CODE_TERM_ACK ||
431  code == CODE_ECHO_REP) && id != xcp->ident)
432  (*_printf) (" **ERR**");
433  (*_printf) (" len:%d", length);
434 
435  switch (code)
436  {
437  case CODE_CONF_REQ:
438  case CODE_CONF_ACK:
439  case CODE_CONF_NAK:
440  case CODE_CONF_REJ:
441  option_show (state, xcp, bp, len);
442  break;
443  case CODE_TERM_REQ:
444  case CODE_TERM_ACK:
445  if (len > 0)
446  {
447  (*_printf) (" ");
448  safe_string (bp, len);
449  }
450  break;
451  case CODE_CODE_REJ:
452  (*_printf) (" code %d", *bp);
453  break;
454  case CODE_PROTO_REJ:
455  (*_printf) (" protocol %02X%02X", bp[0], bp[1]);
456  break;
457  case CODE_ECHO_REQ:
458  case CODE_ECHO_REP:
459  case CODE_DISCARD_REQ:
460  if (len >= 4)
461  (*_printf) (" magic %02X%02X%02X%02X", bp[0], bp[1], bp[2], bp[3]);
462  if (len > 4)
463  {
464  (*_printf) (" ");
465  safe_string (bp+4, len-4);
466  }
467  break;
468  }
469  (*_printf) ("\n");
470 }
471 
472 #undef PRINTF
473 #define PRINTF(lvl,arg) do { \
474  if (debug >= lvl) \
475  (*_printf) arg; \
476  } while (0)
477 #else
478  #undef PRINTF
479  #define PRINTF(lvl,arg) ((void)0)
480 #endif /* USE_DEBUG */
481 
482 
483 /*
484  * Write packet to PPPoE session. Display contents if debugging.
485  */
486 static void ppp_write (const struct ppp_state *state,
487  const struct ppp_xcp *xcp,
488  const BYTE *buf, int len)
489 {
490  WATT_ASSERT (state);
491  WATT_ASSERT (xcp);
492 
493 #if defined(USE_DEBUG)
494  if (debug > 3)
495  buffer_print ("Transmitting", buf, len);
496 
497  if (debug > 2)
498  {
499  int retv = buf[0] == 0xFF ? 2 : 0;
500  retv += buf[retv] & 1 ? 1 : 2;
501  show_packet ("SENT", state, xcp, buf + retv, len - retv);
502  }
503 #endif
504  pppoe_send_sess (NULL /*\todo state->sock */, buf, len);
505 
506  ARGSUSED (state);
507  ARGSUSED (xcp);
508 }
509 
510 /*
511  * Insert PPP protocol field.
512  */
513 static __inline BYTE *setup_acpf (BYTE *buf, WORD proto)
514 {
515  *(WORD*)buf = intel16 (proto);
516  return (buf + 2);
517 }
518 
519 /*
520  * Set up buffer for a new message (Configure-Request, Protocol-Reject,
521  * Echo-Request, or Discard-Request).
522  */
523 static BYTE *code_id (struct ppp_state *state, struct ppp_xcp *xcp, int code)
524 {
525  BYTE *buf = setup_acpf (state->outbuffer, xcp->proto);
526 
527  *buf++ = code;
528  *buf++ = ++xcp->ident;
529  *buf++ = 0;
530  *buf++ = 4;
531  return (buf);
532 }
533 
534 /*
535  * Set up buffer for a reply to a previous message (Configure-Ack,
536  * Configure-Nak, Configure-Reject, Echo-Reply).
537  */
538 static BYTE *code_reply (struct ppp_state *state, struct ppp_xcp *xcp, int code)
539 {
540  BYTE *buf = setup_acpf (state->outbuffer, xcp->proto);
541 
542  *buf++ = code;
543  *buf++ = state->inbuffer[3]; /* ident */
544  *buf++ = 0;
545  *buf++ = 4;
546  return (buf);
547 }
548 
549 /*
550  * Find a given option in the list for an XCP.
551  */
552 static struct option_state *find_option (const struct ppp_xcp *xcp, int type)
553 {
554  const struct xcp_type *tp;
555 
556  for (tp = xcp->types; tp->type != -1; tp++)
557  if (tp->type == type)
558  return (xcp->opts + (tp - xcp->types));
559  return (NULL);
560 }
561 
562 /*
563  * Loop over all known options and insert into a Configure-Request
564  * being built.
565  */
566 static void create_request (struct ppp_state *state, struct ppp_xcp *xcp)
567 {
568  struct xcp_type *tp;
569  struct option_state *os;
570  BYTE *bp, *obp;
571 
572  obp = bp = code_id (state, xcp, CODE_CONF_REQ);
573  for (tp = xcp->types, os = xcp->opts; tp->type != -1; tp++, os++)
574  {
575  if (os->state == osUnusable)
576  continue;
577 
578  if (!tp->flag && os->my_value == tp->default_value)
579  continue;
580 
581  bp[0] = (BYTE) tp->type;
582  bp[1] = tp->minlen;
583  if (tp->minlen > 2)
584  bp[2] = (BYTE) (os->my_value >> (8 * (tp->minlen - 3))) & 0xFF;
585  if (tp->minlen > 3)
586  bp[3] = (BYTE) (os->my_value >> (8 * (tp->minlen - 4))) & 0xFF;
587  if (tp->minlen > 4)
588  bp[4] = (BYTE) (os->my_value >> (8 * (tp->minlen - 5))) & 0xFF;
589  if (tp->minlen > 5)
590  bp[5] = (BYTE) os->my_value;
591  bp += bp[1];
592  }
593  *(WORD*) (obp-2) = intel16 (bp-obp+4);
594  state->up = bp;
595 }
596 
597 /*
598  * We've gotten a Configure-Request we like (RCR+), so we're agreeing
599  * with the peer. Set up to send Configure-Ack.
600  */
601 static void copy_peer_values (const struct ppp_state *state, struct ppp_xcp *xcp)
602 {
603  struct option_state *os;
604  const struct xcp_type *tp;
605  const BYTE *bp;
606  int rlen;
607  DWORD val;
608 
609  for (tp = xcp->types, os = xcp->opts; tp->type != -1; tp++, os++)
610  os->peer_value = tp->default_value;
611  bp = state->bp;
612  rlen = state->mlen;
613  while (rlen > 0)
614  {
615  for (tp = xcp->types; tp->type != -1; tp++)
616  if (tp->type == bp[0])
617  break;
618 
619  os = xcp->opts + (tp - xcp->types);
620  val = bp[2];
621  if (bp[1] > 3)
622  val = (val << 8) + bp[3];
623  if (bp[1] > 4)
624  val = (val << 8) + bp[4];
625  if (bp[1] > 5)
626  val = (val << 8) + bp[5];
627  os->peer_value = val;
628  rlen -= bp[1];
629  bp += bp[1];
630  }
631 }
632 
633 /*
634  * Perform RFC 1661 actions as indicated by state machine.
635  */
636 static void dispatch_action (struct ppp_state *state, struct ppp_xcp *xcp,
637  enum xcp_action act)
638 {
639  BYTE *bp;
640 
641  if (act == acNull)
642  return;
643 
644  PRINTF (2, ("%s action %s (%d)\n", xcp->name, ac_str[act], act));
645 
646  switch (act)
647  {
648  case acNull:
649  break;
650 
651  case acIrc:
652  xcp->restart = state->phase == phTerminate ? MAX_TERMINATE : MAX_CONFIGURE;
653  state->timeout_period = INITIAL_TIMEOUT;
654  break;
655 
656  case acScr:
657  if (xcp->restart > 0)
658  {
659  xcp->restart--;
660  create_request (state, xcp);
661  ppp_write (state, xcp, state->outbuffer, state->up - state->outbuffer);
662  }
663  xcp->timeout = time (NULL) + state->timeout_period;
664  break;
665 
666  case acTls:
667  if (xcp == &state->xcps[XCP_IPCP])
668  send_event (state, &state->xcps[XCP_LCP], evOpen);
669  else change_phase (state, phEstablish);
670  break;
671 
672  case acTlf:
673  if (xcp == &state->xcps[XCP_IPCP])
674  send_event (state, &state->xcps[XCP_LCP], evClose);
675  else change_phase (state, phTerminate);
676  break;
677 
678  case acStr:
679  if (xcp->restart > 0)
680  {
681  xcp->restart--;
682  bp = code_id (state, xcp, CODE_TERM_REQ);
683  ppp_write (state, xcp, state->outbuffer, bp - state->outbuffer);
684  }
685  xcp->timeout = time (NULL) + state->timeout_period;
686  break;
687 
688  case acSta:
689  bp = code_reply (state, xcp, CODE_TERM_ACK);
690  ppp_write (state, xcp, state->outbuffer, bp - state->outbuffer);
691  break;
692 
693  case acSca:
694  copy_peer_values (state, xcp);
695  state->inbuffer[2] = CODE_CONF_ACK;
696  ppp_write (state, xcp, state->inbuffer, state->mlen +
697  (state->bp - state->inbuffer));
698  break;
699 
700  case acScn:
701  if (xcp->naks_sent++ >= MAX_FAILURE)
702  state->outbuffer[4] = CODE_CONF_REJ;
703  /* fall-through */
704 
705  case acScj:
706  ppp_write (state, xcp, state->outbuffer, state->up - state->outbuffer);
707  break;
708 
709  case acTld:
710  if (xcp == &state->xcps[XCP_LCP])
711  change_phase (state, phTerminate);
712  else PRINTF (0, ("IPCP down!\n"));
713  break;
714 
715  case acTlu:
716  if (xcp == &state->xcps[XCP_LCP])
717  change_phase (state, phAuthenticate);
718  else
719  {
720  struct option_state *os = find_option (xcp, 3);
721  DWORD addr = intel (os->my_value);
722 
723  my_ip_addr = addr;
724  PRINTF (0, ("IPCP up! Local address %s, ",
725  _inet_ntoa(NULL,addr)));
726  addr = intel (os->peer_value);
728  _arp_add_gateway (NULL, addr);
729  PRINTF (0, ("remote %s\n", _inet_ntoa(NULL,addr)));
730  }
731  xcp->restart = MAX_CONFIGURE;
732  xcp->timeout = 0;
733  break;
734 
735  case acZrc:
736  xcp->restart = 0;
737  state->timeout_period = INITIAL_TIMEOUT;
738  break;
739 
740  case acSer:
741  state->inbuffer[2] = CODE_ECHO_REP;
742  *(long*) (state->inbuffer + 6) = intel (state->mymagic);
743  ppp_write (state, xcp, state->inbuffer, state->mlen +
744  (state->bp - state->inbuffer));
745  break;
746  }
747 }
748 
749 /*
750  * Issue event into XCP state machine -- go to next state and
751  * invoke associated actions.
752  */
753 static void send_event (struct ppp_state *state, struct ppp_xcp *xcp,
754  enum ppp_event event)
755 {
756  const struct ppp_dispatch *dp = &ppp_dispatch [xcp->state][event];
757 
758  if (dp->next == stNoChange)
759  {
760  PRINTF (2, ("%s got illegal %s event (%d) in %s state (%d)\n"
761  "\t(RFC 1661 section 4.4)\n",
762  xcp->name, ev_str[event], event, st_str[xcp->state],
763  xcp->state));
764  }
765  else
766  {
767  PRINTF (2, ("%s got %s event (%d) in %s state (%d), next is %s state (%d)\n",
768  xcp->name, ev_str[event], event, st_str[xcp->state],
769  xcp->state, st_str[dp->next], dp->next));
770  xcp->state = dp->next;
771  }
772  dispatch_action (state, xcp, dp->act[0]);
773  dispatch_action (state, xcp, dp->act[1]);
774  dispatch_action (state, xcp, dp->act[2]);
775 }
776 
777 /*
778  * Change overall link phase. Central routine helps with
779  * debugging.
780  */
781 static void change_phase (struct ppp_state *state, enum ppp_phase phase)
782 {
783  PRINTF (2, ("Current PPP phase is %s, switching to %s\n",
784  ph_str[state->phase], ph_str[phase]));
785 
786  switch (phase)
787  {
788  case phEstablish:
789  if (state->phase == phDead)
790  send_event (state, &state->xcps[XCP_LCP], evUp);
791  break;
792  case phAuthenticate:
793  break;
794  case phNetwork:
795  if (state->phase == phAuthenticate)
796  send_event (state, &state->xcps[XCP_IPCP], evUp);
797  break;
798  case phTerminate:
799  send_event (state, &state->xcps[XCP_IPCP], evDown);
800  break;
801  case phDead:
802  break;
803  }
804  state->phase = phase;
805  if (phase == phAuthenticate)
806  change_phase (state, phNetwork); /* XXX - no auth yet */
807 }
808 
809 /*
810  * Check for time-outs
811  */
812 static void check_timeouts (void)
813 {
814  time_t now;
815  int i;
816 
817  if (mystate.timeout_period < MAX_TIMEOUT)
818  mystate.timeout_period <<= 1;
819  now = time (NULL);
820 
821  for (i = 0; i < DIM(mystate.xcps); i++)
822  {
823  if (mystate.xcps[i].timeout && now >= mystate.xcps[i].timeout)
824  {
825  mystate.xcps[i].timeout = 0;
826 
827  /* Hack -- send with same ID on timeout.
828  */
829  if (mystate.xcps[i].restart > 0)
830  mystate.xcps[i].ident--;
831 
832  PRINTF (4, ("Sending TO%c to %s\n",
833  mystate.xcps[i].restart > 0 ? '+' : '-',
834  mystate.xcps[i].name));
835 
836  send_event (&mystate, mystate.xcps+i,
837  mystate.xcps[i].restart > 0 ? evTOp : evTOm);
838  }
839  }
840 }
841 
845 void ppp_input (const BYTE *inbuffer, WORD len)
846 {
847  struct ppp_state *state = &mystate;
848  int i;
849  WORD proto;
850 
851  state->inbuffer = (BYTE*) inbuffer;
852 
853 #if defined(USE_DEBUG)
854  if (debug > 3)
855  buffer_print ("Received", state->inbuffer, len);
856 #endif
857 
858 #if 0 /* no proto-compression used in PPPoE */
859  if (state->inbuffer[0] & 0x1)
860  {
861  proto = state->inbuffer[0];
862  state->inbuffer++;
863  len--;
864  }
865  else if (state->inbuffer[1] & 0x1)
866  {
867  proto = intel16 (*(WORD*)state->inbuffer);
868  state->inbuffer += 2;
869  len -=2;
870  }
871  else
872  {
873  proto = intel16 (*(WORD*)state->inbuffer);
874  PRINTF (0, ("Bad protocol field %04X\n", proto));
875  return;
876  }
877 #else
878  proto = intel16 (*(WORD*)state->inbuffer);
879  state->inbuffer += 2;
880  len -= 2;
881 #endif
882 
883  if (proto == PPP_IP)
884  {
885  _ip4_handler ((const in_Header*)state->inbuffer, FALSE);
886  return;
887  }
888 
889  /* Find XCP (IPCP/LCP) for indicated protocol
890  */
891  for (i = 0; i < DIM(state->xcps); i++)
892  if (state->xcps[i].proto == proto)
893  break;
894 
895  if (i >= DIM(state->xcps))
896  {
897  /* Generate LCP Protocol-Reject for unknown things.
898  */
899  PRINTF (0, ("Unknown protocol 0x%04X\n", proto));
900 
901  if (state->xcps[XCP_LCP].state == stOpened)
902  {
903  BYTE *bp = code_id (state, &state->xcps[XCP_LCP], CODE_PROTO_REJ);
904 
905  i = sizeof(state->outbuffer) - (bp - state->outbuffer);
906  if (len > i)
907  len = i;
908  memcpy (bp, state->inbuffer-2, len);
909  len += bp - state->outbuffer;
910  *(WORD*) (state->outbuffer+2) = intel16 (len-4);
911  ppp_write (state, &state->xcps[XCP_LCP], state->outbuffer, len);
912  }
913  return;
914  }
915 
916  state->bp = state->inbuffer;
917  state->mlen = len;
918  (*state->xcps[i].deliver) (state, state->xcps + i);
919 }
920 
921 /*
922  * Add current option to list of options to be sent in Configure-Reject.
923  */
924 static void set_reject (struct ppp_state *state, struct ppp_xcp *xcp,
925  const BYTE *bp)
926 {
927  int i;
928 
929  if (state->parse_state == psBad)
930  return;
931 
932  /* If this is the first reject for this packet, then set up.
933  */
934  if (state->parse_state != psRej)
935  {
936  state->up = code_reply (state, xcp, CODE_CONF_REJ);
937  state->parse_state = psRej;
938  }
939 
940  /* Handle malformed options; make sure we don't send anything illegal
941  * to the peer (even if he's sending us junk).
942  */
943  i = bp[1];
944  if (i < 2)
945  i = 2;
946  memcpy (state->up, bp, i);
947  state->up[1] = i;
948  state->up += i;
949 }
950 
951 /*
952  * Add current option to list of options to be sent in Configure-Nak.
953  */
954 static void set_nak (struct ppp_state *state, struct ppp_xcp *xcp, int type,
955  int len, const BYTE *bp)
956 {
957  /* If we're rejecting, then no point in doing naks.
958  */
959  if (state->parse_state == psBad || state->parse_state == psRej)
960  return;
961 
962  /* If this is the first nak for this packet, then set up.
963  */
964  if (state->parse_state != psNak)
965  {
966  state->up = code_reply (state, xcp, CODE_CONF_NAK);
967  state->parse_state = psNak;
968  }
969  *state->up++ = type;
970  *state->up++ = len;
971  while (--len > 1)
972  *state->up++ = *bp++;
973 }
974 
975 /*
976  * Check Configure-Request options from peer against list of
977  * known, valid, and desired options.
978  */
979 static int validate_request (struct ppp_state *state, struct ppp_xcp *xcp)
980 {
981  const struct xcp_type *tp;
982  const BYTE *bp;
983  int rlen, i;
984 
985  state->parse_state = psOK;
986  rlen = state->mlen;
987  bp = state->bp;
988 
989  while (rlen > 0)
990  {
991  if (rlen < 2 || bp[1] > rlen)
992  {
993  state->parse_state = psBad;
994  break;
995  }
996  for (tp = xcp->types; tp->type != -1; tp++)
997  if (tp->type == bp[0])
998  break;
999 
1000  if (tp->type == -1)
1001  set_reject (state, xcp, bp);
1002  else if (bp[1] < tp->minlen)
1003  set_nak (state, xcp, tp->type, tp->minlen, bp + 2);
1004  else if (bp[1] > tp->maxlen)
1005  set_nak (state, xcp, tp->type, tp->maxlen, bp + 2);
1006  else if (tp->validate_req)
1007  (*tp->validate_req) (state, xcp, tp, bp + 2, bp[1]);
1008 
1009  i = bp[1];
1010  if (i < 2)
1011  i = 2;
1012  rlen -= i;
1013  bp += i;
1014  }
1015  if (state->parse_state == psNak || state->parse_state == psRej)
1016  {
1017  i = (state->up - state->outbuffer) - 4;
1018  state->outbuffer[6] = (i >> 8) & 0xFF;
1019  state->outbuffer[7] = i & 0xFF;
1020  }
1021  return (state->parse_state == psOK);
1022 }
1023 
1024 /*
1025  * Process options in a Configure-{Ack,Nak,Reject}.
1026  */
1027 static void process_rcx (struct ppp_state *state, struct ppp_xcp *xcp, BYTE code)
1028 {
1029  struct option_state *os;
1030  const struct xcp_type *tp;
1031  int rlen, i, val;
1032  BYTE *bp;
1033 
1034  rlen = state->mlen;
1035  bp = state->bp;
1036 
1037  while (rlen > 0)
1038  {
1039  if (rlen < 2 || bp[1] > rlen)
1040  break;
1041 
1042  for (tp = xcp->types; tp->type != -1; tp++)
1043  if (tp->type == bp[0])
1044  break;
1045 
1046  if (tp->type != -1)
1047  {
1048  os = xcp->opts + (tp - xcp->types);
1049  if (code == CODE_CONF_REJ)
1050  os->state = osUnusable;
1051  else if (code == CODE_CONF_ACK || tp->validate_nak == NULL)
1052  {
1053  if (bp[1] > 6 || bp[1] <= 2)
1054  os->my_value = tp->default_value;
1055  else
1056  {
1057  val = bp[2];
1058  if (bp[1] > 3)
1059  val = (val << 8) + bp[3];
1060  if (bp[1] > 4)
1061  val = (val << 8) + bp[4];
1062  if (bp[1] > 5)
1063  val = (val << 8) + bp[5];
1064  os->my_value = val;
1065  }
1066  }
1067  else
1068  (*tp->validate_nak) (state, xcp, tp, bp + 2, bp[1]);
1069  }
1070  if ((i = bp[1]) < 2)
1071  i = 2;
1072  rlen -= i;
1073  bp += i;
1074  }
1075 }
1076 
1077 /*
1078  * Standard negotiation entry point. This is assigned as the
1079  * 'delivery' function for control protocols, like LCP and IPCP.
1080  */
1081 static void std_negotiation (struct ppp_state *state, struct ppp_xcp *xcp)
1082 {
1083  BYTE code, id;
1084  WORD proto;
1085  int i, length;
1086 
1087  /* Validate overall message length
1088  */
1089  if (state->mlen < 4)
1090  {
1091  PRINTF (0, ("Malformed negotiation message; %d < 4\n", state->mlen));
1092  return;
1093  }
1094 
1095  code = *state->bp++;
1096  id = *state->bp++;
1097  length = intel16 (*(WORD*)state->bp); /* !! */
1098  if (length > state->mlen)
1099  {
1100  PRINTF (0, ("Truncated negotiation message; %d > %d\n",
1101  length, state->mlen));
1102  return;
1103  }
1104  if (length < state->mlen)
1105  {
1106  PRINTF (0, ("Trimmed negotiation message; %d < %d\n",
1107  length, state->mlen));
1108  state->mlen = length;
1109  }
1110  state->bp += 2;
1111  state->mlen -= 4;
1112 
1113 #if defined(USE_DEBUG)
1114  if (debug > 2)
1115  show_packet ("RCVD", state, xcp, state->bp-4, state->mlen+4);
1116 #endif
1117 
1118  /* Now switch out on received code number
1119  */
1120  switch (code)
1121  {
1122  case CODE_CONF_REQ:
1123  /* If request is good, then RCR+, if bad, then RCR-
1124  */
1125  if (validate_request (state, xcp))
1126  send_event (state, xcp, evRCRp);
1127  else send_event (state, xcp, evRCRm);
1128  break;
1129 
1130  case CODE_CONF_ACK:
1131  /* Configure-Ack ID number must match last sent.
1132  */
1133  if (id == xcp->ident)
1134  {
1135  /* Should validate contents against last req sent, but we don't.
1136  */
1137  process_rcx (state, xcp, code);
1138  send_event (state, xcp, evRCA);
1139  }
1141  break;
1142 
1143  case CODE_CONF_NAK:
1144  case CODE_CONF_REJ:
1145  /* Configure-Nak/Reject ID number must match last sent.
1146  */
1147  if (id == xcp->ident)
1148  {
1149  process_rcx (state, xcp, code);
1150  send_event (state, xcp, evRCN);
1151  }
1152  break;
1153 
1154  case CODE_TERM_REQ:
1155  send_event (state, xcp, evRTR);
1156  break;
1157 
1158  case CODE_TERM_ACK:
1159  if (id == xcp->ident)
1160  send_event (state, xcp, evRTA);
1161  break;
1162 
1163  case CODE_CODE_REJ:
1164  code = *state->bp++;
1165 
1166  /* Peer cannot reject well-known code numbers.
1167  */
1168  if (code && code < CODE_ECHO_REQ)
1169  {
1170  PRINTF (0, ("Invalid code reject for %d\n", code));
1171  send_event (state, xcp, evRXJm);
1172  }
1173  else
1174  send_event (state, xcp, evRXJp);
1175  break;
1176 
1177  case CODE_PROTO_REJ:
1178  proto = intel16 (*(WORD*)state->bp); /* !! */
1179 
1180  /* Peer cannot reject LCP!
1181  */
1182  if (proto == state->xcps[XCP_LCP].proto)
1183  {
1184  PRINTF (0, ("Peer protocol-rejected LCP itself!\n"));
1185  send_event (state, &state->xcps[XCP_LCP], evRXJm);
1186  }
1187  else
1188  {
1189  send_event (state, xcp, evRXJp);
1190  for (i = 0; i < DIM(state->xcps); i++)
1191  if (state->xcps[i].proto == proto)
1192  state->xcps[i].state = stInitial;
1193  }
1194  break;
1195 
1196  case CODE_ECHO_REQ:
1197  /* send a reply here. */
1198  send_event (state, xcp, evRXR);
1199  break;
1200 
1201  case CODE_DISCARD_REQ:
1202  send_event (state, xcp, evRXR);
1203  break;
1204 
1205  case CODE_ECHO_REP:
1206  /* ID number in Echo-Reply must match last echo sent.
1207  */
1208  if (id == xcp->ident)
1209  send_event (state, xcp, evRXR);
1210  break;
1211 
1212  default:
1213  state->bp -= 4;
1214  send_event (state, xcp, evRUC);
1215  break;
1216  }
1217 }
1218 
1219 /*
1220  * Initialize an XCP (LCP or NCP).
1221  */
1222 static void init_xcp (const char *name, struct ppp_xcp *xcp,
1223  void (*deliver) (struct ppp_state *state,
1224  struct ppp_xcp *xcp),
1225  const struct xcp_type *types, int ntypes, WORD proto)
1226 {
1227  struct option_state *os;
1228 
1229  xcp->name = name;
1230  xcp->state = stInitial;
1231  xcp->restart = 0;
1232  xcp->timeout = 0;
1233  xcp->deliver = deliver;
1234  xcp->types = (struct xcp_type*)types;
1235  xcp->proto = proto;
1236 
1237  /* If no options, then no vector to store negotiated values.
1238  */
1239  if (ntypes <= 0)
1240  {
1241  xcp->opts = NULL;
1242  return;
1243  }
1244  /* Otherwise, allocate vector and initialize options
1245  */
1246  os = xcp->opts = (struct option_state*) calloc (ntypes, sizeof(*os));
1247 
1248  while (--ntypes >= 0)
1249  {
1250  os->my_value = os->peer_value = types->default_value;
1251  os->state = osUsable;
1252  os++;
1253  types++;
1254  }
1255 }
1256 
1257 /*
1258  * Handle Configure-Request from peer. If it's in the range we think
1259  * it should be, then do nothing (allow Configure-Ack). Otherwise,
1260  * send Configure-Nak with something more appropriate.
1261  */
1262 static void ipcp_addr_req (struct ppp_state *state,
1263  struct ppp_xcp *xcp,
1264  const struct xcp_type *tp,
1265  const BYTE *buf, int len)
1266 {
1267  struct option_state *os;
1268  BYTE lbuf[4];
1269  DWORD addr = intel (*(DWORD*)buf);
1270 
1271  os = xcp->opts + (tp - xcp->types);
1272  if (addr != os->my_value && (addr & remote_ip_mask) == remote_ip_base)
1273  return;
1274 
1275  addr = xcp->opts [tp-xcp->types].peer_value;
1276  *(DWORD*) &lbuf = intel (addr);
1277  set_nak (state, xcp, tp->type, tp->minlen, lbuf);
1278  ARGSUSED (len);
1279 }
1280 
1281 /*
1282  * Got a Configure-Nak of our address. Just change; we're flexible.
1283  */
1284 static void ipcp_addr_nak (struct ppp_state *state,
1285  struct ppp_xcp *xcp,
1286  const struct xcp_type *tp,
1287  const BYTE *buf, int len)
1288 {
1289  xcp->opts [tp-xcp->types].my_value = intel (*(DWORD*)buf);
1290  ARGSUSED (state);
1291  ARGSUSED (len);
1292 }
1293 
1294 /*
1295  * Show IP address.
1296  */
1297 static void ipcp_addr_show (struct ppp_state *state,
1298  struct ppp_xcp *xcp, const struct xcp_type *tp,
1299  const BYTE *buf, int len)
1300 {
1301  PRINTF (0, ("%s", _inet_ntoa(NULL, intel(*(DWORD*)buf))));
1302  ARGSUSED (state);
1303  ARGSUSED (xcp);
1304  ARGSUSED (tp);
1305  ARGSUSED (buf);
1306  ARGSUSED (len);
1307 }
1308 
1309 /*
1310  * Set local value (for Configure-Request).
1311  */
1312 static void set_option_value_lcl (struct ppp_xcp *xcp, int type, int value)
1313 {
1314  struct option_state *os = find_option (xcp, type);
1315 
1316  if (os)
1317  os->my_value = value;
1318 }
1319 
1320 /*
1321  * Set desired value for peer (we'll Configure-Nak with this).
1322  */
1323 static void set_option_value_rem (struct ppp_xcp *xcp, int type, int value)
1324 {
1325  struct option_state *os = find_option (xcp, type);
1326 
1327  if (os)
1328  os->peer_value = value;
1329 }
1330 
1331 void ppp_start (int dbg_level)
1332 {
1333  struct ppp_state *state = &mystate;
1334 
1335  debug = dbg_level;
1336 
1337  /* Initialize PPP state machine and add LCP and IPCP.
1338  */
1339  state->phase = phDead;
1340  state->timeout_period = INITIAL_TIMEOUT;
1341  state->mymagic = Random (0, UINT_MAX);
1342 
1343  init_xcp ("LCP", &state->xcps[XCP_LCP], std_negotiation,
1344  lcp_types, DIM(lcp_types) - 1, PPP_LCP);
1345 
1346  init_xcp ("IPCP", &state->xcps[XCP_IPCP], std_negotiation,
1347  ipcp_types, DIM(ipcp_types) - 1, PPP_IPCP);
1348 
1349  set_option_value_lcl (&state->xcps[XCP_IPCP], 3, 0x0A000000 + (rand() % 1000));
1350  set_option_value_rem (&state->xcps[XCP_IPCP], 3, 0x0A00000A + (rand() % 1000));
1351 
1352  /* Tell LCP to open
1353  */
1354  send_event (state, &state->xcps[XCP_IPCP], evOpen);
1355 
1356  /* Add handler for checking timeouts (via tcp_tick)
1357  */
1358  DAEMON_ADD (check_timeouts);
1359 }
1360 
1361 #endif /* USE_PPPOE */
1362 
unsigned W32_CALL Random(unsigned a, unsigned b)
Returns a random integer in range [a..b].
Definition: misc.c:742
Definition: ppp.h:96
int _ip4_handler(const in_Header *ip, BOOL broadcast)
Definition: ip4_in.c:34
BOOL W32_CALL _arp_add_gateway(const char *config_string, DWORD ip)
Add a gateway to the routing table.
Definition: pcarp.c:247
void W32_CALL _arp_kill_gateways(void)
Delete all gateways.
Definition: pcarp.c:373
Core definitions.
int pppoe_send_sess(const void *sock, const BYTE *buf, WORD len)
Build and send a PPPoE Session packet (IPCP or LCP packet).
Definition: pppoe.c:357
static void std_negotiation(struct ppp_state *state, struct ppp_xcp *xcp)
Definition: ppp.c:1081
Definition: zinftree.h:24
void ppp_input(const BYTE *inbuffer, WORD len)
The PPP input handler.
Definition: ppp.c:845
DWORD my_ip_addr
our IP address
Definition: pctcp.c:70
Definition: ppp.h:114
Definition: ppp.h:73
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43