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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [pppd/] [fsm.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 * fsm.c - {Link, IP} Control Protocol Finite State Machine.
3
 *
4
 * Copyright (c) 1989 Carnegie Mellon University.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms are permitted
8
 * provided that the above copyright notice and this paragraph are
9
 * duplicated in all such forms and that any documentation,
10
 * advertising materials, and other materials related to such
11
 * distribution and use acknowledge that the software was developed
12
 * by Carnegie Mellon University.  The name of the
13
 * University may not be used to endorse or promote products derived
14
 * from this software without specific prior written permission.
15
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18
 */
19
 
20
#define RCSID   "fsm.c,v 1.6 2002/07/25 13:54:40 joel Exp"
21
 
22
/*
23
 * TODO:
24
 * Randomize fsm id on link/init.
25
 * Deal with variable outgoing MTU.
26
 */
27
 
28
#include <stdio.h>
29
#include <string.h>
30
#include <sys/types.h>
31
 
32
#include "pppd.h"
33
#include "fsm.h"
34
 
35
static const char rcsid[] = RCSID;
36
 
37
static void fsm_timeout __P((void *));
38
static void fsm_rconfreq __P((fsm *, u_char, u_char *, int));
39
static void fsm_rconfack __P((fsm *, int, u_char *, int));
40
static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));
41
static void fsm_rtermreq __P((fsm *, int, u_char *, int));
42
static void fsm_rtermack __P((fsm *));
43
static void fsm_rcoderej __P((fsm *, u_char *, int));
44
static void fsm_sconfreq __P((fsm *, int));
45
 
46
#define PROTO_NAME(f)   ((f)->callbacks->proto_name)
47
 
48
int peer_mru[NUM_PPP];
49
 
50
 
51
/*
52
 * fsm_init - Initialize fsm.
53
 *
54
 * Initialize fsm state.
55
 */
56
void
57
fsm_init(f)
58
    fsm *f;
59
{
60
    f->state = INITIAL;
61
    f->flags = 0;
62
    f->id = 100;                /* XXX Start with random id? */
63
    f->timeouttime = DEFTIMEOUT;
64
    f->maxconfreqtransmits = DEFMAXCONFREQS;
65
    f->maxtermtransmits = DEFMAXTERMREQS;
66
    f->maxnakloops = DEFMAXNAKLOOPS;
67
    f->term_reason_len = 0;
68
}
69
 
70
 
71
/*
72
 * fsm_lowerup - The lower layer is up.
73
 */
74
void
75
fsm_lowerup(f)
76
    fsm *f;
77
{
78
    switch( f->state ){
79
    case INITIAL:
80
        f->state = CLOSED;
81
        break;
82
 
83
    case STARTING:
84
        if( f->flags & OPT_SILENT )
85
            f->state = STOPPED;
86
        else {
87
            /* Send an initial configure-request */
88
            fsm_sconfreq(f, 0);
89
            f->state = REQSENT;
90
        }
91
        break;
92
 
93
    default:
94
        FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state));
95
    }
96
}
97
 
98
 
99
/*
100
 * fsm_lowerdown - The lower layer is down.
101
 *
102
 * Cancel all timeouts and inform upper layers.
103
 */
104
void
105
fsm_lowerdown(f)
106
    fsm *f;
107
{
108
    switch( f->state ){
109
    case CLOSED:
110
        f->state = INITIAL;
111
        break;
112
 
113
    case STOPPED:
114
        f->state = STARTING;
115
        if( f->callbacks->starting )
116
            (*f->callbacks->starting)(f);
117
        break;
118
 
119
    case CLOSING:
120
        f->state = INITIAL;
121
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
122
        break;
123
 
124
    case STOPPING:
125
    case REQSENT:
126
    case ACKRCVD:
127
    case ACKSENT:
128
        f->state = STARTING;
129
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
130
        break;
131
 
132
    case OPENED:
133
        if( f->callbacks->down )
134
            (*f->callbacks->down)(f);
135
        f->state = STARTING;
136
        break;
137
 
138
    default:
139
        FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state));
140
    }
141
}
142
 
143
 
144
/*
145
 * fsm_open - Link is allowed to come up.
146
 */
147
void
148
fsm_open(f)
149
    fsm *f;
150
{
151
    switch( f->state ){
152
    case INITIAL:
153
        f->state = STARTING;
154
        if( f->callbacks->starting )
155
            (*f->callbacks->starting)(f);
156
        break;
157
 
158
    case CLOSED:
159
        if( f->flags & OPT_SILENT )
160
            f->state = STOPPED;
161
        else {
162
            /* Send an initial configure-request */
163
            fsm_sconfreq(f, 0);
164
            f->state = REQSENT;
165
        }
166
        break;
167
 
168
    case CLOSING:
169
        f->state = STOPPING;
170
        /* fall through */
171
    case STOPPED:
172
    case OPENED:
173
        if( f->flags & OPT_RESTART ){
174
            fsm_lowerdown(f);
175
            fsm_lowerup(f);
176
        }
177
        break;
178
    }
179
}
180
 
181
 
182
/*
183
 * fsm_close - Start closing connection.
184
 *
185
 * Cancel timeouts and either initiate close or possibly go directly to
186
 * the CLOSED state.
187
 */
188
void
189
fsm_close(f, reason)
190
    fsm *f;
191
    char *reason;
192
{
193
    f->term_reason = reason;
194
    f->term_reason_len = (reason == NULL? 0: strlen(reason));
195
    switch( f->state ){
196
    case STARTING:
197
        f->state = INITIAL;
198
        break;
199
    case STOPPED:
200
        f->state = CLOSED;
201
        break;
202
    case STOPPING:
203
        f->state = CLOSING;
204
        break;
205
 
206
    case REQSENT:
207
    case ACKRCVD:
208
    case ACKSENT:
209
    case OPENED:
210
        if( f->state != OPENED )
211
            UNTIMEOUT(fsm_timeout, f);  /* Cancel timeout */
212
        else if( f->callbacks->down )
213
            (*f->callbacks->down)(f);   /* Inform upper layers we're down */
214
 
215
        /* Init restart counter, send Terminate-Request */
216
        f->retransmits = f->maxtermtransmits;
217
        fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
218
                  (u_char *) f->term_reason, f->term_reason_len);
219
        TIMEOUT(fsm_timeout, f, f->timeouttime);
220
        --f->retransmits;
221
 
222
        f->state = CLOSING;
223
        break;
224
    }
225
}
226
 
227
 
228
/*
229
 * fsm_timeout - Timeout expired.
230
 */
231
static void
232
fsm_timeout(arg)
233
    void *arg;
234
{
235
    fsm *f = (fsm *) arg;
236
 
237
    switch (f->state) {
238
    case CLOSING:
239
    case STOPPING:
240
        if( f->retransmits <= 0 ){
241
            /*
242
             * We've waited for an ack long enough.  Peer probably heard us.
243
             */
244
            f->state = (f->state == CLOSING)? CLOSED: STOPPED;
245
            if( f->callbacks->finished )
246
                (*f->callbacks->finished)(f);
247
        } else {
248
            /* Send Terminate-Request */
249
            fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
250
                      (u_char *) f->term_reason, f->term_reason_len);
251
            TIMEOUT(fsm_timeout, f, f->timeouttime);
252
            --f->retransmits;
253
        }
254
        break;
255
 
256
    case REQSENT:
257
    case ACKRCVD:
258
    case ACKSENT:
259
        if (f->retransmits <= 0) {
260
            warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f));
261
            f->state = STOPPED;
262
            if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
263
                (*f->callbacks->finished)(f);
264
 
265
        } else {
266
            /* Retransmit the configure-request */
267
            if (f->callbacks->retransmit)
268
                (*f->callbacks->retransmit)(f);
269
            fsm_sconfreq(f, 1);         /* Re-send Configure-Request */
270
            if( f->state == ACKRCVD )
271
                f->state = REQSENT;
272
        }
273
        break;
274
 
275
    default:
276
        FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state));
277
    }
278
}
279
 
280
 
281
/*
282
 * fsm_input - Input packet.
283
 */
284
void
285
fsm_input(f, inpacket, l)
286
    fsm *f;
287
    u_char *inpacket;
288
    int l;
289
{
290
    u_char *inp;
291
    u_char code, id;
292
    int len;
293
 
294
    /*
295
     * Parse header (code, id and length).
296
     * If packet too short, drop it.
297
     */
298
    inp = inpacket;
299
    if (l < HEADERLEN) {
300
        FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));
301
        return;
302
    }
303
    GETCHAR(code, inp);
304
    GETCHAR(id, inp);
305
    GETSHORT(len, inp);
306
    if (len < HEADERLEN) {
307
        FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));
308
        return;
309
    }
310
    if (len > l) {
311
        FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));
312
        return;
313
    }
314
    len -= HEADERLEN;           /* subtract header length */
315
 
316
    if( f->state == INITIAL || f->state == STARTING ){
317
        FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",
318
                  f->protocol, f->state));
319
        return;
320
    }
321
 
322
    /*
323
     * Action depends on code.
324
     */
325
    switch (code) {
326
    case CONFREQ:
327
        fsm_rconfreq(f, id, inp, len);
328
        break;
329
 
330
    case CONFACK:
331
        fsm_rconfack(f, id, inp, len);
332
        break;
333
 
334
    case CONFNAK:
335
    case CONFREJ:
336
        fsm_rconfnakrej(f, code, id, inp, len);
337
        break;
338
 
339
    case TERMREQ:
340
        fsm_rtermreq(f, id, inp, len);
341
        break;
342
 
343
    case TERMACK:
344
        fsm_rtermack(f);
345
        break;
346
 
347
    case CODEREJ:
348
        fsm_rcoderej(f, inp, len);
349
        break;
350
 
351
    default:
352
        if( !f->callbacks->extcode
353
           || !(*f->callbacks->extcode)(f, code, id, inp, len) )
354
            fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
355
        break;
356
    }
357
}
358
 
359
 
360
/*
361
 * fsm_rconfreq - Receive Configure-Request.
362
 */
363
static void
364
fsm_rconfreq(f, id, inp, len)
365
    fsm *f;
366
    u_char id;
367
    u_char *inp;
368
    int len;
369
{
370
    int code, reject_if_disagree;
371
 
372
    switch( f->state ){
373
    case CLOSED:
374
        /* Go away, we're closed */
375
        fsm_sdata(f, TERMACK, id, NULL, 0);
376
        return;
377
    case CLOSING:
378
    case STOPPING:
379
        return;
380
 
381
    case OPENED:
382
        /* Go down and restart negotiation */
383
        if( f->callbacks->down )
384
            (*f->callbacks->down)(f);   /* Inform upper layers */
385
        fsm_sconfreq(f, 0);              /* Send initial Configure-Request */
386
        break;
387
 
388
    case STOPPED:
389
        /* Negotiation started by our peer */
390
        fsm_sconfreq(f, 0);              /* Send initial Configure-Request */
391
        f->state = REQSENT;
392
        break;
393
    }
394
 
395
    /*
396
     * Pass the requested configuration options
397
     * to protocol-specific code for checking.
398
     */
399
    if (f->callbacks->reqci){           /* Check CI */
400
        reject_if_disagree = (f->nakloops >= f->maxnakloops);
401
        code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
402
    } else if (len)
403
        code = CONFREJ;                 /* Reject all CI */
404
    else
405
        code = CONFACK;
406
 
407
    /* send the Ack, Nak or Rej to the peer */
408
    fsm_sdata(f, code, id, inp, len);
409
 
410
    if (code == CONFACK) {
411
        if (f->state == ACKRCVD) {
412
            UNTIMEOUT(fsm_timeout, f);  /* Cancel timeout */
413
            f->state = OPENED;
414
            if (f->callbacks->up)
415
                (*f->callbacks->up)(f); /* Inform upper layers */
416
        } else {
417
            f->state = ACKSENT;
418
            ppp_delay();
419
        }
420
        f->nakloops = 0;
421
 
422
    } else {
423
        /* we sent CONFACK or CONFREJ */
424
        if (f->state != ACKRCVD)
425
            f->state = REQSENT;
426
        if( code == CONFNAK )
427
            ++f->nakloops;
428
    }
429
}
430
 
431
 
432
/*
433
 * fsm_rconfack - Receive Configure-Ack.
434
 */
435
static void
436
fsm_rconfack(f, id, inp, len)
437
    fsm *f;
438
    int id;
439
    u_char *inp;
440
    int len;
441
{
442
    if (id != f->reqid || f->seen_ack)          /* Expected id? */
443
        return;                                 /* Nope, toss... */
444
    if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
445
          (len == 0)) ){
446
        /* Ack is bad - ignore it */
447
        error("Received bad configure-ack: %P", inp, len);
448
        return;
449
    }
450
    f->seen_ack = 1;
451
 
452
    switch (f->state) {
453
    case CLOSED:
454
    case STOPPED:
455
        fsm_sdata(f, TERMACK, id, NULL, 0);
456
        break;
457
 
458
    case REQSENT:
459
        f->state = ACKRCVD;
460
        f->retransmits = f->maxconfreqtransmits;
461
        break;
462
 
463
    case ACKRCVD:
464
        /* Huh? an extra valid Ack? oh well... */
465
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
466
        fsm_sconfreq(f, 0);
467
        f->state = REQSENT;
468
        break;
469
 
470
    case ACKSENT:
471
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
472
        f->state = OPENED;
473
        f->retransmits = f->maxconfreqtransmits;
474
        if (f->callbacks->up)
475
            (*f->callbacks->up)(f);     /* Inform upper layers */
476
        break;
477
 
478
    case OPENED:
479
        /* Go down and restart negotiation */
480
        if (f->callbacks->down)
481
            (*f->callbacks->down)(f);   /* Inform upper layers */
482
        fsm_sconfreq(f, 0);              /* Send initial Configure-Request */
483
        f->state = REQSENT;
484
        break;
485
    }
486
}
487
 
488
 
489
/*
490
 * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
491
 */
492
static void
493
fsm_rconfnakrej(f, code, id, inp, len)
494
    fsm *f;
495
    int code, id;
496
    u_char *inp;
497
    int len;
498
{
499
    int (*proc) __P((fsm *, u_char *, int));
500
    int ret;
501
 
502
    if (id != f->reqid || f->seen_ack)  /* Expected id? */
503
        return;                         /* Nope, toss... */
504
    proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
505
    if (!proc || !(ret = proc(f, inp, len))) {
506
        /* Nak/reject is bad - ignore it */
507
        error("Received bad configure-nak/rej: %P", inp, len);
508
        return;
509
    }
510
    f->seen_ack = 1;
511
 
512
    switch (f->state) {
513
    case CLOSED:
514
    case STOPPED:
515
        fsm_sdata(f, TERMACK, id, NULL, 0);
516
        break;
517
 
518
    case REQSENT:
519
    case ACKSENT:
520
        /* They didn't agree to what we wanted - try another request */
521
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
522
        if (ret < 0)
523
            f->state = STOPPED;         /* kludge for stopping CCP */
524
        else
525
            fsm_sconfreq(f, 0);          /* Send Configure-Request */
526
        break;
527
 
528
    case ACKRCVD:
529
        /* Got a Nak/reject when we had already had an Ack?? oh well... */
530
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
531
        fsm_sconfreq(f, 0);
532
        f->state = REQSENT;
533
        break;
534
 
535
    case OPENED:
536
        /* Go down and restart negotiation */
537
        if (f->callbacks->down)
538
            (*f->callbacks->down)(f);   /* Inform upper layers */
539
        fsm_sconfreq(f, 0);              /* Send initial Configure-Request */
540
        f->state = REQSENT;
541
        break;
542
    }
543
}
544
 
545
 
546
/*
547
 * fsm_rtermreq - Receive Terminate-Req.
548
 */
549
static void
550
fsm_rtermreq(f, id, p, len)
551
    fsm *f;
552
    int id;
553
    u_char *p;
554
    int len;
555
{
556
    switch (f->state) {
557
    case ACKRCVD:
558
    case ACKSENT:
559
        f->state = REQSENT;             /* Start over but keep trying */
560
        break;
561
 
562
    case OPENED:
563
        if (len > 0) {
564
            info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p);
565
        } else
566
            info("%s terminated by peer", PROTO_NAME(f));
567
        if (f->callbacks->down)
568
            (*f->callbacks->down)(f);   /* Inform upper layers */
569
        f->retransmits = 0;
570
        f->state = STOPPING;
571
        TIMEOUT(fsm_timeout, f, f->timeouttime);
572
        break;
573
    }
574
 
575
    fsm_sdata(f, TERMACK, id, NULL, 0);
576
}
577
 
578
 
579
/*
580
 * fsm_rtermack - Receive Terminate-Ack.
581
 */
582
static void
583
fsm_rtermack(f)
584
    fsm *f;
585
{
586
    switch (f->state) {
587
    case CLOSING:
588
        UNTIMEOUT(fsm_timeout, f);
589
        f->state = CLOSED;
590
        if( f->callbacks->finished )
591
            (*f->callbacks->finished)(f);
592
        break;
593
    case STOPPING:
594
        UNTIMEOUT(fsm_timeout, f);
595
        f->state = STOPPED;
596
        if( f->callbacks->finished )
597
            (*f->callbacks->finished)(f);
598
        break;
599
 
600
    case ACKRCVD:
601
        f->state = REQSENT;
602
        break;
603
 
604
    case OPENED:
605
        if (f->callbacks->down)
606
            (*f->callbacks->down)(f);   /* Inform upper layers */
607
        fsm_sconfreq(f, 0);
608
        break;
609
    }
610
}
611
 
612
 
613
/*
614
 * fsm_rcoderej - Receive an Code-Reject.
615
 */
616
static void
617
fsm_rcoderej(f, inp, len)
618
    fsm *f;
619
    u_char *inp;
620
    int len;
621
{
622
    u_char code, id;
623
 
624
    if (len < HEADERLEN) {
625
        FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!"));
626
        return;
627
    }
628
    GETCHAR(code, inp);
629
    GETCHAR(id, inp);
630
    warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id);
631
 
632
    if( f->state == ACKRCVD )
633
        f->state = REQSENT;
634
}
635
 
636
 
637
/*
638
 * fsm_protreject - Peer doesn't speak this protocol.
639
 *
640
 * Treat this as a catastrophic error (RXJ-).
641
 */
642
void
643
fsm_protreject(f)
644
    fsm *f;
645
{
646
    switch( f->state ){
647
    case CLOSING:
648
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
649
        /* fall through */
650
    case CLOSED:
651
        f->state = CLOSED;
652
        if( f->callbacks->finished )
653
            (*f->callbacks->finished)(f);
654
        break;
655
 
656
    case STOPPING:
657
    case REQSENT:
658
    case ACKRCVD:
659
    case ACKSENT:
660
        UNTIMEOUT(fsm_timeout, f);      /* Cancel timeout */
661
        /* fall through */
662
    case STOPPED:
663
        f->state = STOPPED;
664
        if( f->callbacks->finished )
665
            (*f->callbacks->finished)(f);
666
        break;
667
 
668
    case OPENED:
669
        if( f->callbacks->down )
670
            (*f->callbacks->down)(f);
671
 
672
        /* Init restart counter, send Terminate-Request */
673
        f->retransmits = f->maxtermtransmits;
674
        fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
675
                  (u_char *) f->term_reason, f->term_reason_len);
676
        TIMEOUT(fsm_timeout, f, f->timeouttime);
677
        --f->retransmits;
678
 
679
        f->state = STOPPING;
680
        break;
681
 
682
    default:
683
        FSMDEBUG(("%s: Protocol-reject event in state %d!",
684
                  PROTO_NAME(f), f->state));
685
    }
686
}
687
 
688
 
689
/*
690
 * fsm_sconfreq - Send a Configure-Request.
691
 */
692
static void
693
fsm_sconfreq(f, retransmit)
694
    fsm *f;
695
    int retransmit;
696
{
697
    u_char *outp;
698
    int cilen;
699
 
700
    if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
701
        /* Not currently negotiating - reset options */
702
        if( f->callbacks->resetci )
703
            (*f->callbacks->resetci)(f);
704
        f->nakloops = 0;
705
    }
706
 
707
    if( !retransmit ){
708
        /* New request - reset retransmission counter, use new ID */
709
        f->retransmits = f->maxconfreqtransmits;
710
        f->reqid = ++f->id;
711
    }
712
 
713
    f->seen_ack = 0;
714
 
715
    /*
716
     * Make up the request packet
717
     */
718
    outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
719
    if( f->callbacks->cilen && f->callbacks->addci ){
720
        cilen = (*f->callbacks->cilen)(f);
721
        if( cilen > peer_mru[f->unit] - HEADERLEN )
722
            cilen = peer_mru[f->unit] - HEADERLEN;
723
        if (f->callbacks->addci)
724
            (*f->callbacks->addci)(f, outp, &cilen);
725
    } else
726
        cilen = 0;
727
 
728
    /* send the request to our peer */
729
    fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
730
 
731
    /* start the retransmit timer */
732
    --f->retransmits;
733
    TIMEOUT(fsm_timeout, f, f->timeouttime);
734
}
735
 
736
 
737
/*
738
 * fsm_sdata - Send some data.
739
 *
740
 * Used for all packets sent to our peer by this module.
741
 */
742
void
743
fsm_sdata(f, code, id, data, datalen)
744
    fsm *f;
745
    u_char code, id;
746
    u_char *data;
747
    int datalen;
748
{
749
    u_char *outp;
750
    int outlen;
751
 
752
    /* Adjust length to be smaller than MTU */
753
    outp = outpacket_buf;
754
    if (datalen > peer_mru[f->unit] - HEADERLEN)
755
        datalen = peer_mru[f->unit] - HEADERLEN;
756
    if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
757
        BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
758
    outlen = datalen + HEADERLEN;
759
    MAKEHEADER(outp, f->protocol);
760
    PUTCHAR(code, outp);
761
    PUTCHAR(id, outp);
762
    PUTSHORT(outlen, outp);
763
    output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
764
}

powered by: WebSVN 2.1.0

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