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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [pppd/] [ipxcp.c] - Blame information for rev 373

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * ipxcp.c - PPP IPX Control Protocol.
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
#ifdef IPX_CHANGE
21
#ifndef lint
22
/* static char rcsid[] = "$Id: ipxcp.c,v 1.2 2001-09-27 12:01:57 chris Exp $"; */
23
#endif
24
 
25
/*
26
 * TODO:
27
 */
28
 
29
#include <stdio.h>
30
#include <string.h>
31
#include <syslog.h>
32
#include <sys/types.h>
33
#include <sys/socket.h>
34
#include <netinet/in.h>
35
 
36
#include "pppd.h"
37
#include "fsm.h"
38
#include "ipxcp.h"
39
#include "pathnames.h"
40
 
41
/* global vars */
42
ipxcp_options ipxcp_wantoptions[NUM_PPP];       /* Options that we want to request */
43
ipxcp_options ipxcp_gotoptions[NUM_PPP];        /* Options that peer ack'd */
44
ipxcp_options ipxcp_allowoptions[NUM_PPP];      /* Options we allow peer to request */
45
ipxcp_options ipxcp_hisoptions[NUM_PPP];        /* Options that we ack'd */
46
 
47
#define wo (&ipxcp_wantoptions[0])
48
#define ao (&ipxcp_allowoptions[0])
49
#define go (&ipxcp_gotoptions[0])
50
#define ho (&ipxcp_hisoptions[0])
51
 
52
/*
53
 * Callbacks for fsm code.  (CI = Configuration Information)
54
 */
55
static void ipxcp_resetci __P((fsm *)); /* Reset our CI */
56
static int  ipxcp_cilen __P((fsm *));           /* Return length of our CI */
57
static void ipxcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
58
static int  ipxcp_ackci __P((fsm *, u_char *, int));    /* Peer ack'd our CI */
59
static int  ipxcp_nakci __P((fsm *, u_char *, int));    /* Peer nak'd our CI */
60
static int  ipxcp_rejci __P((fsm *, u_char *, int));    /* Peer rej'd our CI */
61
static int  ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
62
static void ipxcp_up __P((fsm *));              /* We're UP */
63
static void ipxcp_down __P((fsm *));            /* We're DOWN */
64
static void ipxcp_script __P((fsm *, char *)); /* Run an up/down script */
65
 
66
fsm ipxcp_fsm[NUM_PPP];         /* IPXCP fsm structure */
67
 
68
static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
69
    ipxcp_resetci,              /* Reset our Configuration Information */
70
    ipxcp_cilen,                /* Length of our Configuration Information */
71
    ipxcp_addci,                /* Add our Configuration Information */
72
    ipxcp_ackci,                /* ACK our Configuration Information */
73
    ipxcp_nakci,                /* NAK our Configuration Information */
74
    ipxcp_rejci,                /* Reject our Configuration Information */
75
    ipxcp_reqci,                /* Request peer's Configuration Information */
76
    ipxcp_up,                   /* Called when fsm reaches OPENED state */
77
    ipxcp_down,                 /* Called when fsm leaves OPENED state */
78
    NULL,                       /* Called when we want the lower layer up */
79
    NULL,                       /* Called when we want the lower layer down */
80
    NULL,                       /* Called when Protocol-Reject received */
81
    NULL,                       /* Retransmission is necessary */
82
    NULL,                       /* Called to handle protocol-specific codes */
83
    "IPXCP"                     /* String name of protocol */
84
};
85
 
86
/*
87
 * Protocol entry points.
88
 */
89
 
90
static void ipxcp_init __P((int));
91
static void ipxcp_open __P((int));
92
static void ipxcp_close __P((int, char *));
93
static void ipxcp_lowerup __P((int));
94
static void ipxcp_lowerdown __P((int));
95
static void ipxcp_input __P((int, u_char *, int));
96
static void ipxcp_protrej __P((int));
97
static int  ipxcp_printpkt __P((u_char *, int,
98
                                void (*) __P((void *, char *, ...)), void *));
99
 
100
struct protent ipxcp_protent = {
101
    PPP_IPXCP,
102
    ipxcp_init,
103
    ipxcp_input,
104
    ipxcp_protrej,
105
    ipxcp_lowerup,
106
    ipxcp_lowerdown,
107
    ipxcp_open,
108
    ipxcp_close,
109
    ipxcp_printpkt,
110
    NULL,
111
    0,
112
    "IPXCP",
113
    NULL,
114
    NULL,
115
    NULL
116
};
117
 
118
/*
119
 * Lengths of configuration options.
120
 */
121
 
122
#define CILEN_VOID      2
123
#define CILEN_COMPLETE  2       /* length of complete option */
124
#define CILEN_NETN      6       /* network number length option */
125
#define CILEN_NODEN     8       /* node number length option */
126
#define CILEN_PROTOCOL  4       /* Minimum length of routing protocol */
127
#define CILEN_NAME      3       /* Minimum length of router name */
128
#define CILEN_COMPRESS  4       /* Minimum length of compression protocol */
129
 
130
#define CODENAME(x)     ((x) == CONFACK ? "ACK" : \
131
                         (x) == CONFNAK ? "NAK" : "REJ")
132
 
133
/* Used in printing the node number */
134
#define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
135
 
136
/* Used to generate the proper bit mask */
137
#define BIT(num)   (1 << (num))
138
 
139
/*
140
 * Convert from internal to external notation
141
 */
142
 
143
static short int
144
to_external(internal)
145
short int internal;
146
{
147
    short int  external;
148
 
149
    if (internal & IPX_NONE)
150
        external = IPX_NONE;
151
    else
152
        external = RIP_SAP;
153
 
154
    return external;
155
}
156
 
157
/*
158
 * Make a string representation of a network IP address.
159
 */
160
 
161
char *
162
ipx_ntoa(ipxaddr)
163
u_int32_t ipxaddr;
164
{
165
    static char b[64];
166
    sprintf(b, "%x", ipxaddr);
167
    return b;
168
}
169
 
170
 
171
/*
172
 * ipxcp_init - Initialize IPXCP.
173
 */
174
static void
175
ipxcp_init(unit)
176
    int unit;
177
{
178
    fsm *f = &ipxcp_fsm[unit];
179
 
180
    f->unit      = unit;
181
    f->protocol  = PPP_IPXCP;
182
    f->callbacks = &ipxcp_callbacks;
183
    fsm_init(&ipxcp_fsm[unit]);
184
 
185
    memset (wo->name,     0, sizeof (wo->name));
186
    memset (wo->our_node, 0, sizeof (wo->our_node));
187
    memset (wo->his_node, 0, sizeof (wo->his_node));
188
 
189
    wo->neg_nn         = 1;
190
    wo->neg_complete   = 1;
191
    wo->network        = 0;
192
 
193
    ao->neg_node       = 1;
194
    ao->neg_nn         = 1;
195
    ao->neg_name       = 1;
196
    ao->neg_complete   = 1;
197
    ao->neg_router     = 1;
198
 
199
    ao->accept_local   = 0;
200
    ao->accept_remote  = 0;
201
    ao->accept_network = 0;
202
 
203
    wo->tried_rip      = 0;
204
    wo->tried_nlsp     = 0;
205
}
206
 
207
/*
208
 * Copy the node number
209
 */
210
 
211
static void
212
copy_node (src, dst)
213
u_char *src, *dst;
214
{
215
    memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
216
}
217
 
218
/*
219
 * Compare node numbers
220
 */
221
 
222
static int
223
compare_node (src, dst)
224
u_char *src, *dst;
225
{
226
    return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
227
}
228
 
229
/*
230
 * Is the node number zero?
231
 */
232
 
233
static int
234
zero_node (node)
235
u_char *node;
236
{
237
    int indx;
238
    for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
239
        if (node [indx] != 0)
240
            return 0;
241
    return 1;
242
}
243
 
244
/*
245
 * Increment the node number
246
 */
247
 
248
static void
249
inc_node (node)
250
u_char *node;
251
{
252
    u_char   *outp;
253
    u_int32_t magic_num;
254
 
255
    outp      = node;
256
    magic_num = magic();
257
    *outp++   = '\0';
258
    *outp++   = '\0';
259
    PUTLONG (magic_num, outp);
260
}
261
 
262
/*
263
 * ipxcp_open - IPXCP is allowed to come up.
264
 */
265
static void
266
ipxcp_open(unit)
267
    int unit;
268
{
269
    fsm_open(&ipxcp_fsm[unit]);
270
}
271
 
272
/*
273
 * ipxcp_close - Take IPXCP down.
274
 */
275
static void
276
ipxcp_close(unit, reason)
277
    int unit;
278
    char *reason;
279
{
280
    fsm_close(&ipxcp_fsm[unit], reason);
281
}
282
 
283
 
284
/*
285
 * ipxcp_lowerup - The lower layer is up.
286
 */
287
static void
288
ipxcp_lowerup(unit)
289
    int unit;
290
{
291
    fsm_lowerup(&ipxcp_fsm[unit]);
292
}
293
 
294
 
295
/*
296
 * ipxcp_lowerdown - The lower layer is down.
297
 */
298
static void
299
ipxcp_lowerdown(unit)
300
    int unit;
301
{
302
    fsm_lowerdown(&ipxcp_fsm[unit]);
303
}
304
 
305
 
306
/*
307
 * ipxcp_input - Input IPXCP packet.
308
 */
309
static void
310
ipxcp_input(unit, p, len)
311
    int unit;
312
    u_char *p;
313
    int len;
314
{
315
    fsm_input(&ipxcp_fsm[unit], p, len);
316
}
317
 
318
 
319
/*
320
 * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
321
 *
322
 * Pretend the lower layer went down, so we shut up.
323
 */
324
static void
325
ipxcp_protrej(unit)
326
    int unit;
327
{
328
    fsm_lowerdown(&ipxcp_fsm[unit]);
329
}
330
 
331
 
332
/*
333
 * ipxcp_resetci - Reset our CI.
334
 */
335
static void
336
ipxcp_resetci(f)
337
    fsm *f;
338
{
339
    wo->req_node = wo->neg_node && ao->neg_node;
340
    wo->req_nn   = wo->neg_nn   && ao->neg_nn;
341
 
342
    if (wo->our_network == 0) {
343
        wo->neg_node       = 1;
344
        ao->accept_network = 1;
345
    }
346
/*
347
 * If our node number is zero then change it.
348
 */
349
    if (zero_node (wo->our_node)) {
350
        inc_node (wo->our_node);
351
        ao->accept_local = 1;
352
        wo->neg_node     = 1;
353
    }
354
/*
355
 * If his node number is zero then change it.
356
 */
357
    if (zero_node (wo->his_node)) {
358
        inc_node (wo->his_node);
359
        ao->accept_remote = 1;
360
    }
361
/*
362
 * If no routing agent was specified then we do RIP/SAP according to the
363
 * RFC documents. If you have specified something then OK. Otherwise, we
364
 * do RIP/SAP.
365
 */
366
    if (ao->router == 0) {
367
        ao->router |= BIT(RIP_SAP);
368
        wo->router |= BIT(RIP_SAP);
369
    }
370
 
371
    /* Always specify a routing protocol unless it was REJected. */
372
    wo->neg_router = 1;
373
/*
374
 * Start with these default values
375
 */
376
    *go = *wo;
377
}
378
 
379
/*
380
 * ipxcp_cilen - Return length of our CI.
381
 */
382
 
383
static int
384
ipxcp_cilen(f)
385
    fsm *f;
386
{
387
    int len;
388
 
389
    len  = go->neg_nn       ? CILEN_NETN     : 0;
390
    len += go->neg_node     ? CILEN_NODEN    : 0;
391
    len += go->neg_name     ? CILEN_NAME + strlen (go->name) - 1 : 0;
392
 
393
    /* RFC says that defaults should not be included. */
394
    if (go->neg_router && to_external(go->router) != RIP_SAP)
395
        len += CILEN_PROTOCOL;
396
 
397
    return (len);
398
}
399
 
400
 
401
/*
402
 * ipxcp_addci - Add our desired CIs to a packet.
403
 */
404
static void
405
ipxcp_addci(f, ucp, lenp)
406
    fsm *f;
407
    u_char *ucp;
408
    int *lenp;
409
{
410
/*
411
 * Add the options to the record.
412
 */
413
    if (go->neg_nn) {
414
        PUTCHAR (IPX_NETWORK_NUMBER, ucp);
415
        PUTCHAR (CILEN_NETN, ucp);
416
        PUTLONG (go->our_network, ucp);
417
    }
418
 
419
    if (go->neg_node) {
420
        int indx;
421
        PUTCHAR (IPX_NODE_NUMBER, ucp);
422
        PUTCHAR (CILEN_NODEN, ucp);
423
        for (indx = 0; indx < sizeof (go->our_node); ++indx)
424
            PUTCHAR (go->our_node[indx], ucp);
425
    }
426
 
427
    if (go->neg_name) {
428
        int cilen = strlen (go->name);
429
        int indx;
430
        PUTCHAR (IPX_ROUTER_NAME, ucp);
431
        PUTCHAR (CILEN_NAME + cilen - 1, ucp);
432
        for (indx = 0; indx < cilen; ++indx)
433
            PUTCHAR (go->name [indx], ucp);
434
    }
435
 
436
    if (go->neg_router) {
437
        short external = to_external (go->router);
438
        if (external != RIP_SAP) {
439
            PUTCHAR  (IPX_ROUTER_PROTOCOL, ucp);
440
            PUTCHAR  (CILEN_PROTOCOL,      ucp);
441
            PUTSHORT (external,            ucp);
442
        }
443
    }
444
}
445
 
446
/*
447
 * ipxcp_ackci - Ack our CIs.
448
 *
449
 * Returns:
450
 *      0 - Ack was bad.
451
 *      1 - Ack was good.
452
 */
453
static int
454
ipxcp_ackci(f, p, len)
455
    fsm *f;
456
    u_char *p;
457
    int len;
458
{
459
    u_short cilen, citype, cishort;
460
    u_char cichar;
461
    u_int32_t cilong;
462
 
463
#define ACKCIVOID(opt, neg) \
464
    if (neg) { \
465
        if ((len -= CILEN_VOID) < 0) \
466
            break; \
467
        GETCHAR(citype, p); \
468
        GETCHAR(cilen, p); \
469
        if (cilen != CILEN_VOID || \
470
            citype != opt) \
471
            break; \
472
    }
473
 
474
#define ACKCICOMPLETE(opt,neg)  ACKCIVOID(opt, neg)
475
 
476
#define ACKCICHARS(opt, neg, val, cnt) \
477
    if (neg) { \
478
        int indx, count = cnt; \
479
        len -= (count + 2); \
480
        if (len < 0) \
481
            break; \
482
        GETCHAR(citype, p); \
483
        GETCHAR(cilen, p); \
484
        if (cilen != (count + 2) || \
485
            citype != opt) \
486
            break; \
487
        for (indx = 0; indx < count; ++indx) {\
488
            GETCHAR(cichar, p); \
489
            if (cichar != ((u_char *) &val)[indx]) \
490
               break; \
491
        }\
492
        if (indx != count) \
493
            break; \
494
    }
495
 
496
#define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
497
#define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
498
 
499
#define ACKCINETWORK(opt, neg, val) \
500
    if (neg) { \
501
        if ((len -= CILEN_NETN) < 0) \
502
            break; \
503
        GETCHAR(citype, p); \
504
        GETCHAR(cilen, p); \
505
        if (cilen != CILEN_NETN || \
506
            citype != opt) \
507
            break; \
508
        GETLONG(cilong, p); \
509
        if (cilong != val) \
510
            break; \
511
    }
512
 
513
#define ACKCIPROTO(opt, neg, val) \
514
    if (neg) { \
515
        if (len < 2) \
516
            break; \
517
        GETCHAR(citype, p); \
518
        GETCHAR(cilen, p); \
519
        if (cilen != CILEN_PROTOCOL || citype != opt) \
520
            break; \
521
        len -= cilen; \
522
        if (len < 0) \
523
            break; \
524
        GETSHORT(cishort, p); \
525
        if (cishort != to_external (val) || cishort == RIP_SAP) \
526
            break; \
527
      }
528
/*
529
 * Process the ACK frame in the order in which the frame was assembled
530
 */
531
    do {
532
        ACKCINETWORK  (IPX_NETWORK_NUMBER,  go->neg_nn,     go->our_network);
533
        ACKCINODE     (IPX_NODE_NUMBER,     go->neg_node,   go->our_node);
534
        ACKCINAME     (IPX_ROUTER_NAME,     go->neg_name,   go->name);
535
        ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
536
        ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
537
        ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
538
/*
539
 * This is the end of the record.
540
 */
541
        if (len == 0)
542
            return (1);
543
    } while (0);
544
/*
545
 * The frame is invalid
546
 */
547
    IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
548
    return (0);
549
}
550
 
551
/*
552
 * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
553
 * This should not modify any state if the Nak is bad
554
 * or if IPXCP is in the OPENED state.
555
 *
556
 * Returns:
557
 *      0 - Nak was bad.
558
 *      1 - Nak was good.
559
 */
560
 
561
static int
562
ipxcp_nakci(f, p, len)
563
    fsm *f;
564
    u_char *p;
565
    int len;
566
{
567
    u_char citype, cilen, *next;
568
    u_short s;
569
    u_int32_t l;
570
    ipxcp_options no;           /* options we've seen Naks for */
571
    ipxcp_options try;          /* options to request next time */
572
 
573
    BZERO(&no, sizeof(no));
574
    try = *go;
575
 
576
    while (len > CILEN_VOID) {
577
        GETCHAR (citype, p);
578
        GETCHAR (cilen,  p);
579
        len -= cilen;
580
        if (len < 0)
581
            goto bad;
582
        next = &p [cilen - CILEN_VOID];
583
 
584
        switch (citype) {
585
        case IPX_NETWORK_NUMBER:
586
            if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
587
                goto bad;
588
            no.neg_nn = 1;
589
 
590
            GETLONG(l, p);
591
            IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
592
            if (l && ao->accept_network)
593
                try.our_network = l;
594
            break;
595
 
596
        case IPX_NODE_NUMBER:
597
            if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
598
                goto bad;
599
            no.neg_node = 1;
600
 
601
            IPXCPDEBUG((LOG_INFO,
602
                        "local node number %02X%02X%02X%02X%02X%02X",
603
                        NODE(p)));
604
 
605
            if (!zero_node (p) && ao->accept_local &&
606
                ! compare_node (p, ho->his_node))
607
                copy_node (p, try.our_node);
608
            break;
609
 
610
            /* This has never been sent. Ignore the NAK frame */
611
        case IPX_COMPRESSION_PROTOCOL:
612
            goto bad;
613
 
614
        case IPX_ROUTER_PROTOCOL:
615
            if (!go->neg_router || (cilen < CILEN_PROTOCOL))
616
                goto bad;
617
 
618
            GETSHORT (s, p);
619
            if (s > 15)         /* This is just bad, but ignore for now. */
620
                break;
621
 
622
            s = BIT(s);
623
            if (no.router & s)  /* duplicate NAKs are always bad */
624
                goto bad;
625
 
626
            if (no.router == 0) /* Reset on first NAK only */
627
                try.router = 0;
628
 
629
            no.router      |= s;
630
            try.router     |= s;
631
            try.neg_router  = 1;
632
 
633
            IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
634
            break;
635
 
636
            /* These, according to the RFC, must never be NAKed. */
637
        case IPX_ROUTER_NAME:
638
        case IPX_COMPLETE:
639
            goto bad;
640
 
641
            /* These are for options which we have not seen. */
642
        default:
643
            break;
644
        }
645
        p = next;
646
    }
647
 
648
    /* If there is still anything left, this packet is bad. */
649
    if (len != 0)
650
        goto bad;
651
 
652
    /*
653
     * Do not permit the peer to force a router protocol which we do not
654
     * support. However, default to the condition that will accept "NONE".
655
     */
656
    try.router &= (ao->router | BIT(IPX_NONE));
657
    if (try.router == 0 && ao->router != 0)
658
        try.router = BIT(IPX_NONE);
659
 
660
    if (try.router != 0)
661
        try.neg_router = 1;
662
 
663
    /*
664
     * OK, the Nak is good.  Now we can update state.
665
     */
666
    if (f->state != OPENED)
667
        *go = try;
668
 
669
    return 1;
670
 
671
bad:
672
    IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
673
    return 0;
674
}
675
 
676
/*
677
 * ipxcp_rejci - Reject some of our CIs.
678
 */
679
static int
680
ipxcp_rejci(f, p, len)
681
    fsm *f;
682
    u_char *p;
683
    int len;
684
{
685
    u_short cilen, citype, cishort;
686
    u_char cichar;
687
    u_int32_t cilong;
688
    ipxcp_options try;          /* options to request next time */
689
 
690
#define REJCINETWORK(opt, neg, val) \
691
    if (neg && p[0] == opt) { \
692
        if ((len -= CILEN_NETN) < 0) \
693
            break; \
694
        GETCHAR(citype, p); \
695
        GETCHAR(cilen, p); \
696
        if (cilen != CILEN_NETN || \
697
            citype != opt) \
698
            break; \
699
        GETLONG(cilong, p); \
700
        if (cilong != val) \
701
            break; \
702
        IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
703
        neg = 0; \
704
    }
705
 
706
#define REJCICHARS(opt, neg, val, cnt) \
707
    if (neg && p[0] == opt) { \
708
        int indx, count = cnt; \
709
        len -= (count + 2); \
710
        if (len < 0) \
711
            break; \
712
        GETCHAR(citype, p); \
713
        GETCHAR(cilen, p); \
714
        if (cilen != (count + 2) || \
715
            citype != opt) \
716
            break; \
717
        for (indx = 0; indx < count; ++indx) {\
718
            GETCHAR(cichar, p); \
719
            if (cichar != ((u_char *) &val)[indx]) \
720
               break; \
721
        }\
722
        if (indx != count) \
723
            break; \
724
        IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
725
        neg = 0; \
726
    }
727
 
728
#define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
729
#define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
730
 
731
#define REJCIVOID(gpt, neg! \
732
    if (neg && p[0] == opt) { \
733
        if ((len -= CILEN_VOID) < 0) \
734
            break; \
735
        GETCHAR(citype, p); \
736
        GETCHAR(cilen, p); \
737
        if (cilen != CILEN_VOID || citype != opt) \
738
            break; \
739
        IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
740
        neg = 0; \
741
    }
742
 
743
/* a reject for RIP/SAP is invalid since we don't send it and you can't
744
   reject something which is not sent. (You can NAK, but you can't REJ.) */
745
#define REJCIPROTO(opt, neg, val, bit) \
746
    if (neg && p[0] == opt) { \
747
        if ((len -= CILEN_PROTOCOL) < 0) \
748
            break; \
749
        GETCHAR(citype, p); \
750
        GETCHAR(cilen, p); \
751
        if (cilen != CILEN_PROTOCOL) \
752
            break; \
753
        GETSHORT(cishort, p); \
754
        if (cishort != to_external (val) || cishort == RIP_SAP) \
755
            break; \
756
        IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \
757
        neg = 0; \
758
    }
759
/*
760
 * Any Rejected CIs must be in exactly the same order that we sent.
761
 * Check packet length and CI length at each step.
762
 * If we find any deviations, then this packet is bad.
763
 */
764
    try = *go;
765
 
766
    do {
767
        REJCINETWORK (IPX_NETWORK_NUMBER,  try.neg_nn,     try.our_network);
768
        REJCINODE    (IPX_NODE_NUMBER,     try.neg_node,   try.our_node);
769
        REJCINAME    (IPX_ROUTER_NAME,     try.neg_name,   try.name);
770
        REJCIPROTO   (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
771
/*
772
 * This is the end of the record.
773
 */
774
        if (len == 0) {
775
            if (f->state != OPENED)
776
                *go = try;
777
            return (1);
778
        }
779
    } while (0);
780
/*
781
 * The frame is invalid at this point.
782
 */
783
    IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
784
    return 0;
785
}
786
 
787
/*
788
 * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
789
 *
790
 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
791
 * appropriately.  If reject_if_disagree is non-zero, doesn't return
792
 * CONFNAK; returns CONFREJ if it can't return CONFACK.
793
 */
794
static int
795
ipxcp_reqci(f, inp, len, reject_if_disagree)
796
    fsm *f;
797
    u_char *inp;                /* Requested CIs */
798
    int *len;                   /* Length of requested CIs */
799
    int reject_if_disagree;
800
{
801
    u_char *cip, *next;         /* Pointer to current and next CIs */
802
    u_short cilen, citype;      /* Parsed len, type */
803
    u_short cishort;            /* Parsed short value */
804
    u_int32_t cinetwork;        /* Parsed address values */
805
    int rc = CONFACK;           /* Final packet return code */
806
    int orc;                    /* Individual option return code */
807
    u_char *p;                  /* Pointer to next char to parse */
808
    u_char *ucp = inp;          /* Pointer to current output char */
809
    int l = *len;               /* Length left */
810
 
811
    /*
812
     * Reset all his options.
813
     */
814
    BZERO(ho, sizeof(*ho));
815
 
816
    /*
817
     * Process all his options.
818
     */
819
    next = inp;
820
    while (l) {
821
        orc = CONFACK;                  /* Assume success */
822
        cip = p = next;                 /* Remember begining of CI */
823
        if (l < 2 ||                    /* Not enough data for CI header or */
824
            p[1] < 2 ||                 /*  CI length too small or */
825
            p[1] > l) {                 /*  CI length too big? */
826
            IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
827
            orc = CONFREJ;              /* Reject bad CI */
828
            cilen = l;                  /* Reject till end of packet */
829
            l = 0;                       /* Don't loop again */
830
            goto endswitch;
831
        }
832
        GETCHAR(citype, p);             /* Parse CI type */
833
        GETCHAR(cilen, p);              /* Parse CI length */
834
        l -= cilen;                     /* Adjust remaining length */
835
        next += cilen;                  /* Step to next CI */
836
 
837
        switch (citype) {               /* Check CI type */
838
/*
839
 * The network number must match. Choose the larger of the two.
840
 */
841
        case IPX_NETWORK_NUMBER:
842
            IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
843
 
844
            /* if we wont negotiate the network number or the length is wrong
845
               then reject the option */
846
            if ( !ao->neg_nn || cilen != CILEN_NETN ) {
847
                orc = CONFREJ;
848
                break;
849
            }
850
            GETLONG(cinetwork, p);
851
            IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
852
 
853
            /* If the network numbers match then acknowledge them. */
854
            if (cinetwork != 0) {
855
                ho->his_network = cinetwork;
856
                ho->neg_nn      = 1;
857
                if (wo->our_network == cinetwork)
858
                    break;
859
/*
860
 * If the network number is not given or we don't accept their change or
861
 * the network number is too small then NAK it.
862
 */
863
                if (! ao->accept_network || cinetwork < wo->our_network) {
864
                    DECPTR (sizeof (u_int32_t), p);
865
                    PUTLONG (wo->our_network, p);
866
                    orc = CONFNAK;
867
                }
868
                break;
869
            }
870
/*
871
 * The peer sent '0' for the network. Give it ours if we have one.
872
 */
873
            if (go->our_network != 0) {
874
                DECPTR (sizeof (u_int32_t), p);
875
                PUTLONG (wo->our_network, p);
876
                orc = CONFNAK;
877
/*
878
 * We don't have one. Reject the value.
879
 */
880
            } else
881
                orc = CONFREJ;
882
 
883
            break;
884
/*
885
 * The node number is required
886
 */
887
        case IPX_NODE_NUMBER:
888
            IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
889
 
890
            /* if we wont negotiate the node number or the length is wrong
891
               then reject the option */
892
            if ( cilen != CILEN_NODEN ) {
893
                orc = CONFREJ;
894
                break;
895
            }
896
 
897
            copy_node (p, ho->his_node);
898
            ho->neg_node = 1;
899
/*
900
 * If the remote does not have a number and we do then NAK it with the value
901
 * which we have for it. (We never have a default value of zero.)
902
 */
903
            if (zero_node (ho->his_node)) {
904
                orc = CONFNAK;
905
                copy_node (wo->his_node, p);
906
                INCPTR (sizeof (wo->his_node), p);
907
                break;
908
            }
909
/*
910
 * If you have given me the expected network node number then I'll accept
911
 * it now.
912
 */
913
            if (compare_node (wo->his_node, ho->his_node)) {
914
                orc = CONFACK;
915
                ho->neg_node = 1;
916
                INCPTR (sizeof (wo->his_node), p);
917
                break;
918
            }
919
/*
920
 * If his node number is the same as ours then ask him to try the next
921
 * value.
922
 */
923
            if (compare_node (ho->his_node, go->our_node)) {
924
                inc_node (ho->his_node);
925
                orc = CONFNAK;
926
                copy_node (ho->his_node, p);
927
                INCPTR (sizeof (wo->his_node), p);
928
                break;
929
            }
930
/*
931
 * If we don't accept a new value then NAK it.
932
 */
933
            if (! ao->accept_remote) {
934
                copy_node (wo->his_node, p);
935
                INCPTR (sizeof (wo->his_node), p);
936
                orc = CONFNAK;
937
                break;
938
            }
939
            orc = CONFACK;
940
            ho->neg_node = 1;
941
            INCPTR (sizeof (wo->his_node), p);
942
            break;
943
/*
944
 * Compression is not desired at this time. It is always rejected.
945
 */
946
        case IPX_COMPRESSION_PROTOCOL:
947
            IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
948
            orc = CONFREJ;
949
            break;
950
/*
951
 * The routing protocol is a bitmask of various types. Any combination
952
 * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no
953
 * routing protocol must be specified only once.
954
 */
955
        case IPX_ROUTER_PROTOCOL:
956
            if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
957
                orc = CONFREJ;
958
                break;
959
            }
960
 
961
            GETSHORT (cishort, p);
962
            IPXCPDEBUG((LOG_INFO,
963
                        "Remote router protocol number 0x%04x",
964
                        cishort));
965
 
966
            if (wo->neg_router == 0) {
967
                wo->neg_router = 1;
968
                wo->router     = BIT(IPX_NONE);
969
            }
970
 
971
            if ((cishort == IPX_NONE && ho->router != 0) ||
972
                (ho->router & BIT(IPX_NONE))) {
973
                orc = CONFREJ;
974
                break;
975
            }
976
 
977
            cishort = BIT(cishort);
978
            if (ho->router & cishort) {
979
                orc = CONFREJ;
980
                break;
981
            }
982
 
983
            ho->router    |= cishort;
984
            ho->neg_router = 1;
985
 
986
            /* Finally do not allow a router protocol which we do not
987
               support. */
988
 
989
            if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) {
990
                int protocol;
991
 
992
                if (cishort == BIT(NLSP) &&
993
                    (ao->router & BIT(RIP_SAP)) &&
994
                    !wo->tried_rip) {
995
                    protocol      = RIP_SAP;
996
                    wo->tried_rip = 1;
997
                } else
998
                    protocol = IPX_NONE;
999
 
1000
                DECPTR (sizeof (u_int16_t), p);
1001
                PUTSHORT (protocol, p);
1002
                orc = CONFNAK;
1003
            }
1004
            break;
1005
/*
1006
 * The router name is advisorary. Just accept it if it is not too large.
1007
 */
1008
        case IPX_ROUTER_NAME:
1009
            IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
1010
            if (cilen >= CILEN_NAME) {
1011
                int name_size = cilen - CILEN_NAME;
1012
                if (name_size > sizeof (ho->name))
1013
                    name_size = sizeof (ho->name) - 1;
1014
                memset (ho->name, 0, sizeof (ho->name));
1015
                memcpy (ho->name, p, name_size);
1016
                ho->name [name_size] = '\0';
1017
                ho->neg_name = 1;
1018
                orc = CONFACK;
1019
                break;
1020
            }
1021
            orc = CONFREJ;
1022
            break;
1023
/*
1024
 * This is advisorary.
1025
 */
1026
        case IPX_COMPLETE:
1027
            IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1028
            if (cilen != CILEN_COMPLETE)
1029
                orc = CONFREJ;
1030
            else {
1031
                ho->neg_complete = 1;
1032
                orc = CONFACK;
1033
            }
1034
            break;
1035
/*
1036
 * All other entries are not known at this time.
1037
 */
1038
        default:
1039
            IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1040
            orc = CONFREJ;
1041
            break;
1042
        }
1043
 
1044
endswitch:
1045
        IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
1046
 
1047
        if (orc == CONFACK &&           /* Good CI */
1048
            rc != CONFACK)              /*  but prior CI wasnt? */
1049
            continue;                   /* Don't send this one */
1050
 
1051
        if (orc == CONFNAK) {           /* Nak this CI? */
1052
            if (reject_if_disagree)     /* Getting fed up with sending NAKs? */
1053
                orc = CONFREJ;          /* Get tough if so */
1054
            if (rc == CONFREJ)          /* Rejecting prior CI? */
1055
                continue;               /* Don't send this one */
1056
            if (rc == CONFACK) {        /* Ack'd all prior CIs? */
1057
                rc  = CONFNAK;          /* Not anymore... */
1058
                ucp = inp;              /* Backup */
1059
            }
1060
        }
1061
 
1062
        if (orc == CONFREJ &&           /* Reject this CI */
1063
            rc != CONFREJ) {            /*  but no prior ones? */
1064
            rc = CONFREJ;
1065
            ucp = inp;                  /* Backup */
1066
        }
1067
 
1068
        /* Need to move CI? */
1069
        if (ucp != cip)
1070
            BCOPY(cip, ucp, cilen);     /* Move it */
1071
 
1072
        /* Update output pointer */
1073
        INCPTR(cilen, ucp);
1074
    }
1075
 
1076
    /*
1077
     * If we aren't rejecting this packet, and we want to negotiate
1078
     * their address, and they didn't send their address, then we
1079
     * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
1080
     * input buffer is long enough that we can append the extra
1081
     * option safely.
1082
     */
1083
 
1084
    if (rc != CONFREJ && !ho->neg_node &&
1085
        wo->req_nn && !reject_if_disagree) {
1086
        if (rc == CONFACK) {
1087
            rc = CONFNAK;
1088
            wo->req_nn = 0;              /* don't ask again */
1089
            ucp = inp;                  /* reset pointer */
1090
        }
1091
 
1092
        if (zero_node (wo->his_node))
1093
            inc_node (wo->his_node);
1094
 
1095
        PUTCHAR (IPX_NODE_NUMBER, ucp);
1096
        PUTCHAR (CILEN_NODEN, ucp);
1097
        copy_node (wo->his_node, ucp);
1098
        INCPTR (sizeof (wo->his_node), ucp);
1099
    }
1100
 
1101
    *len = ucp - inp;                   /* Compute output length */
1102
    IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc)));
1103
    return (rc);                        /* Return final code */
1104
}
1105
 
1106
/*
1107
 * ipxcp_up - IPXCP has come UP.
1108
 *
1109
 * Configure the IP network interface appropriately and bring it up.
1110
 */
1111
 
1112
static void
1113
ipxcp_up(f)
1114
    fsm *f;
1115
{
1116
    int unit = f->unit;
1117
 
1118
    IPXCPDEBUG((LOG_INFO, "ipxcp: up"));
1119
 
1120
    /* The default router protocol is RIP/SAP. */
1121
    if (ho->router == 0)
1122
        ho->router = BIT(RIP_SAP);
1123
 
1124
    if (go->router == 0)
1125
        go->router = BIT(RIP_SAP);
1126
 
1127
    /* Fetch the network number */
1128
    if (!ho->neg_nn)
1129
        ho->his_network = wo->his_network;
1130
 
1131
    if (!ho->neg_node)
1132
        copy_node (wo->his_node, ho->his_node);
1133
 
1134
    if (!wo->neg_node && !go->neg_node)
1135
        copy_node (wo->our_node, go->our_node);
1136
 
1137
    if (zero_node (go->our_node)) {
1138
        static char errmsg[] = "Could not determine local IPX node address";
1139
        IPXCPDEBUG((LOG_ERR, errmsg));
1140
        ipxcp_close(f->unit, errmsg);
1141
        return;
1142
    }
1143
 
1144
    go->network = go->our_network;
1145
    if (ho->his_network != 0 && ho->his_network > go->network)
1146
        go->network = ho->his_network;
1147
 
1148
    if (go->network == 0) {
1149
        static char errmsg[] = "Can not determine network number";
1150
        IPXCPDEBUG((LOG_ERR, errmsg));
1151
        ipxcp_close (unit, errmsg);
1152
        return;
1153
    }
1154
 
1155
    /* bring the interface up */
1156
    if (!sifup(unit)) {
1157
        IPXCPDEBUG((LOG_WARNING, "sifup failed"));
1158
        ipxcp_close(unit, "Interface configuration failed");
1159
        return;
1160
    }
1161
 
1162
    /* set the network number for IPX */
1163
    if (!sipxfaddr(unit, go->network, go->our_node)) {
1164
        IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
1165
        ipxcp_close(unit, "Interface configuration failed");
1166
        return;
1167
    }
1168
 
1169
    /*
1170
     * Execute the ipx-up script, like this:
1171
     *  /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
1172
     */
1173
 
1174
    ipxcp_script (f, _PATH_IPXUP);
1175
}
1176
 
1177
/*
1178
 * ipxcp_down - IPXCP has gone DOWN.
1179
 *
1180
 * Take the IP network interface down, clear its addresses
1181
 * and delete routes through it.
1182
 */
1183
 
1184
static void
1185
ipxcp_down(f)
1186
    fsm *f;
1187
{
1188
    IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
1189
 
1190
    cipxfaddr (f->unit);
1191
    sifdown(f->unit);
1192
    ipxcp_script (f, _PATH_IPXDOWN);
1193
}
1194
 
1195
 
1196
/*
1197
 * ipxcp_script - Execute a script with arguments
1198
 * interface-name tty-name speed local-IPX remote-IPX networks.
1199
 */
1200
static void
1201
ipxcp_script(f, script)
1202
    fsm *f;
1203
    char *script;
1204
{
1205
    char strspeed[32],   strlocal[32],     strremote[32];
1206
    char strnetwork[32], strpid[32];
1207
    char *argv[14],      strproto_lcl[32], strproto_rmt[32];
1208
 
1209
    sprintf (strpid,   "%d", getpid());
1210
    sprintf (strspeed, "%d", baud_rate);
1211
 
1212
    strproto_lcl[0] = '\0';
1213
    if (go->neg_router && ((go->router & BIT(IPX_NONE)) == 0)) {
1214
        if (go->router & BIT(RIP_SAP))
1215
            strcpy (strproto_lcl, "RIP ");
1216
        if (go->router & BIT(NLSP))
1217
            strcat (strproto_lcl, "NLSP ");
1218
    }
1219
 
1220
    if (strproto_lcl[0] == '\0')
1221
        strcpy (strproto_lcl, "NONE ");
1222
 
1223
    strproto_lcl[strlen (strproto_lcl)-1] = '\0';
1224
 
1225
    strproto_rmt[0] = '\0';
1226
    if (ho->neg_router && ((ho->router & BIT(IPX_NONE)) == 0)) {
1227
        if (ho->router & BIT(RIP_SAP))
1228
            strcpy (strproto_rmt, "RIP ");
1229
        if (ho->router & BIT(NLSP))
1230
            strcat (strproto_rmt, "NLSP ");
1231
    }
1232
 
1233
    if (strproto_rmt[0] == '\0')
1234
        strcpy (strproto_rmt, "NONE ");
1235
 
1236
    strproto_rmt[strlen (strproto_rmt)-1] = '\0';
1237
 
1238
    strcpy (strnetwork, ipx_ntoa (go->network));
1239
 
1240
    sprintf (strlocal,
1241
             "%02X%02X%02X%02X%02X%02X",
1242
             NODE(go->our_node));
1243
 
1244
    sprintf (strremote,
1245
             "%02X%02X%02X%02X%02X%02X",
1246
             NODE(ho->his_node));
1247
 
1248
    argv[0]  = script;
1249
    argv[1]  = ifname;
1250
    argv[2]  = devnam;
1251
    argv[3]  = strspeed;
1252
    argv[4]  = strnetwork;
1253
    argv[5]  = strlocal;
1254
    argv[6]  = strremote;
1255
    argv[7]  = strproto_lcl;
1256
    argv[8]  = strproto_rmt;
1257
    argv[9]  = go->name;
1258
    argv[10] = ho->name;
1259
    argv[11] = ipparam;
1260
    argv[12] = strpid;
1261
    argv[13] = NULL;
1262
    run_program(script, argv, 0);
1263
}
1264
 
1265
/*
1266
 * ipxcp_printpkt - print the contents of an IPXCP packet.
1267
 */
1268
static char *ipxcp_codenames[] = {
1269
    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1270
    "TermReq", "TermAck", "CodeRej"
1271
};
1272
 
1273
static int
1274
ipxcp_printpkt(p, plen, printer, arg)
1275
    u_char *p;
1276
    int plen;
1277
    void (*printer) __P((void *, char *, ...));
1278
    void *arg;
1279
{
1280
    int code, id, len, olen;
1281
    u_char *pstart, *optend;
1282
    u_short cishort;
1283
    u_int32_t cilong;
1284
 
1285
    if (plen < HEADERLEN)
1286
        return 0;
1287
    pstart = p;
1288
    GETCHAR(code, p);
1289
    GETCHAR(id, p);
1290
    GETSHORT(len, p);
1291
    if (len < HEADERLEN || len > plen)
1292
        return 0;
1293
 
1294
    if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
1295
        printer(arg, " %s", ipxcp_codenames[code-1]);
1296
    else
1297
        printer(arg, " code=0x%x", code);
1298
    printer(arg, " id=0x%x", id);
1299
    len -= HEADERLEN;
1300
    switch (code) {
1301
    case CONFREQ:
1302
    case CONFACK:
1303
    case CONFNAK:
1304
    case CONFREJ:
1305
        /* print option list */
1306
        while (len >= 2) {
1307
            GETCHAR(code, p);
1308
            GETCHAR(olen, p);
1309
            p -= 2;
1310
            if (olen < CILEN_VOID || olen > len) {
1311
                break;
1312
            }
1313
            printer(arg, " <");
1314
            len -= olen;
1315
            optend = p + olen;
1316
            switch (code) {
1317
            case IPX_NETWORK_NUMBER:
1318
                if (olen == CILEN_NETN) {
1319
                    p += 2;
1320
                    GETLONG(cilong, p);
1321
                    printer (arg, "network %s", ipx_ntoa (cilong));
1322
                }
1323
                break;
1324
            case IPX_NODE_NUMBER:
1325
                if (olen == CILEN_NODEN) {
1326
                    p += 2;
1327
                    printer (arg, "node ");
1328
                    while (p < optend) {
1329
                        GETCHAR(code, p);
1330
                        printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code);
1331
                    }
1332
                }
1333
                break;
1334
            case IPX_COMPRESSION_PROTOCOL:
1335
                if (olen == CILEN_COMPRESS) {
1336
                    p += 2;
1337
                    GETSHORT (cishort, p);
1338
                    printer (arg, "compression %d", (int) cishort);
1339
                }
1340
                break;
1341
            case IPX_ROUTER_PROTOCOL:
1342
                if (olen == CILEN_PROTOCOL) {
1343
                    p += 2;
1344
                    GETSHORT (cishort, p);
1345
                    printer (arg, "router proto %d", (int) cishort);
1346
                }
1347
                break;
1348
            case IPX_ROUTER_NAME:
1349
                if (olen >= CILEN_NAME) {
1350
                    p += 2;
1351
                    printer (arg, "router name \"");
1352
                    while (p < optend) {
1353
                        GETCHAR(code, p);
1354
                        if (code >= 0x20 && code <= 0x7E)
1355
                            printer (arg, "%c", (int) (unsigned int) (unsigned char) code);
1356
                        else
1357
                            printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code);
1358
                    }
1359
                    printer (arg, "\"");
1360
                }
1361
                break;
1362
            case IPX_COMPLETE:
1363
                if (olen == CILEN_COMPLETE) {
1364
                    p += 2;
1365
                    printer (arg, "complete");
1366
                }
1367
                break;
1368
            default:
1369
                break;
1370
            }
1371
 
1372
            while (p < optend) {
1373
                GETCHAR(code, p);
1374
                printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
1375
            }
1376
            printer(arg, ">");
1377
        }
1378
        break;
1379
 
1380
    case TERMACK:
1381
    case TERMREQ:
1382
        if (len > 0 && *p >= ' ' && *p < 0x7f) {
1383
            printer(arg, " ");
1384
            print_string(p, len, printer, arg);
1385
            p += len;
1386
            len = 0;
1387
        }
1388
        break;
1389
    }
1390
 
1391
    /* print the rest of the bytes in the packet */
1392
    for (; len > 0; --len) {
1393
        GETCHAR(code, p);
1394
        printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
1395
    }
1396
 
1397
    return p - pstart;
1398
}
1399
#endif /* ifdef IPX_CHANGE */

powered by: WebSVN 2.1.0

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