OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_130/] [src/] [netif/] [ppp/] [ipcp.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*****************************************************************************
2
* ipcp.c - Network PPP IP Control Protocol program file.
3
*
4
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5
* portions Copyright (c) 1997 by Global Election Systems Inc.
6
*
7
* The authors hereby grant permission to use, copy, modify, distribute,
8
* and license this software and its documentation for any purpose, provided
9
* that existing copyright notices are retained in all copies and that this
10
* notice and the following disclaimer are included verbatim in any
11
* distributions. No written agreement, license, or royalty fee is required
12
* for any of the authorized uses.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
*
25
******************************************************************************
26
* REVISION HISTORY
27
*
28
* 03-01-01 Marc Boucher <marc@mbsi.ca>
29
*   Ported to lwIP.
30
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
31
*   Original.
32
*****************************************************************************/
33
/*
34
 * ipcp.c - PPP IP Control Protocol.
35
 *
36
 * Copyright (c) 1989 Carnegie Mellon University.
37
 * All rights reserved.
38
 *
39
 * Redistribution and use in source and binary forms are permitted
40
 * provided that the above copyright notice and this paragraph are
41
 * duplicated in all such forms and that any documentation,
42
 * advertising materials, and other materials related to such
43
 * distribution and use acknowledge that the software was developed
44
 * by Carnegie Mellon University.  The name of the
45
 * University may not be used to endorse or promote products derived
46
 * from this software without specific prior written permission.
47
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50
 */
51
 
52
#include "lwip/opt.h"
53
 
54
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
55
 
56
#include "ppp.h"
57
#include "pppdebug.h"
58
 
59
#include "auth.h"
60
#include "fsm.h"
61
#include "vj.h"
62
#include "ipcp.h"
63
 
64
#include <string.h>
65
 
66
/*************************/
67
/*** LOCAL DEFINITIONS ***/
68
/*************************/
69
/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */
70
 
71
/*
72
 * Lengths of configuration options.
73
 */
74
#define CILEN_VOID     2
75
#define CILEN_COMPRESS 4  /* min length for compression protocol opt. */
76
#define CILEN_VJ       6  /* length for RFC1332 Van-Jacobson opt. */
77
#define CILEN_ADDR     6  /* new-style single address option */
78
#define CILEN_ADDRS    10 /* old-style dual address option */
79
 
80
 
81
 
82
/***********************************/
83
/*** LOCAL FUNCTION DECLARATIONS ***/
84
/***********************************/
85
/*
86
 * Callbacks for fsm code.  (CI = Configuration Information)
87
 */
88
static void ipcp_resetci (fsm *);                     /* Reset our CI */
89
static int  ipcp_cilen (fsm *);                       /* Return length of our CI */
90
static void ipcp_addci (fsm *, u_char *, int *);      /* Add our CI */
91
static int  ipcp_ackci (fsm *, u_char *, int);        /* Peer ack'd our CI */
92
static int  ipcp_nakci (fsm *, u_char *, int);        /* Peer nak'd our CI */
93
static int  ipcp_rejci (fsm *, u_char *, int);        /* Peer rej'd our CI */
94
static int  ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
95
static void ipcp_up (fsm *);                          /* We're UP */
96
static void ipcp_down (fsm *);                        /* We're DOWN */
97
#if 0
98
static void ipcp_script (fsm *, char *); /* Run an up/down script */
99
#endif
100
static void ipcp_finished (fsm *);                    /* Don't need lower layer */
101
 
102
/*
103
 * Protocol entry points from main code.
104
 */
105
static void ipcp_init (int);
106
static void ipcp_open (int);
107
static void ipcp_close (int, char *);
108
static void ipcp_lowerup (int);
109
static void ipcp_lowerdown (int);
110
static void ipcp_input (int, u_char *, int);
111
static void ipcp_protrej (int);
112
 
113
static void ipcp_clear_addrs (int);
114
 
115
#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
116
                     (x) == CONFNAK ? "NAK" : "REJ")
117
 
118
 
119
 
120
/******************************/
121
/*** PUBLIC DATA STRUCTURES ***/
122
/******************************/
123
/* global vars */
124
ipcp_options ipcp_wantoptions[NUM_PPP];  /* Options that we want to request */
125
ipcp_options ipcp_gotoptions[NUM_PPP];   /* Options that peer ack'd */
126
ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
127
ipcp_options ipcp_hisoptions[NUM_PPP];   /* Options that we ack'd */
128
 
129
fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
130
 
131
struct protent ipcp_protent = {
132
  PPP_IPCP,
133
  ipcp_init,
134
  ipcp_input,
135
  ipcp_protrej,
136
  ipcp_lowerup,
137
  ipcp_lowerdown,
138
  ipcp_open,
139
  ipcp_close,
140
#if 0
141
  ipcp_printpkt,
142
  NULL,
143
#endif
144
  1,
145
  "IPCP",
146
#if 0
147
  ip_check_options,
148
  NULL,
149
  ip_active_pkt
150
#endif
151
};
152
 
153
 
154
 
155
/*****************************/
156
/*** LOCAL DATA STRUCTURES ***/
157
/*****************************/
158
/* local vars */
159
static int cis_received[NUM_PPP];      /* # Conf-Reqs received */
160
static int default_route_set[NUM_PPP]; /* Have set up a default route */
161
 
162
static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
163
  ipcp_resetci,  /* Reset our Configuration Information */
164
  ipcp_cilen,    /* Length of our Configuration Information */
165
  ipcp_addci,    /* Add our Configuration Information */
166
  ipcp_ackci,    /* ACK our Configuration Information */
167
  ipcp_nakci,    /* NAK our Configuration Information */
168
  ipcp_rejci,    /* Reject our Configuration Information */
169
  ipcp_reqci,    /* Request peer's Configuration Information */
170
  ipcp_up,       /* Called when fsm reaches LS_OPENED state */
171
  ipcp_down,     /* Called when fsm leaves LS_OPENED state */
172
  NULL,          /* Called when we want the lower layer up */
173
  ipcp_finished, /* Called when we want the lower layer down */
174
  NULL,          /* Called when Protocol-Reject received */
175
  NULL,          /* Retransmission is necessary */
176
  NULL,          /* Called to handle protocol-specific codes */
177
  "IPCP"         /* String name of protocol */
178
};
179
 
180
 
181
 
182
/**********************************/
183
/*** LOCAL FUNCTION DEFINITIONS ***/
184
/**********************************/
185
 
186
/*
187
 * Non-standard inet_ntoa left here for compat with original ppp
188
 * sources. Assumes u32_t instead of struct in_addr.
189
 */
190
 
191
char *
192
_inet_ntoa(u32_t n)
193
{
194
  struct in_addr ia;
195
  ia.s_addr = n;
196
  return inet_ntoa(ia);
197
}
198
 
199
#define inet_ntoa _inet_ntoa
200
 
201
/*
202
 * ipcp_init - Initialize IPCP.
203
 */
204
static void
205
ipcp_init(int unit)
206
{
207
  fsm           *f = &ipcp_fsm[unit];
208
  ipcp_options *wo = &ipcp_wantoptions[unit];
209
  ipcp_options *ao = &ipcp_allowoptions[unit];
210
 
211
  f->unit      = unit;
212
  f->protocol  = PPP_IPCP;
213
  f->callbacks = &ipcp_callbacks;
214
  fsm_init(&ipcp_fsm[unit]);
215
 
216
  memset(wo, 0, sizeof(*wo));
217
  memset(ao, 0, sizeof(*ao));
218
 
219
  wo->neg_addr      = 1;
220
  wo->ouraddr       = 0;
221
#if VJ_SUPPORT
222
  wo->neg_vj        = 1;
223
#else  /* VJ_SUPPORT */
224
  wo->neg_vj        = 0;
225
#endif /* VJ_SUPPORT */
226
  wo->vj_protocol   = IPCP_VJ_COMP;
227
  wo->maxslotindex  = MAX_SLOTS - 1;
228
  wo->cflag         = 0;
229
  wo->default_route = 1;
230
 
231
  ao->neg_addr      = 1;
232
#if VJ_SUPPORT
233
  ao->neg_vj        = 1;
234
#else  /* VJ_SUPPORT */
235
  ao->neg_vj        = 0;
236
#endif /* VJ_SUPPORT */
237
  ao->maxslotindex  = MAX_SLOTS - 1;
238
  ao->cflag         = 1;
239
  ao->default_route = 1;
240
}
241
 
242
 
243
/*
244
 * ipcp_open - IPCP is allowed to come up.
245
 */
246
static void
247
ipcp_open(int unit)
248
{
249
  fsm_open(&ipcp_fsm[unit]);
250
}
251
 
252
 
253
/*
254
 * ipcp_close - Take IPCP down.
255
 */
256
static void
257
ipcp_close(int unit, char *reason)
258
{
259
  fsm_close(&ipcp_fsm[unit], reason);
260
}
261
 
262
 
263
/*
264
 * ipcp_lowerup - The lower layer is up.
265
 */
266
static void
267
ipcp_lowerup(int unit)
268
{
269
  fsm_lowerup(&ipcp_fsm[unit]);
270
}
271
 
272
 
273
/*
274
 * ipcp_lowerdown - The lower layer is down.
275
 */
276
static void
277
ipcp_lowerdown(int unit)
278
{
279
  fsm_lowerdown(&ipcp_fsm[unit]);
280
}
281
 
282
 
283
/*
284
 * ipcp_input - Input IPCP packet.
285
 */
286
static void
287
ipcp_input(int unit, u_char *p, int len)
288
{
289
  fsm_input(&ipcp_fsm[unit], p, len);
290
}
291
 
292
 
293
/*
294
 * ipcp_protrej - A Protocol-Reject was received for IPCP.
295
 *
296
 * Pretend the lower layer went down, so we shut up.
297
 */
298
static void
299
ipcp_protrej(int unit)
300
{
301
  fsm_lowerdown(&ipcp_fsm[unit]);
302
}
303
 
304
 
305
/*
306
 * ipcp_resetci - Reset our CI.
307
 */
308
static void
309
ipcp_resetci(fsm *f)
310
{
311
  ipcp_options *wo = &ipcp_wantoptions[f->unit];
312
 
313
  wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
314
  if (wo->ouraddr == 0) {
315
    wo->accept_local = 1;
316
  }
317
  if (wo->hisaddr == 0) {
318
    wo->accept_remote = 1;
319
  }
320
  /* Request DNS addresses from the peer */
321
  wo->req_dns1 = ppp_settings.usepeerdns;
322
  wo->req_dns2 = ppp_settings.usepeerdns;
323
  ipcp_gotoptions[f->unit] = *wo;
324
  cis_received[f->unit] = 0;
325
}
326
 
327
 
328
/*
329
 * ipcp_cilen - Return length of our CI.
330
 */
331
static int
332
ipcp_cilen(fsm *f)
333
{
334
  ipcp_options *go = &ipcp_gotoptions[f->unit];
335
  ipcp_options *wo = &ipcp_wantoptions[f->unit];
336
  ipcp_options *ho = &ipcp_hisoptions[f->unit];
337
 
338
#define LENCIVJ(neg, old)   (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
339
#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
340
#define LENCIDNS(neg)       (neg ? (CILEN_ADDR) : 0)
341
 
342
  /*
343
   * First see if we want to change our options to the old
344
   * forms because we have received old forms from the peer.
345
   */
346
  if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
347
    /* use the old style of address negotiation */
348
    go->neg_addr = 1;
349
    go->old_addrs = 1;
350
  }
351
  if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
352
    /* try an older style of VJ negotiation */
353
    if (cis_received[f->unit] == 0) {
354
      /* keep trying the new style until we see some CI from the peer */
355
      go->neg_vj = 1;
356
    } else {
357
      /* use the old style only if the peer did */
358
      if (ho->neg_vj && ho->old_vj) {
359
        go->neg_vj = 1;
360
        go->old_vj = 1;
361
        go->vj_protocol = ho->vj_protocol;
362
      }
363
    }
364
  }
365
 
366
  return (LENCIADDR(go->neg_addr, go->old_addrs) +
367
          LENCIVJ(go->neg_vj, go->old_vj) +
368
          LENCIDNS(go->req_dns1) +
369
          LENCIDNS(go->req_dns2));
370
}
371
 
372
 
373
/*
374
 * ipcp_addci - Add our desired CIs to a packet.
375
 */
376
static void
377
ipcp_addci(fsm *f, u_char *ucp, int *lenp)
378
{
379
  ipcp_options *go = &ipcp_gotoptions[f->unit];
380
  int len = *lenp;
381
 
382
#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
383
  if (neg) { \
384
    int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
385
    if (len >= vjlen) { \
386
      PUTCHAR(opt, ucp); \
387
      PUTCHAR(vjlen, ucp); \
388
      PUTSHORT(val, ucp); \
389
      if (!old) { \
390
        PUTCHAR(maxslotindex, ucp); \
391
        PUTCHAR(cflag, ucp); \
392
      } \
393
      len -= vjlen; \
394
    } else { \
395
      neg = 0; \
396
    } \
397
  }
398
 
399
#define ADDCIADDR(opt, neg, old, val1, val2) \
400
  if (neg) { \
401
    int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
402
    if (len >= addrlen) { \
403
      u32_t l; \
404
      PUTCHAR(opt, ucp); \
405
      PUTCHAR(addrlen, ucp); \
406
      l = ntohl(val1); \
407
      PUTLONG(l, ucp); \
408
      if (old) { \
409
        l = ntohl(val2); \
410
        PUTLONG(l, ucp); \
411
      } \
412
      len -= addrlen; \
413
    } else { \
414
      neg = 0; \
415
    } \
416
  }
417
 
418
#define ADDCIDNS(opt, neg, addr) \
419
  if (neg) { \
420
    if (len >= CILEN_ADDR) { \
421
      u32_t l; \
422
      PUTCHAR(opt, ucp); \
423
      PUTCHAR(CILEN_ADDR, ucp); \
424
      l = ntohl(addr); \
425
      PUTLONG(l, ucp); \
426
      len -= CILEN_ADDR; \
427
    } else { \
428
      neg = 0; \
429
    } \
430
  }
431
 
432
  ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
433
      go->old_addrs, go->ouraddr, go->hisaddr);
434
 
435
  ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
436
      go->maxslotindex, go->cflag);
437
 
438
  ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
439
 
440
  ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
441
 
442
  *lenp -= len;
443
}
444
 
445
 
446
/*
447
 * ipcp_ackci - Ack our CIs.
448
 *
449
 * Returns:
450
 *  0 - Ack was bad.
451
 *  1 - Ack was good.
452
 */
453
static int
454
ipcp_ackci(fsm *f, u_char *p, int len)
455
{
456
  ipcp_options *go = &ipcp_gotoptions[f->unit];
457
  u_short cilen, citype, cishort;
458
  u32_t cilong;
459
  u_char cimaxslotindex, cicflag;
460
 
461
  /*
462
   * CIs must be in exactly the same order that we sent...
463
   * Check packet length and CI length at each step.
464
   * If we find any deviations, then this packet is bad.
465
   */
466
 
467
#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
468
  if (neg) { \
469
    int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
470
    if ((len -= vjlen) < 0) { \
471
      goto bad; \
472
    } \
473
    GETCHAR(citype, p); \
474
    GETCHAR(cilen, p); \
475
    if (cilen != vjlen || \
476
        citype != opt) { \
477
      goto bad; \
478
    } \
479
    GETSHORT(cishort, p); \
480
    if (cishort != val) { \
481
      goto bad; \
482
    } \
483
    if (!old) { \
484
      GETCHAR(cimaxslotindex, p); \
485
      if (cimaxslotindex != maxslotindex) { \
486
        goto bad; \
487
      } \
488
      GETCHAR(cicflag, p); \
489
      if (cicflag != cflag) { \
490
        goto bad; \
491
      } \
492
    } \
493
  }
494
 
495
#define ACKCIADDR(opt, neg, old, val1, val2) \
496
  if (neg) { \
497
    int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
498
    u32_t l; \
499
    if ((len -= addrlen) < 0) { \
500
      goto bad; \
501
    } \
502
    GETCHAR(citype, p); \
503
    GETCHAR(cilen, p); \
504
    if (cilen != addrlen || \
505
        citype != opt) { \
506
      goto bad; \
507
    } \
508
    GETLONG(l, p); \
509
    cilong = htonl(l); \
510
    if (val1 != cilong) { \
511
      goto bad; \
512
    } \
513
    if (old) { \
514
      GETLONG(l, p); \
515
      cilong = htonl(l); \
516
      if (val2 != cilong) { \
517
        goto bad; \
518
      } \
519
    } \
520
  }
521
 
522
#define ACKCIDNS(opt, neg, addr) \
523
  if (neg) { \
524
    u32_t l; \
525
    if ((len -= CILEN_ADDR) < 0) { \
526
      goto bad; \
527
    } \
528
    GETCHAR(citype, p); \
529
    GETCHAR(cilen, p); \
530
    if (cilen != CILEN_ADDR || \
531
        citype != opt) { \
532
      goto bad; \
533
    } \
534
    GETLONG(l, p); \
535
    cilong = htonl(l); \
536
    if (addr != cilong) { \
537
      goto bad; \
538
    } \
539
  }
540
 
541
  ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
542
        go->old_addrs, go->ouraddr, go->hisaddr);
543
 
544
  ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
545
      go->maxslotindex, go->cflag);
546
 
547
  ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
548
 
549
  ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
550
 
551
  /*
552
   * If there are any remaining CIs, then this packet is bad.
553
   */
554
  if (len != 0) {
555
    goto bad;
556
  }
557
  return (1);
558
 
559
bad:
560
  IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n"));
561
  return (0);
562
}
563
 
564
/*
565
 * ipcp_nakci - Peer has sent a NAK for some of our CIs.
566
 * This should not modify any state if the Nak is bad
567
 * or if IPCP is in the LS_OPENED state.
568
 *
569
 * Returns:
570
 *  0 - Nak was bad.
571
 *  1 - Nak was good.
572
 */
573
static int
574
ipcp_nakci(fsm *f, u_char *p, int len)
575
{
576
  ipcp_options *go = &ipcp_gotoptions[f->unit];
577
  u_char cimaxslotindex, cicflag;
578
  u_char citype, cilen, *next;
579
  u_short cishort;
580
  u32_t ciaddr1, ciaddr2, l, cidnsaddr;
581
  ipcp_options no;    /* options we've seen Naks for */
582
  ipcp_options try;    /* options to request next time */
583
 
584
  BZERO(&no, sizeof(no));
585
  try = *go;
586
 
587
  /*
588
   * Any Nak'd CIs must be in exactly the same order that we sent.
589
   * Check packet length and CI length at each step.
590
   * If we find any deviations, then this packet is bad.
591
   */
592
#define NAKCIADDR(opt, neg, old, code) \
593
  if (go->neg && \
594
      len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
595
      p[1] == cilen && \
596
      p[0] == opt) { \
597
    len -= cilen; \
598
    INCPTR(2, p); \
599
    GETLONG(l, p); \
600
    ciaddr1 = htonl(l); \
601
    if (old) { \
602
      GETLONG(l, p); \
603
      ciaddr2 = htonl(l); \
604
      no.old_addrs = 1; \
605
    } else { \
606
      ciaddr2 = 0; \
607
    } \
608
    no.neg = 1; \
609
    code \
610
  }
611
 
612
#define NAKCIVJ(opt, neg, code) \
613
  if (go->neg && \
614
      ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
615
      len >= cilen && \
616
      p[0] == opt) { \
617
    len -= cilen; \
618
    INCPTR(2, p); \
619
    GETSHORT(cishort, p); \
620
    no.neg = 1; \
621
    code \
622
  }
623
 
624
#define NAKCIDNS(opt, neg, code) \
625
  if (go->neg && \
626
      ((cilen = p[1]) == CILEN_ADDR) && \
627
      len >= cilen && \
628
      p[0] == opt) { \
629
    len -= cilen; \
630
    INCPTR(2, p); \
631
    GETLONG(l, p); \
632
    cidnsaddr = htonl(l); \
633
    no.neg = 1; \
634
    code \
635
  }
636
 
637
  /*
638
   * Accept the peer's idea of {our,his} address, if different
639
   * from our idea, only if the accept_{local,remote} flag is set.
640
   */
641
  NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
642
    if (go->accept_local && ciaddr1) { /* Do we know our address? */
643
      try.ouraddr = ciaddr1;
644
      IPCPDEBUG((LOG_INFO, "local IP address %s\n",
645
           inet_ntoa(ciaddr1)));
646
    }
647
    if (go->accept_remote && ciaddr2) { /* Does he know his? */
648
      try.hisaddr = ciaddr2;
649
      IPCPDEBUG((LOG_INFO, "remote IP address %s\n",
650
           inet_ntoa(ciaddr2)));
651
    }
652
  );
653
 
654
  /*
655
   * Accept the peer's value of maxslotindex provided that it
656
   * is less than what we asked for.  Turn off slot-ID compression
657
   * if the peer wants.  Send old-style compress-type option if
658
   * the peer wants.
659
   */
660
  NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
661
    if (cilen == CILEN_VJ) {
662
      GETCHAR(cimaxslotindex, p);
663
      GETCHAR(cicflag, p);
664
      if (cishort == IPCP_VJ_COMP) {
665
        try.old_vj = 0;
666
        if (cimaxslotindex < go->maxslotindex) {
667
          try.maxslotindex = cimaxslotindex;
668
        }
669
        if (!cicflag) {
670
          try.cflag = 0;
671
        }
672
      } else {
673
        try.neg_vj = 0;
674
      }
675
    } else {
676
      if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
677
        try.old_vj = 1;
678
        try.vj_protocol = cishort;
679
      } else {
680
        try.neg_vj = 0;
681
      }
682
    }
683
  );
684
 
685
  NAKCIDNS(CI_MS_DNS1, req_dns1,
686
      try.dnsaddr[0] = cidnsaddr;
687
        IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr)));
688
      );
689
 
690
  NAKCIDNS(CI_MS_DNS2, req_dns2,
691
      try.dnsaddr[1] = cidnsaddr;
692
        IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
693
      );
694
 
695
  /*
696
  * There may be remaining CIs, if the peer is requesting negotiation
697
  * on an option that we didn't include in our request packet.
698
  * If they want to negotiate about IP addresses, we comply.
699
  * If they want us to ask for compression, we refuse.
700
  */
701
  while (len > CILEN_VOID) {
702
    GETCHAR(citype, p);
703
    GETCHAR(cilen, p);
704
    if( (len -= cilen) < 0 ) {
705
      goto bad;
706
    }
707
    next = p + cilen - 2;
708
 
709
    switch (citype) {
710
      case CI_COMPRESSTYPE:
711
        if (go->neg_vj || no.neg_vj ||
712
            (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
713
          goto bad;
714
        }
715
        no.neg_vj = 1;
716
        break;
717
      case CI_ADDRS:
718
        if ((go->neg_addr && go->old_addrs) || no.old_addrs
719
            || cilen != CILEN_ADDRS) {
720
          goto bad;
721
        }
722
        try.neg_addr = 1;
723
        try.old_addrs = 1;
724
        GETLONG(l, p);
725
        ciaddr1 = htonl(l);
726
        if (ciaddr1 && go->accept_local) {
727
          try.ouraddr = ciaddr1;
728
        }
729
        GETLONG(l, p);
730
        ciaddr2 = htonl(l);
731
        if (ciaddr2 && go->accept_remote) {
732
          try.hisaddr = ciaddr2;
733
        }
734
        no.old_addrs = 1;
735
        break;
736
      case CI_ADDR:
737
        if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) {
738
          goto bad;
739
        }
740
        try.old_addrs = 0;
741
        GETLONG(l, p);
742
        ciaddr1 = htonl(l);
743
        if (ciaddr1 && go->accept_local) {
744
          try.ouraddr = ciaddr1;
745
        }
746
        if (try.ouraddr != 0) {
747
          try.neg_addr = 1;
748
        }
749
        no.neg_addr = 1;
750
        break;
751
    }
752
    p = next;
753
  }
754
 
755
  /* If there is still anything left, this packet is bad. */
756
  if (len != 0) {
757
    goto bad;
758
  }
759
 
760
  /*
761
   * OK, the Nak is good.  Now we can update state.
762
   */
763
  if (f->state != LS_OPENED) {
764
    *go = try;
765
  }
766
 
767
  return 1;
768
 
769
bad:
770
  IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n"));
771
  return 0;
772
}
773
 
774
 
775
/*
776
 * ipcp_rejci - Reject some of our CIs.
777
 */
778
static int
779
ipcp_rejci(fsm *f, u_char *p, int len)
780
{
781
  ipcp_options *go = &ipcp_gotoptions[f->unit];
782
  u_char cimaxslotindex, ciflag, cilen;
783
  u_short cishort;
784
  u32_t cilong;
785
  ipcp_options try;    /* options to request next time */
786
 
787
  try = *go;
788
  /*
789
   * Any Rejected CIs must be in exactly the same order that we sent.
790
   * Check packet length and CI length at each step.
791
   * If we find any deviations, then this packet is bad.
792
   */
793
#define REJCIADDR(opt, neg, old, val1, val2) \
794
  if (go->neg && \
795
      len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
796
      p[1] == cilen && \
797
      p[0] == opt) { \
798
    u32_t l; \
799
    len -= cilen; \
800
    INCPTR(2, p); \
801
    GETLONG(l, p); \
802
    cilong = htonl(l); \
803
    /* Check rejected value. */ \
804
    if (cilong != val1) { \
805
      goto bad; \
806
    } \
807
    if (old) { \
808
      GETLONG(l, p); \
809
      cilong = htonl(l); \
810
      /* Check rejected value. */ \
811
      if (cilong != val2) { \
812
        goto bad; \
813
      } \
814
    } \
815
    try.neg = 0; \
816
  }
817
 
818
#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
819
  if (go->neg && \
820
      p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
821
      len >= p[1] && \
822
      p[0] == opt) { \
823
    len -= p[1]; \
824
    INCPTR(2, p); \
825
    GETSHORT(cishort, p); \
826
    /* Check rejected value. */  \
827
    if (cishort != val) { \
828
      goto bad; \
829
    } \
830
    if (!old) { \
831
      GETCHAR(cimaxslotindex, p); \
832
      if (cimaxslotindex != maxslot) { \
833
        goto bad; \
834
      } \
835
      GETCHAR(ciflag, p); \
836
      if (ciflag != cflag) { \
837
        goto bad; \
838
      } \
839
    } \
840
    try.neg = 0; \
841
  }
842
 
843
#define REJCIDNS(opt, neg, dnsaddr) \
844
  if (go->neg && \
845
      ((cilen = p[1]) == CILEN_ADDR) && \
846
      len >= cilen && \
847
      p[0] == opt) { \
848
    u32_t l; \
849
    len -= cilen; \
850
    INCPTR(2, p); \
851
    GETLONG(l, p); \
852
    cilong = htonl(l); \
853
    /* Check rejected value. */ \
854
    if (cilong != dnsaddr) { \
855
      goto bad; \
856
    } \
857
    try.neg = 0; \
858
  }
859
 
860
  REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
861
        go->old_addrs, go->ouraddr, go->hisaddr);
862
 
863
  REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
864
      go->maxslotindex, go->cflag);
865
 
866
  REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
867
 
868
  REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
869
 
870
  /*
871
   * If there are any remaining CIs, then this packet is bad.
872
   */
873
  if (len != 0) {
874
    goto bad;
875
  }
876
  /*
877
   * Now we can update state.
878
   */
879
  if (f->state != LS_OPENED) {
880
    *go = try;
881
  }
882
  return 1;
883
 
884
bad:
885
  IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n"));
886
  return 0;
887
}
888
 
889
 
890
/*
891
 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
892
 *
893
 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
894
 * appropriately.  If reject_if_disagree is non-zero, doesn't return
895
 * CONFNAK; returns CONFREJ if it can't return CONFACK.
896
 */
897
static int
898
ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree)
899
{
900
  ipcp_options *wo = &ipcp_wantoptions[f->unit];
901
  ipcp_options *ho = &ipcp_hisoptions[f->unit];
902
  ipcp_options *ao = &ipcp_allowoptions[f->unit];
903
#ifdef OLD_CI_ADDRS
904
  ipcp_options *go = &ipcp_gotoptions[f->unit];
905
#endif
906
  u_char *cip, *next;     /* Pointer to current and next CIs */
907
  u_short cilen, citype;  /* Parsed len, type */
908
  u_short cishort;        /* Parsed short value */
909
  u32_t tl, ciaddr1;      /* Parsed address values */
910
#ifdef OLD_CI_ADDRS
911
  u32_t ciaddr2;          /* Parsed address values */
912
#endif
913
  int rc = CONFACK;       /* Final packet return code */
914
  int orc;                /* Individual option return code */
915
  u_char *p;              /* Pointer to next char to parse */
916
  u_char *ucp = inp;      /* Pointer to current output char */
917
  int l = *len;           /* Length left */
918
  u_char maxslotindex, cflag;
919
  int d;
920
 
921
  cis_received[f->unit] = 1;
922
 
923
  /*
924
   * Reset all his options.
925
   */
926
  BZERO(ho, sizeof(*ho));
927
 
928
  /*
929
   * Process all his options.
930
   */
931
  next = inp;
932
  while (l) {
933
    orc = CONFACK;       /* Assume success */
934
    cip = p = next;      /* Remember begining of CI */
935
    if (l < 2 ||         /* Not enough data for CI header or */
936
        p[1] < 2 ||      /*  CI length too small or */
937
        p[1] > l) {      /*  CI length too big? */
938
      IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n"));
939
      orc = CONFREJ;     /* Reject bad CI */
940
      cilen = l;         /* Reject till end of packet */
941
      l = 0;             /* Don't loop again */
942
      goto endswitch;
943
    }
944
    GETCHAR(citype, p);  /* Parse CI type */
945
    GETCHAR(cilen, p);   /* Parse CI length */
946
    l -= cilen;          /* Adjust remaining length */
947
    next += cilen;       /* Step to next CI */
948
 
949
    switch (citype) {      /* Check CI type */
950
#ifdef OLD_CI_ADDRS /* Need to save space... */
951
      case CI_ADDRS:
952
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n"));
953
        if (!ao->neg_addr ||
954
            cilen != CILEN_ADDRS) {  /* Check CI length */
955
          orc = CONFREJ;    /* Reject CI */
956
          break;
957
        }
958
 
959
        /*
960
         * If he has no address, or if we both have his address but
961
         * disagree about it, then NAK it with our idea.
962
         * In particular, if we don't know his address, but he does,
963
         * then accept it.
964
         */
965
        GETLONG(tl, p);    /* Parse source address (his) */
966
        ciaddr1 = htonl(tl);
967
        IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1)));
968
        if (ciaddr1 != wo->hisaddr
969
            && (ciaddr1 == 0 || !wo->accept_remote)) {
970
          orc = CONFNAK;
971
          if (!reject_if_disagree) {
972
            DECPTR(sizeof(u32_t), p);
973
            tl = ntohl(wo->hisaddr);
974
            PUTLONG(tl, p);
975
          }
976
        } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
977
          /*
978
           * If neither we nor he knows his address, reject the option.
979
           */
980
          orc = CONFREJ;
981
          wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
982
          break;
983
        }
984
 
985
        /*
986
         * If he doesn't know our address, or if we both have our address
987
         * but disagree about it, then NAK it with our idea.
988
         */
989
        GETLONG(tl, p);    /* Parse desination address (ours) */
990
        ciaddr2 = htonl(tl);
991
        IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2)));
992
        if (ciaddr2 != wo->ouraddr) {
993
          if (ciaddr2 == 0 || !wo->accept_local) {
994
            orc = CONFNAK;
995
            if (!reject_if_disagree) {
996
              DECPTR(sizeof(u32_t), p);
997
              tl = ntohl(wo->ouraddr);
998
              PUTLONG(tl, p);
999
            }
1000
          } else {
1001
            go->ouraddr = ciaddr2;  /* accept peer's idea */
1002
          }
1003
        }
1004
 
1005
        ho->neg_addr = 1;
1006
        ho->old_addrs = 1;
1007
        ho->hisaddr = ciaddr1;
1008
        ho->ouraddr = ciaddr2;
1009
        break;
1010
#endif
1011
 
1012
      case CI_ADDR:
1013
        if (!ao->neg_addr) {
1014
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n"));
1015
          orc = CONFREJ;        /* Reject CI */
1016
          break;
1017
        } else if (cilen != CILEN_ADDR) {  /* Check CI length */
1018
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));
1019
          orc = CONFREJ;        /* Reject CI */
1020
          break;
1021
        }
1022
 
1023
        /*
1024
         * If he has no address, or if we both have his address but
1025
         * disagree about it, then NAK it with our idea.
1026
         * In particular, if we don't know his address, but he does,
1027
         * then accept it.
1028
         */
1029
        GETLONG(tl, p);  /* Parse source address (his) */
1030
        ciaddr1 = htonl(tl);
1031
        if (ciaddr1 != wo->hisaddr
1032
            && (ciaddr1 == 0 || !wo->accept_remote)) {
1033
          orc = CONFNAK;
1034
          if (!reject_if_disagree) {
1035
            DECPTR(sizeof(u32_t), p);
1036
            tl = ntohl(wo->hisaddr);
1037
            PUTLONG(tl, p);
1038
          }
1039
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
1040
        } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1041
          /*
1042
           * Don't ACK an address of 0.0.0.0 - reject it instead.
1043
           */
1044
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
1045
          orc = CONFREJ;
1046
          wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
1047
          break;
1048
        }
1049
 
1050
        ho->neg_addr = 1;
1051
        ho->hisaddr = ciaddr1;
1052
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
1053
        break;
1054
 
1055
      case CI_MS_DNS1:
1056
      case CI_MS_DNS2:
1057
        /* Microsoft primary or secondary DNS request */
1058
        d = citype == CI_MS_DNS2;
1059
 
1060
        /* If we do not have a DNS address then we cannot send it */
1061
        if (ao->dnsaddr[d] == 0 ||
1062
            cilen != CILEN_ADDR) {  /* Check CI length */
1063
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));
1064
          orc = CONFREJ;        /* Reject CI */
1065
          break;
1066
        }
1067
        GETLONG(tl, p);
1068
        if (htonl(tl) != ao->dnsaddr[d]) {
1069
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",
1070
                d+1, inet_ntoa(tl)));
1071
          DECPTR(sizeof(u32_t), p);
1072
          tl = ntohl(ao->dnsaddr[d]);
1073
          PUTLONG(tl, p);
1074
          orc = CONFNAK;
1075
        }
1076
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));
1077
        break;
1078
 
1079
      case CI_MS_WINS1:
1080
      case CI_MS_WINS2:
1081
        /* Microsoft primary or secondary WINS request */
1082
        d = citype == CI_MS_WINS2;
1083
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));
1084
 
1085
        /* If we do not have a DNS address then we cannot send it */
1086
        if (ao->winsaddr[d] == 0 ||
1087
          cilen != CILEN_ADDR) {  /* Check CI length */
1088
          orc = CONFREJ;      /* Reject CI */
1089
          break;
1090
        }
1091
        GETLONG(tl, p);
1092
        if (htonl(tl) != ao->winsaddr[d]) {
1093
          DECPTR(sizeof(u32_t), p);
1094
          tl = ntohl(ao->winsaddr[d]);
1095
          PUTLONG(tl, p);
1096
          orc = CONFNAK;
1097
        }
1098
        break;
1099
 
1100
      case CI_COMPRESSTYPE:
1101
        if (!ao->neg_vj) {
1102
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
1103
          orc = CONFREJ;
1104
          break;
1105
        } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
1106
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
1107
          orc = CONFREJ;
1108
          break;
1109
        }
1110
        GETSHORT(cishort, p);
1111
 
1112
        if (!(cishort == IPCP_VJ_COMP ||
1113
            (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
1114
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
1115
          orc = CONFREJ;
1116
          break;
1117
        }
1118
 
1119
        ho->neg_vj = 1;
1120
        ho->vj_protocol = cishort;
1121
        if (cilen == CILEN_VJ) {
1122
          GETCHAR(maxslotindex, p);
1123
          if (maxslotindex > ao->maxslotindex) {
1124
            IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
1125
            orc = CONFNAK;
1126
            if (!reject_if_disagree) {
1127
              DECPTR(1, p);
1128
              PUTCHAR(ao->maxslotindex, p);
1129
            }
1130
          }
1131
          GETCHAR(cflag, p);
1132
          if (cflag && !ao->cflag) {
1133
            IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));
1134
            orc = CONFNAK;
1135
            if (!reject_if_disagree) {
1136
              DECPTR(1, p);
1137
              PUTCHAR(wo->cflag, p);
1138
            }
1139
          }
1140
          ho->maxslotindex = maxslotindex;
1141
          ho->cflag = cflag;
1142
        } else {
1143
          ho->old_vj = 1;
1144
          ho->maxslotindex = MAX_SLOTS - 1;
1145
          ho->cflag = 1;
1146
        }
1147
        IPCPDEBUG((LOG_INFO,
1148
              "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
1149
              ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
1150
        break;
1151
 
1152
      default:
1153
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));
1154
        orc = CONFREJ;
1155
        break;
1156
    }
1157
 
1158
endswitch:
1159
    if (orc == CONFACK &&    /* Good CI */
1160
        rc != CONFACK) {     /*  but prior CI wasnt? */
1161
      continue;              /* Don't send this one */
1162
    }
1163
 
1164
    if (orc == CONFNAK) {    /* Nak this CI? */
1165
      if (reject_if_disagree) {  /* Getting fed up with sending NAKs? */
1166
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));
1167
        orc = CONFREJ;       /* Get tough if so */
1168
      } else {
1169
        if (rc == CONFREJ) { /* Rejecting prior CI? */
1170
          continue;          /* Don't send this one */
1171
        }
1172
        if (rc == CONFACK) { /* Ack'd all prior CIs? */
1173
          rc = CONFNAK;      /* Not anymore... */
1174
          ucp = inp;         /* Backup */
1175
        }
1176
      }
1177
    }
1178
 
1179
    if (orc == CONFREJ &&    /* Reject this CI */
1180
        rc != CONFREJ) {  /*  but no prior ones? */
1181
      rc = CONFREJ;
1182
      ucp = inp;        /* Backup */
1183
    }
1184
 
1185
    /* Need to move CI? */
1186
    if (ucp != cip) {
1187
      BCOPY(cip, ucp, cilen);  /* Move it */
1188
    }
1189
 
1190
    /* Update output pointer */
1191
    INCPTR(cilen, ucp);
1192
  }
1193
 
1194
  /*
1195
   * If we aren't rejecting this packet, and we want to negotiate
1196
   * their address, and they didn't send their address, then we
1197
   * send a NAK with a CI_ADDR option appended.  We assume the
1198
   * input buffer is long enough that we can append the extra
1199
   * option safely.
1200
   */
1201
  if (rc != CONFREJ && !ho->neg_addr &&
1202
      wo->req_addr && !reject_if_disagree) {
1203
    IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));
1204
    if (rc == CONFACK) {
1205
      rc = CONFNAK;
1206
      ucp = inp;        /* reset pointer */
1207
      wo->req_addr = 0;    /* don't ask again */
1208
    }
1209
    PUTCHAR(CI_ADDR, ucp);
1210
    PUTCHAR(CILEN_ADDR, ucp);
1211
    tl = ntohl(wo->hisaddr);
1212
    PUTLONG(tl, ucp);
1213
  }
1214
 
1215
  *len = (int)(ucp - inp);    /* Compute output length */
1216
  IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
1217
  return (rc);      /* Return final code */
1218
}
1219
 
1220
 
1221
#if 0
1222
/*
1223
 * ip_check_options - check that any IP-related options are OK,
1224
 * and assign appropriate defaults.
1225
 */
1226
static void
1227
ip_check_options(u_long localAddr)
1228
{
1229
  ipcp_options *wo = &ipcp_wantoptions[0];
1230
 
1231
  /*
1232
   * Load our default IP address but allow the remote host to give us
1233
   * a new address.
1234
   */
1235
  if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) {
1236
    wo->accept_local = 1;  /* don't insist on this default value */
1237
    wo->ouraddr = htonl(localAddr);
1238
  }
1239
}
1240
#endif
1241
 
1242
 
1243
/*
1244
 * ipcp_up - IPCP has come UP.
1245
 *
1246
 * Configure the IP network interface appropriately and bring it up.
1247
 */
1248
static void
1249
ipcp_up(fsm *f)
1250
{
1251
  u32_t mask;
1252
  ipcp_options *ho = &ipcp_hisoptions[f->unit];
1253
  ipcp_options *go = &ipcp_gotoptions[f->unit];
1254
  ipcp_options *wo = &ipcp_wantoptions[f->unit];
1255
 
1256
  np_up(f->unit, PPP_IP);
1257
  IPCPDEBUG((LOG_INFO, "ipcp: up\n"));
1258
 
1259
  /*
1260
   * We must have a non-zero IP address for both ends of the link.
1261
   */
1262
  if (!ho->neg_addr) {
1263
    ho->hisaddr = wo->hisaddr;
1264
  }
1265
 
1266
  if (ho->hisaddr == 0) {
1267
    IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
1268
    ipcp_close(f->unit, "Could not determine remote IP address");
1269
    return;
1270
  }
1271
  if (go->ouraddr == 0) {
1272
    IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
1273
    ipcp_close(f->unit, "Could not determine local IP address");
1274
    return;
1275
  }
1276
 
1277
  if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
1278
    /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/
1279
  }
1280
 
1281
  /*
1282
   * Check that the peer is allowed to use the IP address it wants.
1283
   */
1284
  if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1285
    IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
1286
        inet_ntoa(ho->hisaddr)));
1287
    ipcp_close(f->unit, "Unauthorized remote IP address");
1288
    return;
1289
  }
1290
 
1291
  /* set tcp compression */
1292
  sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1293
 
1294
  /*
1295
   * Set IP addresses and (if specified) netmask.
1296
   */
1297
  mask = GetMask(go->ouraddr);
1298
 
1299
  if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
1300
    IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));
1301
    ipcp_close(f->unit, "Interface configuration failed");
1302
    return;
1303
  }
1304
 
1305
  /* bring the interface up for IP */
1306
  if (!sifup(f->unit)) {
1307
    IPCPDEBUG((LOG_WARNING, "sifup failed\n"));
1308
    ipcp_close(f->unit, "Interface configuration failed");
1309
    return;
1310
  }
1311
 
1312
  sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1313
 
1314
  /* assign a default route through the interface if required */
1315
  if (ipcp_wantoptions[f->unit].default_route) {
1316
    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) {
1317
      default_route_set[f->unit] = 1;
1318
    }
1319
  }
1320
 
1321
  IPCPDEBUG((LOG_NOTICE, "local  IP address %s\n", inet_ntoa(go->ouraddr)));
1322
  IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));
1323
  if (go->dnsaddr[0]) {
1324
    IPCPDEBUG((LOG_NOTICE, "primary   DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
1325
  }
1326
  if (go->dnsaddr[1]) {
1327
    IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
1328
  }
1329
}
1330
 
1331
 
1332
/*
1333
 * ipcp_down - IPCP has gone DOWN.
1334
 *
1335
 * Take the IP network interface down, clear its addresses
1336
 * and delete routes through it.
1337
 */
1338
static void
1339
ipcp_down(fsm *f)
1340
{
1341
  IPCPDEBUG((LOG_INFO, "ipcp: down\n"));
1342
  np_down(f->unit, PPP_IP);
1343
  sifvjcomp(f->unit, 0, 0, 0);
1344
 
1345
  sifdown(f->unit);
1346
  ipcp_clear_addrs(f->unit);
1347
}
1348
 
1349
 
1350
/*
1351
 * ipcp_clear_addrs() - clear the interface addresses, routes, etc.
1352
 */
1353
static void
1354
ipcp_clear_addrs(int unit)
1355
{
1356
  u32_t ouraddr, hisaddr;
1357
 
1358
  ouraddr = ipcp_gotoptions[unit].ouraddr;
1359
  hisaddr = ipcp_hisoptions[unit].hisaddr;
1360
  if (default_route_set[unit]) {
1361
    cifdefaultroute(unit, ouraddr, hisaddr);
1362
    default_route_set[unit] = 0;
1363
  }
1364
  cifaddr(unit, ouraddr, hisaddr);
1365
}
1366
 
1367
 
1368
/*
1369
 * ipcp_finished - possibly shut down the lower layers.
1370
 */
1371
static void
1372
ipcp_finished(fsm *f)
1373
{
1374
  np_finished(f->unit, PPP_IP);
1375
}
1376
 
1377
#if 0
1378
static int
1379
ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
1380
{
1381
  LWIP_UNUSED_ARG(p);
1382
  LWIP_UNUSED_ARG(plen);
1383
  LWIP_UNUSED_ARG(printer);
1384
  LWIP_UNUSED_ARG(arg);
1385
  return 0;
1386
}
1387
 
1388
/*
1389
 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1390
 * We don't bring the link up for IP fragments or for TCP FIN packets
1391
 * with no data.
1392
 */
1393
#define IP_HDRLEN   20  /* bytes */
1394
#define IP_OFFMASK  0x1fff
1395
#define IPPROTO_TCP 6
1396
#define TCP_HDRLEN  20
1397
#define TH_FIN      0x01
1398
 
1399
/*
1400
 * We use these macros because the IP header may be at an odd address,
1401
 * and some compilers might use word loads to get th_off or ip_hl.
1402
 */
1403
 
1404
#define net_short(x)    (((x)[0] << 8) + (x)[1])
1405
#define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
1406
#define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
1407
#define get_ipproto(x)  (((unsigned char *)(x))[9])
1408
#define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
1409
#define get_tcpflags(x) (((unsigned char *)(x))[13])
1410
 
1411
static int
1412
ip_active_pkt(u_char *pkt, int len)
1413
{
1414
  u_char *tcp;
1415
  int hlen;
1416
 
1417
  len -= PPP_HDRLEN;
1418
  pkt += PPP_HDRLEN;
1419
  if (len < IP_HDRLEN) {
1420
    return 0;
1421
  }
1422
  if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
1423
    return 0;
1424
  }
1425
  if (get_ipproto(pkt) != IPPROTO_TCP) {
1426
    return 1;
1427
  }
1428
  hlen = get_iphl(pkt) * 4;
1429
  if (len < hlen + TCP_HDRLEN) {
1430
    return 0;
1431
  }
1432
  tcp = pkt + hlen;
1433
  if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) {
1434
    return 0;
1435
  }
1436
  return 1;
1437
}
1438
#endif
1439
 
1440
#endif /* PPP_SUPPORT */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.