~ubuntu-branches/debian/sid/ppp/sid

« back to all changes in this revision

Viewing changes to solaris/ppp.c

  • Committer: Bazaar Package Importer
  • Author(s): Eddy Petrișor
  • Date: 2007-03-17 22:31:45 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070317223145-felzh5yrmh8fwi8t
Tags: 2.4.4rel-8
* urgency high since fixes an RC bug
* make sure the /etc/resolv.conf file is world readable (Closes: #415077)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * ppp.c - STREAMS multiplexing pseudo-device driver for PPP.
3
 
 *
4
 
 * Copyright (c) 1994 The Australian National University.
5
 
 * All rights reserved.
6
 
 *
7
 
 * Permission to use, copy, modify, and distribute this software and its
8
 
 * documentation is hereby granted, provided that the above copyright
9
 
 * notice appears in all copies.  This software is provided without any
10
 
 * warranty, express or implied. The Australian National University
11
 
 * makes no representations about the suitability of this software for
12
 
 * any purpose.
13
 
 *
14
 
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15
 
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16
 
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17
 
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
18
 
 * OF SUCH DAMAGE.
19
 
 *
20
 
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21
 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
 
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23
 
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24
 
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25
 
 * OR MODIFICATIONS.
26
 
 *
27
 
 * $Id: ppp.c,v 1.1 2000/04/18 23:51:28 masputra Exp $
28
 
 */
29
 
 
30
 
/*
31
 
 * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
32
 
 */
33
 
 
34
 
#include <sys/types.h>
35
 
#include <sys/param.h>
36
 
#include <sys/stat.h>
37
 
#include <sys/stream.h>
38
 
#include <sys/stropts.h>
39
 
#include <sys/errno.h>
40
 
#ifdef __osf__
41
 
#include <sys/ioctl.h>
42
 
#include <sys/cmn_err.h>
43
 
#define queclass(mp)    ((mp)->b_band & QPCTL)
44
 
#else
45
 
#include <sys/ioccom.h>
46
 
#endif
47
 
#include <sys/time.h>
48
 
#ifdef SVR4
49
 
#include <sys/cmn_err.h>
50
 
#include <sys/conf.h>
51
 
#include <sys/dlpi.h>
52
 
#include <sys/ddi.h>
53
 
#ifdef SOL2
54
 
#include <sys/ksynch.h>
55
 
#include <sys/kstat.h>
56
 
#include <sys/sunddi.h>
57
 
#include <sys/ethernet.h>
58
 
#else
59
 
#include <sys/socket.h>
60
 
#include <sys/sockio.h>
61
 
#include <net/if.h>
62
 
#include <netinet/in.h>
63
 
#endif /* SOL2 */
64
 
#else /* not SVR4 */
65
 
#include <sys/user.h>
66
 
#endif /* SVR4 */
67
 
#include <net/ppp_defs.h>
68
 
#include <net/pppio.h>
69
 
#include "ppp_mod.h"
70
 
 
71
 
/*
72
 
 * Modifications marked with #ifdef PRIOQ are for priority queueing of
73
 
 * interactive traffic, and are due to Marko Zec <zec@japa.tel.fer.hr>.
74
 
 */
75
 
#ifdef PRIOQ
76
 
#endif  /* PRIOQ */
77
 
 
78
 
#include <netinet/in.h> /* leave this outside of PRIOQ for htons */
79
 
 
80
 
#ifdef __STDC__
81
 
#define __P(x)  x
82
 
#else
83
 
#define __P(x)  ()
84
 
#endif
85
 
 
86
 
/*
87
 
 * The IP module may use this SAP value for IP packets.
88
 
 */
89
 
#ifndef ETHERTYPE_IP
90
 
#define ETHERTYPE_IP    0x800
91
 
#endif
92
 
 
93
 
#if !defined(ETHERTYPE_IPV6) 
94
 
#define ETHERTYPE_IPV6  0x86dd
95
 
#endif /* !defined(ETHERTYPE_IPV6) */
96
 
 
97
 
#if !defined(ETHERTYPE_ALLSAP) && defined(SOL2)
98
 
#define ETHERTYPE_ALLSAP   0
99
 
#endif /* !defined(ETHERTYPE_ALLSAP) && defined(SOL2) */
100
 
 
101
 
#if !defined(PPP_ALLSAP) && defined(SOL2)
102
 
#define PPP_ALLSAP  PPP_ALLSTATIONS
103
 
#endif /* !defined(PPP_ALLSAP) && defined(SOL2) */
104
 
 
105
 
extern time_t time;
106
 
 
107
 
#ifdef SOL2
108
 
/*
109
 
 * We use this reader-writer lock to ensure that the lower streams
110
 
 * stay connected to the upper streams while the lower-side put and
111
 
 * service procedures are running.  Essentially it is an existence
112
 
 * lock for the upper stream associated with each lower stream.
113
 
 */
114
 
krwlock_t ppp_lower_lock;
115
 
#define LOCK_LOWER_W    rw_enter(&ppp_lower_lock, RW_WRITER)
116
 
#define LOCK_LOWER_R    rw_enter(&ppp_lower_lock, RW_READER)
117
 
#define TRYLOCK_LOWER_R rw_tryenter(&ppp_lower_lock, RW_READER)
118
 
#define UNLOCK_LOWER    rw_exit(&ppp_lower_lock)
119
 
 
120
 
#define MT_ENTER(x)     mutex_enter(x)
121
 
#define MT_EXIT(x)      mutex_exit(x)
122
 
 
123
 
/*
124
 
 * Notes on multithreaded implementation for Solaris 2:
125
 
 *
126
 
 * We use an inner perimeter around each queue pair and an outer
127
 
 * perimeter around the whole driver.  The inner perimeter is
128
 
 * entered exclusively for all entry points (open, close, put,
129
 
 * service).  The outer perimeter is entered exclusively for open
130
 
 * and close and shared for put and service.  This is all done for
131
 
 * us by the streams framework.
132
 
 *
133
 
 * I used to think that the perimeters were entered for the lower
134
 
 * streams' put and service routines as well as for the upper streams'.
135
 
 * Because of problems experienced by people, and after reading the
136
 
 * documentation more closely, I now don't think that is true.  So we
137
 
 * now use ppp_lower_lock to give us an existence guarantee on the
138
 
 * upper stream controlling each lower stream.
139
 
 *
140
 
 * Shared entry to the outer perimeter protects the existence of all
141
 
 * the upper streams and their upperstr_t structures, and guarantees
142
 
 * that the following fields of any upperstr_t won't change:
143
 
 * nextmn, next, nextppa.  It guarantees that the lowerq field of an
144
 
 * upperstr_t won't go from non-zero to zero, that the global `ppas'
145
 
 * won't change and that the no lower stream will get unlinked.
146
 
 *
147
 
 * Shared (reader) access to ppa_lower_lock guarantees that no lower
148
 
 * stream will be unlinked and that the lowerq field of all upperstr_t
149
 
 * structures won't change.
150
 
 */
151
 
 
152
 
#else /* SOL2 */
153
 
#define LOCK_LOWER_W    0
154
 
#define LOCK_LOWER_R    0
155
 
#define TRYLOCK_LOWER_R 1
156
 
#define UNLOCK_LOWER    0
157
 
#define MT_ENTER(x)     0
158
 
#define MT_EXIT(x)      0
159
 
 
160
 
#endif /* SOL2 */
161
 
 
162
 
/*
163
 
 * Private information; one per upper stream.
164
 
 */
165
 
typedef struct upperstr {
166
 
    minor_t mn;                 /* minor device number */
167
 
    struct upperstr *nextmn;    /* next minor device */
168
 
    queue_t *q;                 /* read q associated with this upper stream */
169
 
    int flags;                  /* flag bits, see below */
170
 
    int state;                  /* current DLPI state */
171
 
    int sap;                    /* service access point */
172
 
    int req_sap;                /* which SAP the DLPI client requested */
173
 
    struct upperstr *ppa;       /* control stream for our ppa */
174
 
    struct upperstr *next;      /* next stream for this ppa */
175
 
    uint ioc_id;                /* last ioctl ID for this stream */
176
 
    enum NPmode npmode;         /* what to do with packets on this SAP */
177
 
    unsigned char rblocked;     /* flow control has blocked upper read strm */
178
 
        /* N.B. rblocked is only changed by control stream's put/srv procs */
179
 
    /*
180
 
     * There is exactly one control stream for each PPA.
181
 
     * The following fields are only used for control streams.
182
 
     */
183
 
    int ppa_id;
184
 
    queue_t *lowerq;            /* write queue attached below this PPA */
185
 
    struct upperstr *nextppa;   /* next control stream */
186
 
    int mru;
187
 
    int mtu;
188
 
    struct pppstat stats;       /* statistics */
189
 
    time_t last_sent;           /* time last NP packet sent */
190
 
    time_t last_recv;           /* time last NP packet rcvd */
191
 
#ifdef SOL2
192
 
    kmutex_t stats_lock;        /* lock for stats updates */
193
 
    kstat_t *kstats;            /* stats for netstat */
194
 
#endif /* SOL2 */
195
 
#ifdef LACHTCP
196
 
    int ifflags;
197
 
    char ifname[IFNAMSIZ];
198
 
    struct ifstats ifstats;
199
 
#endif /* LACHTCP */
200
 
} upperstr_t;
201
 
 
202
 
/* Values for flags */
203
 
#define US_PRIV         1       /* stream was opened by superuser */
204
 
#define US_CONTROL      2       /* stream is a control stream */
205
 
#define US_BLOCKED      4       /* flow ctrl has blocked lower write stream */
206
 
#define US_LASTMOD      8       /* no PPP modules below us */
207
 
#define US_DBGLOG       0x10    /* log various occurrences */
208
 
#define US_RBLOCKED     0x20    /* flow ctrl has blocked upper read stream */
209
 
 
210
 
#if defined(SOL2)
211
 
#if DL_CURRENT_VERSION >= 2
212
 
#define US_PROMISC      0x40    /* stream is promiscuous */
213
 
#endif /* DL_CURRENT_VERSION >= 2 */
214
 
#define US_RAWDATA      0x80    /* raw M_DATA, no DLPI header */
215
 
#endif /* defined(SOL2) */
216
 
 
217
 
#ifdef PRIOQ
218
 
static u_char max_band=0;
219
 
static u_char def_band=0;
220
 
 
221
 
#define IPPORT_DEFAULT          65535
222
 
 
223
 
/*
224
 
 * Port priority table
225
 
 * Highest priority ports are listed first, lowest are listed last.
226
 
 * ICMP & packets using unlisted ports will be treated as "default".
227
 
 * If IPPORT_DEFAULT is not listed here, "default" packets will be 
228
 
 * assigned lowest priority.
229
 
 * Each line should be terminated with "0".
230
 
 * Line containing only "0" marks the end of the list.
231
 
 */
232
 
 
233
 
static u_short prioq_table[]= {
234
 
    113, 53, 0,
235
 
    22, 23, 513, 517, 518, 0,
236
 
    514, 21, 79, 111, 0,
237
 
    25, 109, 110, 0,
238
 
    IPPORT_DEFAULT, 0,
239
 
    20, 70, 80, 8001, 8008, 8080, 0, /* 8001,8008,8080 - common proxy ports */
240
 
0 };
241
 
 
242
 
#endif  /* PRIOQ */
243
 
 
244
 
 
245
 
static upperstr_t *minor_devs = NULL;
246
 
static upperstr_t *ppas = NULL;
247
 
 
248
 
#ifdef SVR4
249
 
static int pppopen __P((queue_t *, dev_t *, int, int, cred_t *));
250
 
static int pppclose __P((queue_t *, int, cred_t *));
251
 
#else
252
 
static int pppopen __P((queue_t *, int, int, int));
253
 
static int pppclose __P((queue_t *, int));
254
 
#endif /* SVR4 */
255
 
static int pppurput __P((queue_t *, mblk_t *));
256
 
static int pppuwput __P((queue_t *, mblk_t *));
257
 
static int pppursrv __P((queue_t *));
258
 
static int pppuwsrv __P((queue_t *));
259
 
static int ppplrput __P((queue_t *, mblk_t *));
260
 
static int ppplwput __P((queue_t *, mblk_t *));
261
 
static int ppplrsrv __P((queue_t *));
262
 
static int ppplwsrv __P((queue_t *));
263
 
#ifndef NO_DLPI
264
 
static void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));
265
 
static void dlpi_error __P((queue_t *, upperstr_t *, int, int, int));
266
 
static void dlpi_ok __P((queue_t *, int));
267
 
#endif
268
 
static int send_data __P((mblk_t *, upperstr_t *));
269
 
static void new_ppa __P((queue_t *, mblk_t *));
270
 
static void attach_ppa __P((queue_t *, mblk_t *));
271
 
static void detach_ppa __P((queue_t *, mblk_t *));
272
 
static void detach_lower __P((queue_t *, mblk_t *));
273
 
static void debug_dump __P((queue_t *, mblk_t *));
274
 
static upperstr_t *find_dest __P((upperstr_t *, int));
275
 
#if defined(SOL2)
276
 
static upperstr_t *find_promisc __P((upperstr_t *, int));
277
 
static mblk_t *prepend_ether __P((upperstr_t *, mblk_t *, int));
278
 
static mblk_t *prepend_udind __P((upperstr_t *, mblk_t *, int));
279
 
static void promisc_sendup __P((upperstr_t *, mblk_t *, int, int));
280
 
#endif /* defined(SOL2) */
281
 
static int putctl2 __P((queue_t *, int, int, int));
282
 
static int putctl4 __P((queue_t *, int, int, int));
283
 
static int pass_packet __P((upperstr_t *ppa, mblk_t *mp, int outbound));
284
 
#ifdef FILTER_PACKETS
285
 
static int ip_hard_filter __P((upperstr_t *ppa, mblk_t *mp, int outbound));
286
 
#endif /* FILTER_PACKETS */
287
 
 
288
 
#define PPP_ID 0xb1a6
289
 
static struct module_info ppp_info = {
290
 
#ifdef PRIOQ
291
 
    PPP_ID, "ppp", 0, 512, 512, 384
292
 
#else
293
 
    PPP_ID, "ppp", 0, 512, 512, 128
294
 
#endif  /* PRIOQ */
295
 
};
296
 
 
297
 
static struct qinit pppurint = {
298
 
    pppurput, pppursrv, pppopen, pppclose, NULL, &ppp_info, NULL
299
 
};
300
 
 
301
 
static struct qinit pppuwint = {
302
 
    pppuwput, pppuwsrv, NULL, NULL, NULL, &ppp_info, NULL
303
 
};
304
 
 
305
 
static struct qinit ppplrint = {
306
 
    ppplrput, ppplrsrv, NULL, NULL, NULL, &ppp_info, NULL
307
 
};
308
 
 
309
 
static struct qinit ppplwint = {
310
 
    ppplwput, ppplwsrv, NULL, NULL, NULL, &ppp_info, NULL
311
 
};
312
 
 
313
 
#ifdef LACHTCP
314
 
extern struct ifstats *ifstats;
315
 
int pppdevflag = 0;
316
 
#endif
317
 
 
318
 
struct streamtab pppinfo = {
319
 
    &pppurint, &pppuwint,
320
 
    &ppplrint, &ppplwint
321
 
};
322
 
 
323
 
int ppp_count;
324
 
 
325
 
/*
326
 
 * How we maintain statistics.
327
 
 */
328
 
#ifdef SOL2
329
 
#define INCR_IPACKETS(ppa)                              \
330
 
        if (ppa->kstats != 0) {                         \
331
 
            KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++; \
332
 
        }
333
 
#define INCR_IERRORS(ppa)                               \
334
 
        if (ppa->kstats != 0) {                         \
335
 
            KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++; \
336
 
        }
337
 
#define INCR_OPACKETS(ppa)                              \
338
 
        if (ppa->kstats != 0) {                         \
339
 
            KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++; \
340
 
        }
341
 
#define INCR_OERRORS(ppa)                               \
342
 
        if (ppa->kstats != 0) {                         \
343
 
            KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++; \
344
 
        }
345
 
#endif
346
 
 
347
 
#ifdef LACHTCP
348
 
#define INCR_IPACKETS(ppa)      ppa->ifstats.ifs_ipackets++;
349
 
#define INCR_IERRORS(ppa)       ppa->ifstats.ifs_ierrors++;
350
 
#define INCR_OPACKETS(ppa)      ppa->ifstats.ifs_opackets++;
351
 
#define INCR_OERRORS(ppa)       ppa->ifstats.ifs_oerrors++;
352
 
#endif
353
 
 
354
 
/*
355
 
 * STREAMS driver entry points.
356
 
 */
357
 
static int
358
 
#ifdef SVR4
359
 
pppopen(q, devp, oflag, sflag, credp)
360
 
    queue_t *q;
361
 
    dev_t *devp;
362
 
    int oflag, sflag;
363
 
    cred_t *credp;
364
 
#else
365
 
pppopen(q, dev, oflag, sflag)
366
 
    queue_t *q;
367
 
    int dev;                    /* really dev_t */
368
 
    int oflag, sflag;
369
 
#endif
370
 
{
371
 
    upperstr_t *up;
372
 
    upperstr_t **prevp;
373
 
    minor_t mn;
374
 
#ifdef PRIOQ
375
 
    u_short *ptr;
376
 
    u_char new_band;
377
 
#endif  /* PRIOQ */
378
 
 
379
 
    if (q->q_ptr)
380
 
        DRV_OPEN_OK(dev);       /* device is already open */
381
 
 
382
 
#ifdef PRIOQ
383
 
    /* Calculate max_bband & def_band from definitions in prioq.h
384
 
       This colud be done at some more approtiate time (less often)
385
 
       but this way it works well so I'll just leave it here */
386
 
 
387
 
    max_band = 1;
388
 
    def_band = 0;
389
 
    ptr = prioq_table;
390
 
    while (*ptr) {
391
 
        new_band = 1;
392
 
        while (*ptr)
393
 
            if (*ptr++ == IPPORT_DEFAULT) {
394
 
                new_band = 0;
395
 
                def_band = max_band;
396
 
            }
397
 
        max_band += new_band;
398
 
        ptr++;
399
 
    }
400
 
    if (def_band)
401
 
        def_band = max_band - def_band;
402
 
    --max_band;
403
 
#endif  /* PRIOQ */
404
 
 
405
 
    if (sflag == CLONEOPEN) {
406
 
        mn = 0;
407
 
        for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
408
 
            if (up->mn != mn)
409
 
                break;
410
 
            ++mn;
411
 
        }
412
 
    } else {
413
 
#ifdef SVR4
414
 
        mn = getminor(*devp);
415
 
#else
416
 
        mn = minor(dev);
417
 
#endif
418
 
        for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
419
 
            if (up->mn >= mn)
420
 
                break;
421
 
        }
422
 
        if (up->mn == mn) {
423
 
            /* this can't happen */
424
 
            q->q_ptr = WR(q)->q_ptr = (caddr_t) up;
425
 
            DRV_OPEN_OK(dev);
426
 
        }
427
 
    }
428
 
 
429
 
    /*
430
 
     * Construct a new minor node.
431
 
     */
432
 
    up = (upperstr_t *) ALLOC_SLEEP(sizeof(upperstr_t));
433
 
    bzero((caddr_t) up, sizeof(upperstr_t));
434
 
    if (up == 0) {
435
 
        DPRINT("pppopen: out of kernel memory\n");
436
 
        OPEN_ERROR(ENXIO);
437
 
    }
438
 
    up->nextmn = *prevp;
439
 
    *prevp = up;
440
 
    up->mn = mn;
441
 
#ifdef SVR4
442
 
    *devp = makedevice(getmajor(*devp), mn);
443
 
#endif
444
 
    up->q = q;
445
 
    if (NOTSUSER() == 0)
446
 
        up->flags |= US_PRIV;
447
 
#ifndef NO_DLPI
448
 
    up->state = DL_UNATTACHED;
449
 
#endif
450
 
#ifdef LACHTCP
451
 
    up->ifflags = IFF_UP | IFF_POINTOPOINT;
452
 
#endif
453
 
    up->sap = -1;
454
 
    up->last_sent = up->last_recv = time;
455
 
    up->npmode = NPMODE_DROP;
456
 
    q->q_ptr = (caddr_t) up;
457
 
    WR(q)->q_ptr = (caddr_t) up;
458
 
    noenable(WR(q));
459
 
#ifdef SOL2
460
 
    mutex_init(&up->stats_lock, NULL, MUTEX_DRIVER, NULL);
461
 
#endif
462
 
    ++ppp_count;
463
 
 
464
 
    qprocson(q);
465
 
    DRV_OPEN_OK(makedev(major(dev), mn));
466
 
}
467
 
 
468
 
static int
469
 
#ifdef SVR4
470
 
pppclose(q, flag, credp)
471
 
    queue_t *q;
472
 
    int flag;
473
 
    cred_t *credp;
474
 
#else
475
 
pppclose(q, flag)
476
 
    queue_t *q;
477
 
    int flag;
478
 
#endif
479
 
{
480
 
    upperstr_t *up, **upp;
481
 
    upperstr_t *as, *asnext;
482
 
    upperstr_t **prevp;
483
 
 
484
 
    qprocsoff(q);
485
 
 
486
 
    up = (upperstr_t *) q->q_ptr;
487
 
    if (up == 0) {
488
 
        DPRINT("pppclose: q_ptr = 0\n");
489
 
        return 0;
490
 
    }
491
 
    if (up->flags & US_DBGLOG)
492
 
        DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);
493
 
    if (up->flags & US_CONTROL) {
494
 
#ifdef LACHTCP
495
 
        struct ifstats *ifp, *pifp;
496
 
#endif
497
 
        if (up->lowerq != 0) {
498
 
            /* Gack! the lower stream should have be unlinked earlier! */
499
 
            DPRINT1("ppp%d: lower stream still connected on close?\n",
500
 
                    up->mn);
501
 
            LOCK_LOWER_W;
502
 
            up->lowerq->q_ptr = 0;
503
 
            RD(up->lowerq)->q_ptr = 0;
504
 
            up->lowerq = 0;
505
 
            UNLOCK_LOWER;
506
 
        }
507
 
 
508
 
        /*
509
 
         * This stream represents a PPA:
510
 
         * For all streams attached to the PPA, clear their
511
 
         * references to this PPA.
512
 
         * Then remove this PPA from the list of PPAs.
513
 
         */
514
 
        for (as = up->next; as != 0; as = asnext) {
515
 
            asnext = as->next;
516
 
            as->next = 0;
517
 
            as->ppa = 0;
518
 
            if (as->flags & US_BLOCKED) {
519
 
                as->flags &= ~US_BLOCKED;
520
 
                flushq(WR(as->q), FLUSHDATA);
521
 
            }
522
 
        }
523
 
        for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa)
524
 
            if (*upp == up) {
525
 
                *upp = up->nextppa;
526
 
                break;
527
 
            }
528
 
#ifdef LACHTCP
529
 
        /* Remove the statistics from the active list.  */
530
 
        for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) {
531
 
            if (ifp == &up->ifstats) {
532
 
                if (pifp)
533
 
                    pifp->ifs_next = ifp->ifs_next;
534
 
                else
535
 
                    ifstats = ifp->ifs_next;
536
 
                break;
537
 
            }
538
 
            pifp = ifp;
539
 
        }
540
 
#endif
541
 
    } else {
542
 
        /*
543
 
         * If this stream is attached to a PPA,
544
 
         * remove it from the PPA's list.
545
 
         */
546
 
        if ((as = up->ppa) != 0) {
547
 
            for (; as->next != 0; as = as->next)
548
 
                if (as->next == up) {
549
 
                    as->next = up->next;
550
 
                    break;
551
 
                }
552
 
        }
553
 
    }
554
 
 
555
 
#ifdef SOL2
556
 
    if (up->kstats)
557
 
        kstat_delete(up->kstats);
558
 
    mutex_destroy(&up->stats_lock);
559
 
#endif
560
 
 
561
 
    q->q_ptr = NULL;
562
 
    WR(q)->q_ptr = NULL;
563
 
 
564
 
    for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
565
 
        if (*prevp == up) {
566
 
            *prevp = up->nextmn;
567
 
            break;
568
 
        }
569
 
    }
570
 
    FREE(up, sizeof(upperstr_t));
571
 
    --ppp_count;
572
 
 
573
 
    return 0;
574
 
}
575
 
 
576
 
/*
577
 
 * A message from on high.  We do one of three things:
578
 
 *      - qreply()
579
 
 *      - put the message on the lower write stream
580
 
 *      - queue it for our service routine
581
 
 */
582
 
static int
583
 
pppuwput(q, mp)
584
 
    queue_t *q;
585
 
    mblk_t *mp;
586
 
{
587
 
    upperstr_t *us, *ppa, *nps;
588
 
    struct iocblk *iop;
589
 
    struct linkblk *lb;
590
 
#ifdef LACHTCP
591
 
    struct ifreq *ifr;
592
 
    int i;
593
 
#endif
594
 
    queue_t *lq;
595
 
    int error, n, sap;
596
 
    mblk_t *mq;
597
 
    struct ppp_idle *pip;
598
 
#ifdef PRIOQ
599
 
    queue_t *tlq;
600
 
#endif  /* PRIOQ */
601
 
#ifdef NO_DLPI
602
 
    upperstr_t *os;
603
 
#endif
604
 
 
605
 
    us = (upperstr_t *) q->q_ptr;
606
 
    if (us == 0) {
607
 
        DPRINT("pppuwput: q_ptr = 0!\n");
608
 
        return 0;
609
 
    }
610
 
    if (mp == 0) {
611
 
        DPRINT1("pppuwput/%d: mp = 0!\n", us->mn);
612
 
        return 0;
613
 
    }
614
 
    if (mp->b_datap == 0) {
615
 
        DPRINT1("pppuwput/%d: mp->b_datap = 0!\n", us->mn);
616
 
        return 0;
617
 
    }
618
 
    switch (mp->b_datap->db_type) {
619
 
#ifndef NO_DLPI
620
 
    case M_PCPROTO:
621
 
    case M_PROTO:
622
 
        dlpi_request(q, mp, us);
623
 
        break;
624
 
#endif /* NO_DLPI */
625
 
 
626
 
    case M_DATA:
627
 
        if (us->flags & US_DBGLOG)
628
 
            DPRINT3("ppp/%d: uwput M_DATA len=%d flags=%x\n",
629
 
                    us->mn, msgdsize(mp), us->flags);
630
 
        if (us->ppa == 0 || msgdsize(mp) > us->ppa->mtu + PPP_HDRLEN
631
 
#ifndef NO_DLPI
632
 
            || (us->flags & US_CONTROL) == 0
633
 
#endif /* NO_DLPI */
634
 
            ) {
635
 
            DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp));
636
 
            freemsg(mp);
637
 
            break;
638
 
        }
639
 
#ifdef NO_DLPI
640
 
        if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1))
641
 
            break;
642
 
#endif
643
 
        if (!send_data(mp, us))
644
 
            putq(q, mp);
645
 
        break;
646
 
 
647
 
    case M_IOCTL:
648
 
        iop = (struct iocblk *) mp->b_rptr;
649
 
        error = EINVAL;
650
 
        if (us->flags & US_DBGLOG)
651
 
            DPRINT3("ppp/%d: ioctl %x count=%d\n",
652
 
                    us->mn, iop->ioc_cmd, iop->ioc_count);
653
 
        switch (iop->ioc_cmd) {
654
 
#if defined(SOL2)
655
 
        case DLIOCRAW:      /* raw M_DATA mode */
656
 
            us->flags |= US_RAWDATA;
657
 
            error = 0;
658
 
            break;
659
 
#endif /* defined(SOL2) */
660
 
        case I_LINK:
661
 
            if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
662
 
                break;
663
 
            if (mp->b_cont == 0) {
664
 
                DPRINT1("pppuwput/%d: ioctl I_LINK b_cont = 0!\n", us->mn);
665
 
                break;
666
 
            }
667
 
            lb = (struct linkblk *) mp->b_cont->b_rptr;
668
 
            lq = lb->l_qbot;
669
 
            if (lq == 0) {
670
 
                DPRINT1("pppuwput/%d: ioctl I_LINK l_qbot = 0!\n", us->mn);
671
 
                break;
672
 
            }
673
 
            LOCK_LOWER_W;
674
 
            us->lowerq = lq;
675
 
            lq->q_ptr = (caddr_t) q;
676
 
            RD(lq)->q_ptr = (caddr_t) us->q;
677
 
            UNLOCK_LOWER;
678
 
            iop->ioc_count = 0;
679
 
            error = 0;
680
 
            us->flags &= ~US_LASTMOD;
681
 
            /* Unblock upper streams which now feed this lower stream. */
682
 
            qenable(q);
683
 
            /* Send useful information down to the modules which
684
 
               are now linked below us. */
685
 
            putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
686
 
            putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
687
 
            putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
688
 
#ifdef PRIOQ
689
 
            /* Lower tty driver's queue hiwat/lowat from default 4096/128
690
 
               to 256/128 since we don't want queueing of data on
691
 
               output to physical device */
692
 
 
693
 
            freezestr(lq);
694
 
            for (tlq = lq; tlq->q_next != NULL; tlq = tlq->q_next)
695
 
                ;
696
 
            strqset(tlq, QHIWAT, 0, 256);
697
 
            strqset(tlq, QLOWAT, 0, 128);
698
 
            unfreezestr(lq);
699
 
#endif  /* PRIOQ */
700
 
            break;
701
 
 
702
 
        case I_UNLINK:
703
 
            if (mp->b_cont == 0) {
704
 
                DPRINT1("pppuwput/%d: ioctl I_UNLINK b_cont = 0!\n", us->mn);
705
 
                break;
706
 
            }
707
 
            lb = (struct linkblk *) mp->b_cont->b_rptr;
708
 
#if DEBUG
709
 
            if (us->lowerq != lb->l_qbot) {
710
 
                DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
711
 
                        us->lowerq, lb->l_qbot);
712
 
                break;
713
 
            }
714
 
#endif
715
 
            iop->ioc_count = 0;
716
 
            qwriter(q, mp, detach_lower, PERIM_OUTER);
717
 
            error = -1;
718
 
            break;
719
 
 
720
 
        case PPPIO_NEWPPA:
721
 
            if (us->flags & US_CONTROL)
722
 
                break;
723
 
            if ((us->flags & US_PRIV) == 0) {
724
 
                error = EPERM;
725
 
                break;
726
 
            }
727
 
            /* Arrange to return an int */
728
 
            if ((mq = mp->b_cont) == 0
729
 
                || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) {
730
 
                mq = allocb(sizeof(int), BPRI_HI);
731
 
                if (mq == 0) {
732
 
                    error = ENOSR;
733
 
                    break;
734
 
                }
735
 
                if (mp->b_cont != 0)
736
 
                    freemsg(mp->b_cont);
737
 
                mp->b_cont = mq;
738
 
                mq->b_cont = 0;
739
 
            }
740
 
            iop->ioc_count = sizeof(int);
741
 
            mq->b_wptr = mq->b_rptr + sizeof(int);
742
 
            qwriter(q, mp, new_ppa, PERIM_OUTER);
743
 
            error = -1;
744
 
            break;
745
 
 
746
 
        case PPPIO_ATTACH:
747
 
            /* like dlpi_attach, for programs which can't write to
748
 
               the stream (like pppstats) */
749
 
            if (iop->ioc_count != sizeof(int) || us->ppa != 0)
750
 
                break;
751
 
            if (mp->b_cont == 0) {
752
 
                DPRINT1("pppuwput/%d: ioctl PPPIO_ATTACH b_cont = 0!\n", us->mn);
753
 
                break;
754
 
            }
755
 
            n = *(int *)mp->b_cont->b_rptr;
756
 
            for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
757
 
                if (ppa->ppa_id == n)
758
 
                    break;
759
 
            if (ppa == 0)
760
 
                break;
761
 
            us->ppa = ppa;
762
 
            iop->ioc_count = 0;
763
 
            qwriter(q, mp, attach_ppa, PERIM_OUTER);
764
 
            error = -1;
765
 
            break;
766
 
 
767
 
#ifdef NO_DLPI
768
 
        case PPPIO_BIND:
769
 
            /* Attach to a given SAP. */
770
 
            if (iop->ioc_count != sizeof(int) || us->ppa == 0)
771
 
                break;
772
 
            if (mp->b_cont == 0) {
773
 
                DPRINT1("pppuwput/%d: ioctl PPPIO_BIND b_cont = 0!\n", us->mn);
774
 
                break;
775
 
            }
776
 
            n = *(int *)mp->b_cont->b_rptr;
777
 
            /* n must be a valid PPP network protocol number. */
778
 
            if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1)
779
 
                break;
780
 
            /* check that no other stream is bound to this sap already. */
781
 
            for (os = us->ppa; os != 0; os = os->next)
782
 
                if (os->sap == n)
783
 
                    break;
784
 
            if (os != 0)
785
 
                break;
786
 
            us->sap = n;
787
 
            iop->ioc_count = 0;
788
 
            error = 0;
789
 
            break;
790
 
#endif /* NO_DLPI */
791
 
 
792
 
        case PPPIO_MRU:
793
 
            if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
794
 
                break;
795
 
            if (mp->b_cont == 0) {
796
 
                DPRINT1("pppuwput/%d: ioctl PPPIO_MRU b_cont = 0!\n", us->mn);
797
 
                break;
798
 
            }
799
 
            n = *(int *)mp->b_cont->b_rptr;
800
 
            if (n <= 0 || n > PPP_MAXMRU)
801
 
                break;
802
 
            if (n < PPP_MRU)
803
 
                n = PPP_MRU;
804
 
            us->mru = n;
805
 
            if (us->lowerq)
806
 
                putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n);
807
 
            error = 0;
808
 
            iop->ioc_count = 0;
809
 
            break;
810
 
 
811
 
        case PPPIO_MTU:
812
 
            if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
813
 
                break;
814
 
            if (mp->b_cont == 0) {
815
 
                DPRINT1("pppuwput/%d: ioctl PPPIO_MTU b_cont = 0!\n", us->mn);
816
 
                break;
817
 
            }
818
 
            n = *(int *)mp->b_cont->b_rptr;
819
 
            if (n <= 0 || n > PPP_MAXMTU)
820
 
                break;
821
 
            us->mtu = n;
822
 
#ifdef LACHTCP
823
 
            /* The MTU reported in netstat, not used as IP max packet size! */
824
 
            us->ifstats.ifs_mtu = n;
825
 
#endif
826
 
            if (us->lowerq)
827
 
                putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n);
828
 
            error = 0;
829
 
            iop->ioc_count = 0;
830
 
            break;
831
 
 
832
 
        case PPPIO_LASTMOD:
833
 
            us->flags |= US_LASTMOD;
834
 
            error = 0;
835
 
            break;
836
 
 
837
 
        case PPPIO_DEBUG:
838
 
            if (iop->ioc_count != sizeof(int))
839
 
                break;
840
 
            if (mp->b_cont == 0) {
841
 
                DPRINT1("pppuwput/%d: ioctl PPPIO_DEBUG b_cont = 0!\n", us->mn);
842
 
                break;
843
 
            }
844
 
            n = *(int *)mp->b_cont->b_rptr;
845
 
            if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
846
 
                qwriter(q, NULL, debug_dump, PERIM_OUTER);
847
 
                iop->ioc_count = 0;
848
 
                error = -1;
849
 
            } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) {
850
 
                DPRINT1("ppp/%d: debug log enabled\n", us->mn);
851
 
                us->flags |= US_DBGLOG;
852
 
                iop->ioc_count = 0;
853
 
                error = 0;
854
 
            } else {
855
 
                if (us->ppa == 0 || us->ppa->lowerq == 0)
856
 
                    break;
857
 
                putnext(us->ppa->lowerq, mp);
858
 
                error = -1;
859
 
            }
860
 
            break;
861
 
 
862
 
        case PPPIO_NPMODE:
863
 
            if (iop->ioc_count != 2 * sizeof(int))
864
 
                break;
865
 
            if ((us->flags & US_CONTROL) == 0)
866
 
                break;
867
 
            if (mp->b_cont == 0) {
868
 
                DPRINT1("pppuwput/%d: ioctl PPPIO_NPMODE b_cont = 0!\n", us->mn);
869
 
                break;
870
 
            }
871
 
            sap = ((int *)mp->b_cont->b_rptr)[0];
872
 
            for (nps = us->next; nps != 0; nps = nps->next) {
873
 
                if (us->flags & US_DBGLOG)
874
 
                    DPRINT2("us = 0x%x, us->next->sap = 0x%x\n", nps, nps->sap);
875
 
                if (nps->sap == sap)
876
 
                    break;
877
 
            }
878
 
            if (nps == 0) {
879
 
                if (us->flags & US_DBGLOG)
880
 
                    DPRINT2("ppp/%d: no stream for sap %x\n", us->mn, sap);
881
 
                break;
882
 
            }
883
 
            /* XXX possibly should use qwriter here */
884
 
            nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1];
885
 
            if (nps->npmode != NPMODE_QUEUE && (nps->flags & US_BLOCKED) != 0)
886
 
                qenable(WR(nps->q));
887
 
            iop->ioc_count = 0;
888
 
            error = 0;
889
 
            break;
890
 
 
891
 
        case PPPIO_GIDLE:
892
 
            if ((ppa = us->ppa) == 0)
893
 
                break;
894
 
            mq = allocb(sizeof(struct ppp_idle), BPRI_HI);
895
 
            if (mq == 0) {
896
 
                error = ENOSR;
897
 
                break;
898
 
            }
899
 
            if (mp->b_cont != 0)
900
 
                freemsg(mp->b_cont);
901
 
            mp->b_cont = mq;
902
 
            mq->b_cont = 0;
903
 
            pip = (struct ppp_idle *) mq->b_wptr;
904
 
            pip->xmit_idle = time - ppa->last_sent;
905
 
            pip->recv_idle = time - ppa->last_recv;
906
 
            mq->b_wptr += sizeof(struct ppp_idle);
907
 
            iop->ioc_count = sizeof(struct ppp_idle);
908
 
            error = 0;
909
 
            break;
910
 
 
911
 
#ifdef LACHTCP
912
 
        case SIOCSIFNAME:
913
 
            /* Sent from IP down to us.  Attach the ifstats structure.  */
914
 
            if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
915
 
                break;
916
 
            ifr = (struct ifreq *)mp->b_cont->b_rptr;
917
 
            /* Find the unit number in the interface name.  */
918
 
            for (i = 0; i < IFNAMSIZ; i++) {
919
 
                if (ifr->ifr_name[i] == 0 ||
920
 
                    (ifr->ifr_name[i] >= '0' &&
921
 
                     ifr->ifr_name[i] <= '9'))
922
 
                    break;
923
 
                else
924
 
                    us->ifname[i] = ifr->ifr_name[i];
925
 
            }
926
 
            us->ifname[i] = 0;
927
 
 
928
 
            /* Convert the unit number to binary.  */
929
 
            for (n = 0; i < IFNAMSIZ; i++) {
930
 
                if (ifr->ifr_name[i] == 0) {
931
 
                    break;
932
 
                }
933
 
                else {
934
 
                    n = n * 10 + ifr->ifr_name[i] - '0';
935
 
                }
936
 
            }
937
 
 
938
 
            /* Verify the ppa.  */
939
 
            if (us->ppa->ppa_id != n)
940
 
                break;
941
 
            ppa = us->ppa;
942
 
 
943
 
            /* Set up the netstat block.  */
944
 
            strncpy (ppa->ifname, us->ifname, IFNAMSIZ);
945
 
 
946
 
            ppa->ifstats.ifs_name = ppa->ifname;
947
 
            ppa->ifstats.ifs_unit = n;
948
 
            ppa->ifstats.ifs_active = us->state != DL_UNBOUND;
949
 
            ppa->ifstats.ifs_mtu = ppa->mtu;
950
 
 
951
 
            /* Link in statistics used by netstat.  */
952
 
            ppa->ifstats.ifs_next = ifstats;
953
 
            ifstats = &ppa->ifstats;
954
 
 
955
 
            iop->ioc_count = 0;
956
 
            error = 0;
957
 
            break;
958
 
 
959
 
        case SIOCGIFFLAGS:
960
 
            if (!(us->flags & US_CONTROL)) {
961
 
                if (us->ppa)
962
 
                    us = us->ppa;
963
 
                else
964
 
                    break;
965
 
            }
966
 
            ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags;
967
 
            error = 0;
968
 
            break;
969
 
 
970
 
        case SIOCSIFFLAGS:
971
 
            if (!(us->flags & US_CONTROL)) {
972
 
                if (us->ppa)
973
 
                    us = us->ppa;
974
 
                else
975
 
                    break;
976
 
            }
977
 
            us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags;
978
 
            error = 0;
979
 
            break;
980
 
 
981
 
        case SIOCSIFADDR:
982
 
            if (!(us->flags & US_CONTROL)) {
983
 
                if (us->ppa)
984
 
                    us = us->ppa;
985
 
                else
986
 
                    break;
987
 
            }
988
 
            us->ifflags |= IFF_RUNNING;
989
 
            ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING;
990
 
            error = 0;
991
 
            break;
992
 
 
993
 
        case SIOCSIFMTU:
994
 
            /*
995
 
             * Vanilla SVR4 systems don't handle SIOCSIFMTU, rather
996
 
             * they take the MTU from the DL_INFO_ACK we sent in response
997
 
             * to their DL_INFO_REQ.  Fortunately, they will update the
998
 
             * MTU if we send an unsolicited DL_INFO_ACK up.
999
 
             */
1000
 
            if ((mq = allocb(sizeof(dl_info_req_t), BPRI_HI)) == 0)
1001
 
                break;          /* should do bufcall */
1002
 
            ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;
1003
 
            mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);
1004
 
            dlpi_request(q, mq, us);
1005
 
            error = 0;
1006
 
            break;
1007
 
 
1008
 
        case SIOCGIFNETMASK:
1009
 
        case SIOCSIFNETMASK:
1010
 
        case SIOCGIFADDR:
1011
 
        case SIOCGIFDSTADDR:
1012
 
        case SIOCSIFDSTADDR:
1013
 
        case SIOCGIFMETRIC:
1014
 
            error = 0;
1015
 
            break;
1016
 
#endif /* LACHTCP */
1017
 
 
1018
 
        default:
1019
 
            if (us->ppa == 0 || us->ppa->lowerq == 0)
1020
 
                break;
1021
 
            us->ioc_id = iop->ioc_id;
1022
 
            error = -1;
1023
 
            switch (iop->ioc_cmd) {
1024
 
            case PPPIO_GETSTAT:
1025
 
            case PPPIO_GETCSTAT:
1026
 
                if (us->flags & US_LASTMOD) {
1027
 
                    error = EINVAL;
1028
 
                    break;
1029
 
                }
1030
 
                putnext(us->ppa->lowerq, mp);
1031
 
                break;
1032
 
            default:
1033
 
                if (us->flags & US_PRIV)
1034
 
                    putnext(us->ppa->lowerq, mp);
1035
 
                else {
1036
 
                    DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);
1037
 
                    error = EPERM;
1038
 
                }
1039
 
                break;
1040
 
            }
1041
 
            break;
1042
 
        }
1043
 
 
1044
 
        if (error > 0) {
1045
 
            iop->ioc_error = error;
1046
 
            mp->b_datap->db_type = M_IOCNAK;
1047
 
            qreply(q, mp);
1048
 
        } else if (error == 0) {
1049
 
            mp->b_datap->db_type = M_IOCACK;
1050
 
            qreply(q, mp);
1051
 
        }
1052
 
        break;
1053
 
 
1054
 
    case M_FLUSH:
1055
 
        if (us->flags & US_DBGLOG)
1056
 
            DPRINT2("ppp/%d: flush %x\n", us->mn, *mp->b_rptr);
1057
 
        if (*mp->b_rptr & FLUSHW)
1058
 
            flushq(q, FLUSHDATA);
1059
 
        if (*mp->b_rptr & FLUSHR) {
1060
 
            *mp->b_rptr &= ~FLUSHW;
1061
 
            qreply(q, mp);
1062
 
        } else
1063
 
            freemsg(mp);
1064
 
        break;
1065
 
 
1066
 
    default:
1067
 
        freemsg(mp);
1068
 
        break;
1069
 
    }
1070
 
    return 0;
1071
 
}
1072
 
 
1073
 
#ifndef NO_DLPI
1074
 
static void
1075
 
dlpi_request(q, mp, us)
1076
 
    queue_t *q;
1077
 
    mblk_t *mp;
1078
 
    upperstr_t *us;
1079
 
{
1080
 
    union DL_primitives *d = (union DL_primitives *) mp->b_rptr;
1081
 
    int size = mp->b_wptr - mp->b_rptr;
1082
 
    mblk_t *reply, *np;
1083
 
    upperstr_t *ppa, *os;
1084
 
    int sap, len;
1085
 
    dl_info_ack_t *info;
1086
 
    dl_bind_ack_t *ackp;
1087
 
#if DL_CURRENT_VERSION >= 2
1088
 
    dl_phys_addr_ack_t  *paddrack;
1089
 
    static struct ether_addr eaddr = {0};
1090
 
#endif
1091
 
 
1092
 
    if (us->flags & US_DBGLOG)
1093
 
        DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,
1094
 
                d->dl_primitive, size);
1095
 
    switch (d->dl_primitive) {
1096
 
    case DL_INFO_REQ:
1097
 
        if (size < sizeof(dl_info_req_t))
1098
 
            goto badprim;
1099
 
        if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)
1100
 
            break;              /* should do bufcall */
1101
 
        reply->b_datap->db_type = M_PCPROTO;
1102
 
        info = (dl_info_ack_t *) reply->b_wptr;
1103
 
        reply->b_wptr += sizeof(dl_info_ack_t);
1104
 
        bzero((caddr_t) info, sizeof(dl_info_ack_t));
1105
 
        info->dl_primitive = DL_INFO_ACK;
1106
 
        info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;
1107
 
        info->dl_min_sdu = 1;
1108
 
        info->dl_addr_length = sizeof(uint);
1109
 
        info->dl_mac_type = DL_ETHER;   /* a bigger lie */
1110
 
        info->dl_current_state = us->state;
1111
 
        info->dl_service_mode = DL_CLDLS;
1112
 
        info->dl_provider_style = DL_STYLE2;
1113
 
#if DL_CURRENT_VERSION >= 2
1114
 
        info->dl_sap_length = sizeof(uint);
1115
 
        info->dl_version = DL_CURRENT_VERSION;
1116
 
#endif
1117
 
        qreply(q, reply);
1118
 
        break;
1119
 
 
1120
 
    case DL_ATTACH_REQ:
1121
 
        if (size < sizeof(dl_attach_req_t))
1122
 
            goto badprim;
1123
 
        if (us->state != DL_UNATTACHED || us->ppa != 0) {
1124
 
            dlpi_error(q, us, DL_ATTACH_REQ, DL_OUTSTATE, 0);
1125
 
            break;
1126
 
        }
1127
 
        for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
1128
 
            if (ppa->ppa_id == d->attach_req.dl_ppa)
1129
 
                break;
1130
 
        if (ppa == 0) {
1131
 
            dlpi_error(q, us, DL_ATTACH_REQ, DL_BADPPA, 0);
1132
 
            break;
1133
 
        }
1134
 
        us->ppa = ppa;
1135
 
        qwriter(q, mp, attach_ppa, PERIM_OUTER);
1136
 
        return;
1137
 
 
1138
 
    case DL_DETACH_REQ:
1139
 
        if (size < sizeof(dl_detach_req_t))
1140
 
            goto badprim;
1141
 
        if (us->state != DL_UNBOUND || us->ppa == 0) {
1142
 
            dlpi_error(q, us, DL_DETACH_REQ, DL_OUTSTATE, 0);
1143
 
            break;
1144
 
        }
1145
 
        qwriter(q, mp, detach_ppa, PERIM_OUTER);
1146
 
        return;
1147
 
 
1148
 
    case DL_BIND_REQ:
1149
 
        if (size < sizeof(dl_bind_req_t))
1150
 
            goto badprim;
1151
 
        if (us->state != DL_UNBOUND || us->ppa == 0) {
1152
 
            dlpi_error(q, us, DL_BIND_REQ, DL_OUTSTATE, 0);
1153
 
            break;
1154
 
        }
1155
 
#if 0
1156
 
        /* apparently this test fails (unnecessarily?) on some systems */
1157
 
        if (d->bind_req.dl_service_mode != DL_CLDLS) {
1158
 
            dlpi_error(q, us, DL_BIND_REQ, DL_UNSUPPORTED, 0);
1159
 
            break;
1160
 
        }
1161
 
#endif
1162
 
 
1163
 
        /* saps must be valid PPP network protocol numbers,
1164
 
           except that we accept ETHERTYPE_IP in place of PPP_IP. */
1165
 
        sap = d->bind_req.dl_sap;
1166
 
        us->req_sap = sap;
1167
 
 
1168
 
#if defined(SOL2)
1169
 
        if (us->flags & US_DBGLOG)
1170
 
            DPRINT2("DL_BIND_REQ: ip gives sap = 0x%x, us = 0x%x", sap, us);
1171
 
 
1172
 
        if (sap == ETHERTYPE_IP)            /* normal IFF_IPV4 */
1173
 
            sap = PPP_IP;
1174
 
        else if (sap == ETHERTYPE_IPV6)     /* when IFF_IPV6 is set */
1175
 
            sap = PPP_IPV6;
1176
 
        else if (sap == ETHERTYPE_ALLSAP)   /* snoop gives sap of 0 */
1177
 
            sap = PPP_ALLSAP;
1178
 
        else {
1179
 
            DPRINT2("DL_BIND_REQ: unrecognized sap = 0x%x, us = 0x%x", sap, us);
1180
 
            dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
1181
 
            break;
1182
 
        }
1183
 
#else
1184
 
        if (sap == ETHERTYPE_IP)
1185
 
            sap = PPP_IP;
1186
 
        if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
1187
 
            dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
1188
 
            break;
1189
 
        }
1190
 
#endif /* defined(SOL2) */
1191
 
 
1192
 
        /* check that no other stream is bound to this sap already. */
1193
 
        for (os = us->ppa; os != 0; os = os->next)
1194
 
            if (os->sap == sap)
1195
 
                break;
1196
 
        if (os != 0) {
1197
 
            dlpi_error(q, us, DL_BIND_REQ, DL_NOADDR, 0);
1198
 
            break;
1199
 
        }
1200
 
 
1201
 
        us->sap = sap;
1202
 
        us->state = DL_IDLE;
1203
 
 
1204
 
        if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(uint),
1205
 
                            BPRI_HI)) == 0)
1206
 
            break;              /* should do bufcall */
1207
 
        ackp = (dl_bind_ack_t *) reply->b_wptr;
1208
 
        reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(uint);
1209
 
        reply->b_datap->db_type = M_PCPROTO;
1210
 
        bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));
1211
 
        ackp->dl_primitive = DL_BIND_ACK;
1212
 
        ackp->dl_sap = sap;
1213
 
        ackp->dl_addr_length = sizeof(uint);
1214
 
        ackp->dl_addr_offset = sizeof(dl_bind_ack_t);
1215
 
        *(uint *)(ackp+1) = sap;
1216
 
        qreply(q, reply);
1217
 
        break;
1218
 
 
1219
 
    case DL_UNBIND_REQ:
1220
 
        if (size < sizeof(dl_unbind_req_t))
1221
 
            goto badprim;
1222
 
        if (us->state != DL_IDLE) {
1223
 
            dlpi_error(q, us, DL_UNBIND_REQ, DL_OUTSTATE, 0);
1224
 
            break;
1225
 
        }
1226
 
        us->sap = -1;
1227
 
        us->state = DL_UNBOUND;
1228
 
#ifdef LACHTCP
1229
 
        us->ppa->ifstats.ifs_active = 0;
1230
 
#endif
1231
 
        dlpi_ok(q, DL_UNBIND_REQ);
1232
 
        break;
1233
 
 
1234
 
    case DL_UNITDATA_REQ:
1235
 
        if (size < sizeof(dl_unitdata_req_t))
1236
 
            goto badprim;
1237
 
        if (us->state != DL_IDLE) {
1238
 
            dlpi_error(q, us, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
1239
 
            break;
1240
 
        }
1241
 
        if ((ppa = us->ppa) == 0) {
1242
 
            cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n");
1243
 
            break;
1244
 
        }
1245
 
        len = mp->b_cont == 0? 0: msgdsize(mp->b_cont);
1246
 
        if (len > ppa->mtu) {
1247
 
            DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
1248
 
            break;
1249
 
        }
1250
 
 
1251
 
#if defined(SOL2)
1252
 
        /*
1253
 
         * Should there be any promiscuous stream(s), send the data
1254
 
         * up for each promiscuous stream that we recognize.
1255
 
         */
1256
 
        if (mp->b_cont)
1257
 
            promisc_sendup(ppa, mp->b_cont, us->sap, 0);
1258
 
#endif /* defined(SOL2) */
1259
 
 
1260
 
        mp->b_band = 0;
1261
 
#ifdef PRIOQ
1262
 
        /* Extract s_port & d_port from IP-packet, the code is a bit
1263
 
           dirty here, but so am I, too... */
1264
 
        if (mp->b_datap->db_type == M_PROTO && us->sap == PPP_IP
1265
 
            && mp->b_cont != 0) {
1266
 
            u_char *bb, *tlh;
1267
 
            int iphlen, len;
1268
 
            u_short *ptr;
1269
 
            u_char band_unset, cur_band, syn;
1270
 
            u_short s_port, d_port;
1271
 
 
1272
 
            bb = mp->b_cont->b_rptr; /* bb points to IP-header*/
1273
 
            len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
1274
 
            syn = 0;
1275
 
            s_port = IPPORT_DEFAULT;
1276
 
            d_port = IPPORT_DEFAULT;
1277
 
            if (len >= 20) {    /* 20 = minimum length of IP header */
1278
 
                iphlen = (bb[0] & 0x0f) * 4;
1279
 
                tlh = bb + iphlen;
1280
 
                len -= iphlen;
1281
 
                switch (bb[9]) {
1282
 
                case IPPROTO_TCP:
1283
 
                    if (len >= 20) {          /* min length of TCP header */
1284
 
                        s_port = (tlh[0] << 8) + tlh[1];
1285
 
                        d_port = (tlh[2] << 8) + tlh[3];
1286
 
                        syn = tlh[13] & 0x02;
1287
 
                    }
1288
 
                    break;
1289
 
                case IPPROTO_UDP:
1290
 
                    if (len >= 8) {           /* min length of UDP header */
1291
 
                        s_port = (tlh[0] << 8) + tlh[1];
1292
 
                        d_port = (tlh[2] << 8) + tlh[3];
1293
 
                    }
1294
 
                    break;
1295
 
                }
1296
 
            }
1297
 
 
1298
 
            /*
1299
 
             * Now calculate b_band for this packet from the
1300
 
             * port-priority table.
1301
 
             */
1302
 
            ptr = prioq_table;
1303
 
            cur_band = max_band;
1304
 
            band_unset = 1;
1305
 
            while (*ptr) {
1306
 
                while (*ptr && band_unset)
1307
 
                    if (s_port == *ptr || d_port == *ptr++) {
1308
 
                        mp->b_band = cur_band;
1309
 
                        band_unset = 0;
1310
 
                        break;
1311
 
                    }
1312
 
                ptr++;
1313
 
                cur_band--;
1314
 
            }
1315
 
            if (band_unset)
1316
 
                mp->b_band = def_band;
1317
 
            /* It may be usable to urge SYN packets a bit */
1318
 
            if (syn)
1319
 
                mp->b_band++;
1320
 
        }
1321
 
#endif  /* PRIOQ */
1322
 
        /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
1323
 
        if (mp->b_datap->db_ref > 1) {
1324
 
            np = allocb(PPP_HDRLEN, BPRI_HI);
1325
 
            if (np == 0)
1326
 
                break;          /* gak! */
1327
 
            np->b_cont = mp->b_cont;
1328
 
            mp->b_cont = 0;
1329
 
            freeb(mp);
1330
 
            mp = np;
1331
 
        } else
1332
 
            mp->b_datap->db_type = M_DATA;
1333
 
        /* XXX should use dl_dest_addr_offset/length here,
1334
 
           but we would have to translate ETHERTYPE_IP -> PPP_IP */
1335
 
        mp->b_wptr = mp->b_rptr + PPP_HDRLEN;
1336
 
        mp->b_rptr[0] = PPP_ALLSTATIONS;
1337
 
        mp->b_rptr[1] = PPP_UI;
1338
 
        mp->b_rptr[2] = us->sap >> 8;
1339
 
        mp->b_rptr[3] = us->sap;
1340
 
        if (pass_packet(us, mp, 1)) {
1341
 
            if (!send_data(mp, us))
1342
 
                putq(q, mp);
1343
 
        }
1344
 
        return;
1345
 
 
1346
 
#if DL_CURRENT_VERSION >= 2
1347
 
    case DL_PHYS_ADDR_REQ:
1348
 
        if (size < sizeof(dl_phys_addr_req_t))
1349
 
            goto badprim;
1350
 
 
1351
 
        /*
1352
 
         * Don't check state because ifconfig sends this one down too
1353
 
         */
1354
 
 
1355
 
        if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL, 
1356
 
                        BPRI_HI)) == 0)
1357
 
            break;              /* should do bufcall */
1358
 
        reply->b_datap->db_type = M_PCPROTO;
1359
 
        paddrack = (dl_phys_addr_ack_t *) reply->b_wptr;
1360
 
        reply->b_wptr += sizeof(dl_phys_addr_ack_t);
1361
 
        bzero((caddr_t) paddrack, sizeof(dl_phys_addr_ack_t)+ETHERADDRL);
1362
 
        paddrack->dl_primitive = DL_PHYS_ADDR_ACK;
1363
 
        paddrack->dl_addr_length = ETHERADDRL;
1364
 
        paddrack->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
1365
 
        bcopy(&eaddr, reply->b_wptr, ETHERADDRL);
1366
 
        reply->b_wptr += ETHERADDRL;
1367
 
        qreply(q, reply);
1368
 
        break;
1369
 
 
1370
 
#if defined(SOL2)
1371
 
    case DL_PROMISCON_REQ:
1372
 
        if (size < sizeof(dl_promiscon_req_t))
1373
 
            goto badprim;
1374
 
        us->flags |= US_PROMISC;
1375
 
        dlpi_ok(q, DL_PROMISCON_REQ);
1376
 
        break;
1377
 
 
1378
 
    case DL_PROMISCOFF_REQ:
1379
 
        if (size < sizeof(dl_promiscoff_req_t))
1380
 
            goto badprim;
1381
 
        us->flags &= ~US_PROMISC;
1382
 
        dlpi_ok(q, DL_PROMISCOFF_REQ);
1383
 
        break;
1384
 
#else
1385
 
    case DL_PROMISCON_REQ:          /* fall thru */
1386
 
    case DL_PROMISCOFF_REQ:         /* fall thru */
1387
 
#endif /* defined(SOL2) */
1388
 
#endif /* DL_CURRENT_VERSION >= 2 */
1389
 
 
1390
 
#if DL_CURRENT_VERSION >= 2
1391
 
    case DL_SET_PHYS_ADDR_REQ:
1392
 
    case DL_SUBS_BIND_REQ:
1393
 
    case DL_SUBS_UNBIND_REQ:
1394
 
    case DL_ENABMULTI_REQ:
1395
 
    case DL_DISABMULTI_REQ:
1396
 
    case DL_XID_REQ:
1397
 
    case DL_TEST_REQ:
1398
 
    case DL_REPLY_UPDATE_REQ:
1399
 
    case DL_REPLY_REQ:
1400
 
    case DL_DATA_ACK_REQ:
1401
 
#endif
1402
 
    case DL_CONNECT_REQ:
1403
 
    case DL_TOKEN_REQ:
1404
 
        dlpi_error(q, us, d->dl_primitive, DL_NOTSUPPORTED, 0);
1405
 
        break;
1406
 
 
1407
 
    case DL_CONNECT_RES:
1408
 
    case DL_DISCONNECT_REQ:
1409
 
    case DL_RESET_REQ:
1410
 
    case DL_RESET_RES:
1411
 
        dlpi_error(q, us, d->dl_primitive, DL_OUTSTATE, 0);
1412
 
        break;
1413
 
 
1414
 
    case DL_UDQOS_REQ:
1415
 
        dlpi_error(q, us, d->dl_primitive, DL_BADQOSTYPE, 0);
1416
 
        break;
1417
 
 
1418
 
#if DL_CURRENT_VERSION >= 2
1419
 
    case DL_TEST_RES:
1420
 
    case DL_XID_RES:
1421
 
        break;
1422
 
#endif
1423
 
 
1424
 
    default:
1425
 
        cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
1426
 
        /* fall through */
1427
 
    badprim:
1428
 
        dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);
1429
 
        break;
1430
 
    }
1431
 
    freemsg(mp);
1432
 
}
1433
 
 
1434
 
static void
1435
 
dlpi_error(q, us, prim, err, uerr)
1436
 
    queue_t *q;
1437
 
    upperstr_t *us;
1438
 
    int prim, err, uerr;
1439
 
{
1440
 
    mblk_t *reply;
1441
 
    dl_error_ack_t *errp;
1442
 
 
1443
 
    if (us->flags & US_DBGLOG)
1444
 
        DPRINT3("ppp/%d: dlpi error, prim=%x, err=%x\n", us->mn, prim, err);
1445
 
    reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
1446
 
    if (reply == 0)
1447
 
        return;                 /* XXX should do bufcall */
1448
 
    reply->b_datap->db_type = M_PCPROTO;
1449
 
    errp = (dl_error_ack_t *) reply->b_wptr;
1450
 
    reply->b_wptr += sizeof(dl_error_ack_t);
1451
 
    errp->dl_primitive = DL_ERROR_ACK;
1452
 
    errp->dl_error_primitive = prim;
1453
 
    errp->dl_errno = err;
1454
 
    errp->dl_unix_errno = uerr;
1455
 
    qreply(q, reply);
1456
 
}
1457
 
 
1458
 
static void
1459
 
dlpi_ok(q, prim)
1460
 
    queue_t *q;
1461
 
    int prim;
1462
 
{
1463
 
    mblk_t *reply;
1464
 
    dl_ok_ack_t *okp;
1465
 
 
1466
 
    reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);
1467
 
    if (reply == 0)
1468
 
        return;                 /* XXX should do bufcall */
1469
 
    reply->b_datap->db_type = M_PCPROTO;
1470
 
    okp = (dl_ok_ack_t *) reply->b_wptr;
1471
 
    reply->b_wptr += sizeof(dl_ok_ack_t);
1472
 
    okp->dl_primitive = DL_OK_ACK;
1473
 
    okp->dl_correct_primitive = prim;
1474
 
    qreply(q, reply);
1475
 
}
1476
 
#endif /* NO_DLPI */
1477
 
 
1478
 
static int
1479
 
pass_packet(us, mp, outbound)
1480
 
    upperstr_t *us;
1481
 
    mblk_t *mp;
1482
 
    int outbound;
1483
 
{
1484
 
    int pass;
1485
 
    upperstr_t *ppa;
1486
 
 
1487
 
    if ((ppa = us->ppa) == 0) {
1488
 
        freemsg(mp);
1489
 
        return 0;
1490
 
    }
1491
 
 
1492
 
#ifdef FILTER_PACKETS
1493
 
    pass = ip_hard_filter(us, mp, outbound);
1494
 
#else
1495
 
    /*
1496
 
     * Here is where we might, in future, decide whether to pass
1497
 
     * or drop the packet, and whether it counts as link activity.
1498
 
     */
1499
 
    pass = 1;
1500
 
#endif /* FILTER_PACKETS */
1501
 
 
1502
 
    if (pass < 0) {
1503
 
        /* pass only if link already up, and don't update time */
1504
 
        if (ppa->lowerq == 0) {
1505
 
            freemsg(mp);
1506
 
            return 0;
1507
 
        }
1508
 
        pass = 1;
1509
 
    } else if (pass) {
1510
 
        if (outbound)
1511
 
            ppa->last_sent = time;
1512
 
        else
1513
 
            ppa->last_recv = time;
1514
 
    }
1515
 
 
1516
 
    return pass;
1517
 
}
1518
 
 
1519
 
/*
1520
 
 * We have some data to send down to the lower stream (or up the
1521
 
 * control stream, if we don't have a lower stream attached).
1522
 
 * Returns 1 if the message was dealt with, 0 if it wasn't able
1523
 
 * to be sent on and should therefore be queued up.
1524
 
 */
1525
 
static int
1526
 
send_data(mp, us)
1527
 
    mblk_t *mp;
1528
 
    upperstr_t *us;
1529
 
{
1530
 
    upperstr_t *ppa;
1531
 
 
1532
 
    if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)
1533
 
        return 0;
1534
 
    ppa = us->ppa;
1535
 
    if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) {
1536
 
        if (us->flags & US_DBGLOG)
1537
 
            DPRINT2("ppp/%d: dropping pkt (npmode=%d)\n", us->mn, us->npmode);
1538
 
        freemsg(mp);
1539
 
        return 1;
1540
 
    }
1541
 
    if (ppa->lowerq == 0) {
1542
 
        /* try to send it up the control stream */
1543
 
        if (bcanputnext(ppa->q, mp->b_band)) {
1544
 
            /*
1545
 
             * The message seems to get corrupted for some reason if
1546
 
             * we just send the message up as it is, so we send a copy.
1547
 
             */
1548
 
            mblk_t *np = copymsg(mp);
1549
 
            freemsg(mp);
1550
 
            if (np != 0)
1551
 
                putnext(ppa->q, np);
1552
 
            return 1;
1553
 
        }
1554
 
    } else {
1555
 
        if (bcanputnext(ppa->lowerq, mp->b_band)) {
1556
 
            MT_ENTER(&ppa->stats_lock);
1557
 
            ppa->stats.ppp_opackets++;
1558
 
            ppa->stats.ppp_obytes += msgdsize(mp);
1559
 
#ifdef INCR_OPACKETS
1560
 
            INCR_OPACKETS(ppa);
1561
 
#endif
1562
 
            MT_EXIT(&ppa->stats_lock);
1563
 
            /*
1564
 
             * The lower queue is only ever detached while holding an
1565
 
             * exclusive lock on the whole driver.  So we can be confident
1566
 
             * that the lower queue is still there.
1567
 
             */
1568
 
            putnext(ppa->lowerq, mp);
1569
 
            return 1;
1570
 
        }
1571
 
    }
1572
 
    us->flags |= US_BLOCKED;
1573
 
    return 0;
1574
 
}
1575
 
 
1576
 
/*
1577
 
 * Allocate a new PPA id and link this stream into the list of PPAs.
1578
 
 * This procedure is called with an exclusive lock on all queues in
1579
 
 * this driver.
1580
 
 */
1581
 
static void
1582
 
new_ppa(q, mp)
1583
 
    queue_t *q;
1584
 
    mblk_t *mp;
1585
 
{
1586
 
    upperstr_t *us, *up, **usp;
1587
 
    int ppa_id;
1588
 
 
1589
 
    us = (upperstr_t *) q->q_ptr;
1590
 
    if (us == 0) {
1591
 
        DPRINT("new_ppa: q_ptr = 0!\n");
1592
 
        return;
1593
 
    }
1594
 
 
1595
 
    usp = &ppas;
1596
 
    ppa_id = 0;
1597
 
    while ((up = *usp) != 0 && ppa_id == up->ppa_id) {
1598
 
        ++ppa_id;
1599
 
        usp = &up->nextppa;
1600
 
    }
1601
 
    us->ppa_id = ppa_id;
1602
 
    us->ppa = us;
1603
 
    us->next = 0;
1604
 
    us->nextppa = *usp;
1605
 
    *usp = us;
1606
 
    us->flags |= US_CONTROL;
1607
 
    us->npmode = NPMODE_PASS;
1608
 
 
1609
 
    us->mtu = PPP_MTU;
1610
 
    us->mru = PPP_MRU;
1611
 
 
1612
 
#ifdef SOL2
1613
 
    /*
1614
 
     * Create a kstats record for our statistics, so netstat -i works.
1615
 
     */
1616
 
    if (us->kstats == 0) {
1617
 
        char unit[32];
1618
 
 
1619
 
        sprintf(unit, "ppp%d", us->ppa->ppa_id);
1620
 
        us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,
1621
 
                                  "net", KSTAT_TYPE_NAMED, 4, 0);
1622
 
        if (us->kstats != 0) {
1623
 
            kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);
1624
 
 
1625
 
            strcpy(kn[0].name, "ipackets");
1626
 
            kn[0].data_type = KSTAT_DATA_ULONG;
1627
 
            strcpy(kn[1].name, "ierrors");
1628
 
            kn[1].data_type = KSTAT_DATA_ULONG;
1629
 
            strcpy(kn[2].name, "opackets");
1630
 
            kn[2].data_type = KSTAT_DATA_ULONG;
1631
 
            strcpy(kn[3].name, "oerrors");
1632
 
            kn[3].data_type = KSTAT_DATA_ULONG;
1633
 
            kstat_install(us->kstats);
1634
 
        }
1635
 
    }
1636
 
#endif /* SOL2 */
1637
 
 
1638
 
    *(int *)mp->b_cont->b_rptr = ppa_id;
1639
 
    mp->b_datap->db_type = M_IOCACK;
1640
 
    qreply(q, mp);
1641
 
}
1642
 
 
1643
 
static void
1644
 
attach_ppa(q, mp)
1645
 
    queue_t *q;
1646
 
    mblk_t *mp;
1647
 
{
1648
 
    upperstr_t *us, *t;
1649
 
 
1650
 
    us = (upperstr_t *) q->q_ptr;
1651
 
    if (us == 0) {
1652
 
        DPRINT("attach_ppa: q_ptr = 0!\n");
1653
 
        return;
1654
 
    }
1655
 
 
1656
 
#ifndef NO_DLPI
1657
 
    us->state = DL_UNBOUND;
1658
 
#endif
1659
 
    for (t = us->ppa; t->next != 0; t = t->next)
1660
 
        ;
1661
 
    t->next = us;
1662
 
    us->next = 0;
1663
 
    if (mp->b_datap->db_type == M_IOCTL) {
1664
 
        mp->b_datap->db_type = M_IOCACK;
1665
 
        qreply(q, mp);
1666
 
    } else {
1667
 
#ifndef NO_DLPI
1668
 
        dlpi_ok(q, DL_ATTACH_REQ);
1669
 
#endif
1670
 
    }
1671
 
}
1672
 
 
1673
 
static void
1674
 
detach_ppa(q, mp)
1675
 
    queue_t *q;
1676
 
    mblk_t *mp;
1677
 
{
1678
 
    upperstr_t *us, *t;
1679
 
 
1680
 
    us = (upperstr_t *) q->q_ptr;
1681
 
    if (us == 0) {
1682
 
        DPRINT("detach_ppa: q_ptr = 0!\n");
1683
 
        return;
1684
 
    }
1685
 
 
1686
 
    for (t = us->ppa; t->next != 0; t = t->next)
1687
 
        if (t->next == us) {
1688
 
            t->next = us->next;
1689
 
            break;
1690
 
        }
1691
 
    us->next = 0;
1692
 
    us->ppa = 0;
1693
 
#ifndef NO_DLPI
1694
 
    us->state = DL_UNATTACHED;
1695
 
    dlpi_ok(q, DL_DETACH_REQ);
1696
 
#endif
1697
 
}
1698
 
 
1699
 
/*
1700
 
 * We call this with qwriter in order to give the upper queue procedures
1701
 
 * the guarantee that the lower queue is not going to go away while
1702
 
 * they are executing.
1703
 
 */
1704
 
static void
1705
 
detach_lower(q, mp)
1706
 
    queue_t *q;
1707
 
    mblk_t *mp;
1708
 
{
1709
 
    upperstr_t *us;
1710
 
 
1711
 
    us = (upperstr_t *) q->q_ptr;
1712
 
    if (us == 0) {
1713
 
        DPRINT("detach_lower: q_ptr = 0!\n");
1714
 
        return;
1715
 
    }
1716
 
 
1717
 
    LOCK_LOWER_W;
1718
 
    us->lowerq->q_ptr = 0;
1719
 
    RD(us->lowerq)->q_ptr = 0;
1720
 
    us->lowerq = 0;
1721
 
    UNLOCK_LOWER;
1722
 
 
1723
 
    /* Unblock streams which now feed back up the control stream. */
1724
 
    qenable(us->q);
1725
 
 
1726
 
    mp->b_datap->db_type = M_IOCACK;
1727
 
    qreply(q, mp);
1728
 
}
1729
 
 
1730
 
static int
1731
 
pppuwsrv(q)
1732
 
    queue_t *q;
1733
 
{
1734
 
    upperstr_t *us, *as;
1735
 
    mblk_t *mp;
1736
 
 
1737
 
    us = (upperstr_t *) q->q_ptr;
1738
 
    if (us == 0) {
1739
 
        DPRINT("pppuwsrv: q_ptr = 0!\n");
1740
 
        return 0;
1741
 
    }
1742
 
 
1743
 
    /*
1744
 
     * If this is a control stream, then this service procedure
1745
 
     * probably got enabled because of flow control in the lower
1746
 
     * stream being enabled (or because of the lower stream going
1747
 
     * away).  Therefore we enable the service procedure of all
1748
 
     * attached upper streams.
1749
 
     */
1750
 
    if (us->flags & US_CONTROL) {
1751
 
        for (as = us->next; as != 0; as = as->next)
1752
 
            qenable(WR(as->q));
1753
 
    }
1754
 
 
1755
 
    /* Try to send on any data queued here. */
1756
 
    us->flags &= ~US_BLOCKED;
1757
 
    while ((mp = getq(q)) != 0) {
1758
 
        if (!send_data(mp, us)) {
1759
 
            putbq(q, mp);
1760
 
            break;
1761
 
        }
1762
 
    }
1763
 
 
1764
 
    return 0;
1765
 
}
1766
 
 
1767
 
/* should never get called... */
1768
 
static int
1769
 
ppplwput(q, mp)
1770
 
    queue_t *q;
1771
 
    mblk_t *mp;
1772
 
{
1773
 
    putnext(q, mp);
1774
 
    return 0;
1775
 
}
1776
 
 
1777
 
static int
1778
 
ppplwsrv(q)
1779
 
    queue_t *q;
1780
 
{
1781
 
    queue_t *uq;
1782
 
 
1783
 
    /*
1784
 
     * Flow control has back-enabled this stream:
1785
 
     * enable the upper write service procedure for
1786
 
     * the upper control stream for this lower stream.
1787
 
     */
1788
 
    LOCK_LOWER_R;
1789
 
    uq = (queue_t *) q->q_ptr;
1790
 
    if (uq != 0)
1791
 
        qenable(uq);
1792
 
    UNLOCK_LOWER;
1793
 
    return 0;
1794
 
}
1795
 
 
1796
 
/*
1797
 
 * This should only get called for control streams.
1798
 
 */
1799
 
static int
1800
 
pppurput(q, mp)
1801
 
    queue_t *q;
1802
 
    mblk_t *mp;
1803
 
{
1804
 
    upperstr_t *ppa, *us;
1805
 
    int proto, len;
1806
 
    struct iocblk *iop;
1807
 
 
1808
 
    ppa = (upperstr_t *) q->q_ptr;
1809
 
    if (ppa == 0) {
1810
 
        DPRINT("pppurput: q_ptr = 0!\n");
1811
 
        return 0;
1812
 
    }
1813
 
 
1814
 
    switch (mp->b_datap->db_type) {
1815
 
    case M_CTL:
1816
 
        MT_ENTER(&ppa->stats_lock);
1817
 
        switch (*mp->b_rptr) {
1818
 
        case PPPCTL_IERROR:
1819
 
#ifdef INCR_IERRORS
1820
 
            INCR_IERRORS(ppa);
1821
 
#endif
1822
 
            ppa->stats.ppp_ierrors++;
1823
 
            break;
1824
 
        case PPPCTL_OERROR:
1825
 
#ifdef INCR_OERRORS
1826
 
            INCR_OERRORS(ppa);
1827
 
#endif
1828
 
            ppa->stats.ppp_oerrors++;
1829
 
            break;
1830
 
        }
1831
 
        MT_EXIT(&ppa->stats_lock);
1832
 
        freemsg(mp);
1833
 
        break;
1834
 
 
1835
 
    case M_IOCACK:
1836
 
    case M_IOCNAK:
1837
 
        /*
1838
 
         * Attempt to match up the response with the stream
1839
 
         * that the request came from.
1840
 
         */
1841
 
        iop = (struct iocblk *) mp->b_rptr;
1842
 
        for (us = ppa; us != 0; us = us->next)
1843
 
            if (us->ioc_id == iop->ioc_id)
1844
 
                break;
1845
 
        if (us == 0)
1846
 
            freemsg(mp);
1847
 
        else
1848
 
            putnext(us->q, mp);
1849
 
        break;
1850
 
 
1851
 
    case M_HANGUP:
1852
 
        /*
1853
 
         * The serial device has hung up.  We don't want to send
1854
 
         * the M_HANGUP message up to pppd because that will stop
1855
 
         * us from using the control stream any more.  Instead we
1856
 
         * send a zero-length message as an end-of-file indication.
1857
 
         */
1858
 
        freemsg(mp);
1859
 
        mp = allocb(1, BPRI_HI);
1860
 
        if (mp == 0) {
1861
 
            DPRINT1("ppp/%d: couldn't allocate eof message!\n", ppa->mn);
1862
 
            break;
1863
 
        }
1864
 
        putnext(ppa->q, mp);
1865
 
        break;
1866
 
 
1867
 
    default:
1868
 
        if (mp->b_datap->db_type == M_DATA) {
1869
 
            len = msgdsize(mp);
1870
 
            if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {
1871
 
                PULLUP(mp, PPP_HDRLEN);
1872
 
                if (mp == 0) {
1873
 
                    DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);
1874
 
                    break;
1875
 
                }
1876
 
            }
1877
 
            MT_ENTER(&ppa->stats_lock);
1878
 
            ppa->stats.ppp_ipackets++;
1879
 
            ppa->stats.ppp_ibytes += len;
1880
 
#ifdef INCR_IPACKETS
1881
 
            INCR_IPACKETS(ppa);
1882
 
#endif
1883
 
            MT_EXIT(&ppa->stats_lock);
1884
 
 
1885
 
            proto = PPP_PROTOCOL(mp->b_rptr);
1886
 
 
1887
 
#if defined(SOL2)
1888
 
            /*
1889
 
             * Should there be any promiscuous stream(s), send the data
1890
 
             * up for each promiscuous stream that we recognize.
1891
 
             */
1892
 
            promisc_sendup(ppa, mp, proto, 1);
1893
 
#endif /* defined(SOL2) */
1894
 
 
1895
 
            if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
1896
 
                /*
1897
 
                 * A data packet for some network protocol.
1898
 
                 * Queue it on the upper stream for that protocol.
1899
 
                 * XXX could we just putnext it?  (would require thought)
1900
 
                 * The rblocked flag is there to ensure that we keep
1901
 
                 * messages in order for each network protocol.
1902
 
                 */
1903
 
                if (!pass_packet(us, mp, 0))
1904
 
                    break;
1905
 
                if (!us->rblocked && !canput(us->q))
1906
 
                    us->rblocked = 1;
1907
 
                if (!us->rblocked)
1908
 
                    putq(us->q, mp);
1909
 
                else
1910
 
                    putq(q, mp);
1911
 
                break;
1912
 
            }
1913
 
        }
1914
 
        /*
1915
 
         * A control frame, a frame for an unknown protocol,
1916
 
         * or some other message type.
1917
 
         * Send it up to pppd via the control stream.
1918
 
         */
1919
 
        if (queclass(mp) == QPCTL || canputnext(ppa->q))
1920
 
            putnext(ppa->q, mp);
1921
 
        else
1922
 
            putq(q, mp);
1923
 
        break;
1924
 
    }
1925
 
 
1926
 
    return 0;
1927
 
}
1928
 
 
1929
 
static int
1930
 
pppursrv(q)
1931
 
    queue_t *q;
1932
 
{
1933
 
    upperstr_t *us, *as;
1934
 
    mblk_t *mp, *hdr;
1935
 
#ifndef NO_DLPI
1936
 
    dl_unitdata_ind_t *ud;
1937
 
#endif
1938
 
    int proto;
1939
 
 
1940
 
    us = (upperstr_t *) q->q_ptr;
1941
 
    if (us == 0) {
1942
 
        DPRINT("pppursrv: q_ptr = 0!\n");
1943
 
        return 0;
1944
 
    }
1945
 
 
1946
 
    if (us->flags & US_CONTROL) {
1947
 
        /*
1948
 
         * A control stream.
1949
 
         * If there is no lower queue attached, run the write service
1950
 
         * routines of other upper streams attached to this PPA.
1951
 
         */
1952
 
        if (us->lowerq == 0) {
1953
 
            as = us;
1954
 
            do {
1955
 
                if (as->flags & US_BLOCKED)
1956
 
                    qenable(WR(as->q));
1957
 
                as = as->next;
1958
 
            } while (as != 0);
1959
 
        }
1960
 
 
1961
 
        /*
1962
 
         * Messages get queued on this stream's read queue if they
1963
 
         * can't be queued on the read queue of the attached stream
1964
 
         * that they are destined for.  This is for flow control -
1965
 
         * when this queue fills up, the lower read put procedure will
1966
 
         * queue messages there and the flow control will propagate
1967
 
         * down from there.
1968
 
         */
1969
 
        while ((mp = getq(q)) != 0) {
1970
 
            proto = PPP_PROTOCOL(mp->b_rptr);
1971
 
            if (proto < 0x8000 && (as = find_dest(us, proto)) != 0) {
1972
 
                if (!canput(as->q))
1973
 
                    break;
1974
 
                putq(as->q, mp);
1975
 
            } else {
1976
 
                if (!canputnext(q))
1977
 
                    break;
1978
 
                putnext(q, mp);
1979
 
            }
1980
 
        }
1981
 
        if (mp) {
1982
 
            putbq(q, mp);
1983
 
        } else {
1984
 
            /* can now put stuff directly on network protocol streams again */
1985
 
            for (as = us->next; as != 0; as = as->next)
1986
 
                as->rblocked = 0;
1987
 
        }
1988
 
 
1989
 
        /*
1990
 
         * If this stream has a lower stream attached,
1991
 
         * enable the read queue's service routine.
1992
 
         * XXX we should really only do this if the queue length
1993
 
         * has dropped below the low-water mark.
1994
 
         */
1995
 
        if (us->lowerq != 0)
1996
 
            qenable(RD(us->lowerq));
1997
 
                
1998
 
    } else {
1999
 
        /*
2000
 
         * A network protocol stream.  Put a DLPI header on each
2001
 
         * packet and send it on.
2002
 
         * (Actually, it seems that the IP module will happily
2003
 
         * accept M_DATA messages without the DL_UNITDATA_IND header.)
2004
 
         */
2005
 
        while ((mp = getq(q)) != 0) {
2006
 
            if (!canputnext(q)) {
2007
 
                putbq(q, mp);
2008
 
                break;
2009
 
            }
2010
 
#ifndef NO_DLPI
2011
 
            proto = PPP_PROTOCOL(mp->b_rptr);
2012
 
            mp->b_rptr += PPP_HDRLEN;
2013
 
            hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint),
2014
 
                         BPRI_MED);
2015
 
            if (hdr == 0) {
2016
 
                /* XXX should put it back and use bufcall */
2017
 
                freemsg(mp);
2018
 
                continue;
2019
 
            }
2020
 
            hdr->b_datap->db_type = M_PROTO;
2021
 
            ud = (dl_unitdata_ind_t *) hdr->b_wptr;
2022
 
            hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint);
2023
 
            hdr->b_cont = mp;
2024
 
            ud->dl_primitive = DL_UNITDATA_IND;
2025
 
            ud->dl_dest_addr_length = sizeof(uint);
2026
 
            ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
2027
 
            ud->dl_src_addr_length = sizeof(uint);
2028
 
            ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(uint);
2029
 
#if DL_CURRENT_VERSION >= 2
2030
 
            ud->dl_group_address = 0;
2031
 
#endif
2032
 
            /* Send the DLPI client the data with the SAP they requested,
2033
 
               (e.g. ETHERTYPE_IP) rather than the PPP protocol number
2034
 
               (e.g. PPP_IP) */
2035
 
            ((uint *)(ud + 1))[0] = us->req_sap;        /* dest SAP */
2036
 
            ((uint *)(ud + 1))[1] = us->req_sap;        /* src SAP */
2037
 
            putnext(q, hdr);
2038
 
#else /* NO_DLPI */
2039
 
            putnext(q, mp);
2040
 
#endif /* NO_DLPI */
2041
 
        }
2042
 
        /*
2043
 
         * Now that we have consumed some packets from this queue,
2044
 
         * enable the control stream's read service routine so that we
2045
 
         * can process any packets for us that might have got queued
2046
 
         * there for flow control reasons.
2047
 
         */
2048
 
        if (us->ppa)
2049
 
            qenable(us->ppa->q);
2050
 
    }
2051
 
 
2052
 
    return 0;
2053
 
}
2054
 
 
2055
 
static upperstr_t *
2056
 
find_dest(ppa, proto)
2057
 
    upperstr_t *ppa;
2058
 
    int proto;
2059
 
{
2060
 
    upperstr_t *us;
2061
 
 
2062
 
    for (us = ppa->next; us != 0; us = us->next)
2063
 
        if (proto == us->sap)
2064
 
            break;
2065
 
    return us;
2066
 
}
2067
 
 
2068
 
#if defined (SOL2)
2069
 
/*
2070
 
 * Test upstream promiscuous conditions. As of now, only pass IPv4 and
2071
 
 * Ipv6 packets upstream (let PPP packets be decoded elsewhere).
2072
 
 */
2073
 
static upperstr_t *
2074
 
find_promisc(us, proto)
2075
 
    upperstr_t *us;
2076
 
    int proto;
2077
 
{
2078
 
 
2079
 
    if ((proto != PPP_IP) && (proto != PPP_IPV6))
2080
 
        return (upperstr_t *)0;
2081
 
 
2082
 
    for ( ; us; us = us->next) {
2083
 
        if ((us->flags & US_PROMISC) && (us->state == DL_IDLE))
2084
 
            return us;
2085
 
    }
2086
 
 
2087
 
    return (upperstr_t *)0;
2088
 
}
2089
 
 
2090
 
/*
2091
 
 * Prepend an empty Ethernet header to msg for snoop, et al.
2092
 
 */
2093
 
static mblk_t *
2094
 
prepend_ether(us, mp, proto)
2095
 
    upperstr_t *us;
2096
 
    mblk_t *mp;
2097
 
    int proto;
2098
 
{
2099
 
    mblk_t *eh;
2100
 
    int type;
2101
 
 
2102
 
    if ((eh = allocb(sizeof(struct ether_header), BPRI_HI)) == 0) {
2103
 
        freemsg(mp);
2104
 
        return (mblk_t *)0;
2105
 
    }
2106
 
 
2107
 
    if (proto == PPP_IP)
2108
 
        type = ETHERTYPE_IP;
2109
 
    else if (proto == PPP_IPV6)
2110
 
        type = ETHERTYPE_IPV6;
2111
 
    else 
2112
 
        type = proto;       /* What else? Let decoder decide */
2113
 
 
2114
 
    eh->b_wptr += sizeof(struct ether_header);
2115
 
    bzero((caddr_t)eh->b_rptr, sizeof(struct ether_header));
2116
 
    ((struct ether_header *)eh->b_rptr)->ether_type = htons((short)type);
2117
 
    eh->b_cont = mp;
2118
 
    return (eh);
2119
 
}
2120
 
 
2121
 
/*
2122
 
 * Prepend DL_UNITDATA_IND mblk to msg
2123
 
 */
2124
 
static mblk_t *
2125
 
prepend_udind(us, mp, proto)
2126
 
    upperstr_t *us;
2127
 
    mblk_t *mp;
2128
 
    int proto;
2129
 
{
2130
 
    dl_unitdata_ind_t *dlu;
2131
 
    mblk_t *dh;
2132
 
    size_t size;
2133
 
 
2134
 
    size = sizeof(dl_unitdata_ind_t);
2135
 
    if ((dh = allocb(size, BPRI_MED)) == 0) {
2136
 
        freemsg(mp);
2137
 
        return (mblk_t *)0;
2138
 
    }
2139
 
 
2140
 
    dh->b_datap->db_type = M_PROTO;
2141
 
    dh->b_wptr = dh->b_datap->db_lim;
2142
 
    dh->b_rptr = dh->b_wptr - size;
2143
 
 
2144
 
    dlu = (dl_unitdata_ind_t *)dh->b_rptr;
2145
 
    dlu->dl_primitive = DL_UNITDATA_IND;
2146
 
    dlu->dl_dest_addr_length = 0;
2147
 
    dlu->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
2148
 
    dlu->dl_src_addr_length = 0;
2149
 
    dlu->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);
2150
 
    dlu->dl_group_address = 0;
2151
 
 
2152
 
    dh->b_cont = mp;
2153
 
    return (dh);
2154
 
}
2155
 
 
2156
 
/*
2157
 
 * For any recognized promiscuous streams, send data upstream
2158
 
 */
2159
 
static void
2160
 
promisc_sendup(ppa, mp, proto, skip)
2161
 
    upperstr_t *ppa;
2162
 
    mblk_t *mp;
2163
 
    int proto, skip;
2164
 
{
2165
 
    mblk_t *dup_mp, *dup_dup_mp;
2166
 
    upperstr_t *prus, *nprus;
2167
 
 
2168
 
    if ((prus = find_promisc(ppa, proto)) != 0) {
2169
 
        if (dup_mp = dupmsg(mp)) {
2170
 
 
2171
 
            if (skip)
2172
 
                dup_mp->b_rptr += PPP_HDRLEN;
2173
 
 
2174
 
            for ( ; nprus = find_promisc(prus->next, proto); 
2175
 
                    prus = nprus) {
2176
 
 
2177
 
                if (dup_dup_mp = dupmsg(dup_mp)) {
2178
 
                    if (canputnext(prus->q)) {
2179
 
                        if (prus->flags & US_RAWDATA) {
2180
 
                            dup_dup_mp = prepend_ether(prus, dup_dup_mp, proto);
2181
 
                            putnext(prus->q, dup_dup_mp);
2182
 
                        } else {
2183
 
                            dup_dup_mp = prepend_udind(prus, dup_dup_mp, proto);
2184
 
                            putnext(prus->q, dup_dup_mp);
2185
 
                        }
2186
 
                    } else {
2187
 
                        DPRINT("ppp_urput: data to promisc q dropped\n");
2188
 
                        freemsg(dup_dup_mp);
2189
 
                    }
2190
 
                }
2191
 
            }
2192
 
 
2193
 
            if (canputnext(prus->q)) {
2194
 
                if (prus->flags & US_RAWDATA) {
2195
 
                    dup_mp = prepend_ether(prus, dup_mp, proto);
2196
 
                    putnext(prus->q, dup_mp);
2197
 
                } else {
2198
 
                    dup_mp = prepend_udind(prus, dup_mp, proto);
2199
 
                    putnext(prus->q, dup_mp);
2200
 
                }
2201
 
            } else {
2202
 
                DPRINT("ppp_urput: data to promisc q dropped\n");
2203
 
                freemsg(dup_mp);
2204
 
            }
2205
 
        }
2206
 
    }
2207
 
}
2208
 
#endif /* defined(SOL2) */
2209
 
 
2210
 
/*
2211
 
 * We simply put the message on to the associated upper control stream
2212
 
 * (either here or in ppplrsrv).  That way we enter the perimeters
2213
 
 * before looking through the list of attached streams to decide which
2214
 
 * stream it should go up.
2215
 
 */
2216
 
static int
2217
 
ppplrput(q, mp)
2218
 
    queue_t *q;
2219
 
    mblk_t *mp;
2220
 
{
2221
 
    queue_t *uq;
2222
 
    struct iocblk *iop;
2223
 
 
2224
 
    switch (mp->b_datap->db_type) {
2225
 
    case M_IOCTL:
2226
 
        iop = (struct iocblk *) mp->b_rptr;
2227
 
        iop->ioc_error = EINVAL;
2228
 
        mp->b_datap->db_type = M_IOCNAK;
2229
 
        qreply(q, mp);
2230
 
        return 0;
2231
 
    case M_FLUSH:
2232
 
        if (*mp->b_rptr & FLUSHR)
2233
 
            flushq(q, FLUSHDATA);
2234
 
        if (*mp->b_rptr & FLUSHW) {
2235
 
            *mp->b_rptr &= ~FLUSHR;
2236
 
            qreply(q, mp);
2237
 
        } else
2238
 
            freemsg(mp);
2239
 
        return 0;
2240
 
    }
2241
 
 
2242
 
    /*
2243
 
     * If we can't get the lower lock straight away, queue this one
2244
 
     * rather than blocking, to avoid the possibility of deadlock.
2245
 
     */
2246
 
    if (!TRYLOCK_LOWER_R) {
2247
 
        putq(q, mp);
2248
 
        return 0;
2249
 
    }
2250
 
 
2251
 
    /*
2252
 
     * Check that we're still connected to the driver.
2253
 
     */
2254
 
    uq = (queue_t *) q->q_ptr;
2255
 
    if (uq == 0) {
2256
 
        UNLOCK_LOWER;
2257
 
        DPRINT1("ppplrput: q = %x, uq = 0??\n", q);
2258
 
        freemsg(mp);
2259
 
        return 0;
2260
 
    }
2261
 
 
2262
 
    /*
2263
 
     * Try to forward the message to the put routine for the upper
2264
 
     * control stream for this lower stream.
2265
 
     * If there are already messages queued here, queue this one so
2266
 
     * they don't get out of order.
2267
 
     */
2268
 
    if (queclass(mp) == QPCTL || (qsize(q) == 0 && canput(uq)))
2269
 
        put(uq, mp);
2270
 
    else
2271
 
        putq(q, mp);
2272
 
 
2273
 
    UNLOCK_LOWER;
2274
 
    return 0;
2275
 
}
2276
 
 
2277
 
static int
2278
 
ppplrsrv(q)
2279
 
    queue_t *q;
2280
 
{
2281
 
    mblk_t *mp;
2282
 
    queue_t *uq;
2283
 
 
2284
 
    /*
2285
 
     * Packets get queued here for flow control reasons
2286
 
     * or if the lrput routine couldn't get the lower lock
2287
 
     * without blocking.
2288
 
     */
2289
 
    LOCK_LOWER_R;
2290
 
    uq = (queue_t *) q->q_ptr;
2291
 
    if (uq == 0) {
2292
 
        UNLOCK_LOWER;
2293
 
        flushq(q, FLUSHALL);
2294
 
        DPRINT1("ppplrsrv: q = %x, uq = 0??\n", q);
2295
 
        return 0;
2296
 
    }
2297
 
    while ((mp = getq(q)) != 0) {
2298
 
        if (queclass(mp) == QPCTL || canput(uq))
2299
 
            put(uq, mp);
2300
 
        else {
2301
 
            putbq(q, mp);
2302
 
            break;
2303
 
        }
2304
 
    }
2305
 
    UNLOCK_LOWER;
2306
 
    return 0;
2307
 
}
2308
 
 
2309
 
static int
2310
 
putctl2(q, type, code, val)
2311
 
    queue_t *q;
2312
 
    int type, code, val;
2313
 
{
2314
 
    mblk_t *mp;
2315
 
 
2316
 
    mp = allocb(2, BPRI_HI);
2317
 
    if (mp == 0)
2318
 
        return 0;
2319
 
    mp->b_datap->db_type = type;
2320
 
    mp->b_wptr[0] = code;
2321
 
    mp->b_wptr[1] = val;
2322
 
    mp->b_wptr += 2;
2323
 
    putnext(q, mp);
2324
 
    return 1;
2325
 
}
2326
 
 
2327
 
static int
2328
 
putctl4(q, type, code, val)
2329
 
    queue_t *q;
2330
 
    int type, code, val;
2331
 
{
2332
 
    mblk_t *mp;
2333
 
 
2334
 
    mp = allocb(4, BPRI_HI);
2335
 
    if (mp == 0)
2336
 
        return 0;
2337
 
    mp->b_datap->db_type = type;
2338
 
    mp->b_wptr[0] = code;
2339
 
    ((short *)mp->b_wptr)[1] = val;
2340
 
    mp->b_wptr += 4;
2341
 
    putnext(q, mp);
2342
 
    return 1;
2343
 
}
2344
 
 
2345
 
static void
2346
 
debug_dump(q, mp)
2347
 
    queue_t *q;
2348
 
    mblk_t *mp;
2349
 
{
2350
 
    upperstr_t *us;
2351
 
    queue_t *uq, *lq;
2352
 
 
2353
 
    DPRINT("ppp upper streams:\n");
2354
 
    for (us = minor_devs; us != 0; us = us->nextmn) {
2355
 
        uq = us->q;
2356
 
        DPRINT3(" %d: q=%x rlev=%d",
2357
 
                us->mn, uq, (uq? qsize(uq): 0));
2358
 
        DPRINT3(" wlev=%d flags=0x%b", (uq? qsize(WR(uq)): 0),
2359
 
                us->flags, "\020\1priv\2control\3blocked\4last");
2360
 
        DPRINT3(" state=%x sap=%x req_sap=%x", us->state, us->sap,
2361
 
                us->req_sap);
2362
 
        if (us->ppa == 0)
2363
 
            DPRINT(" ppa=?\n");
2364
 
        else
2365
 
            DPRINT1(" ppa=%d\n", us->ppa->ppa_id);
2366
 
        if (us->flags & US_CONTROL) {
2367
 
            lq = us->lowerq;
2368
 
            DPRINT3("    control for %d lq=%x rlev=%d",
2369
 
                    us->ppa_id, lq, (lq? qsize(RD(lq)): 0));
2370
 
            DPRINT3(" wlev=%d mru=%d mtu=%d\n",
2371
 
                    (lq? qsize(lq): 0), us->mru, us->mtu);
2372
 
        }
2373
 
    }
2374
 
    mp->b_datap->db_type = M_IOCACK;
2375
 
    qreply(q, mp);
2376
 
}
2377
 
 
2378
 
#ifdef FILTER_PACKETS
2379
 
#include <netinet/in_systm.h>
2380
 
#include <netinet/ip.h>
2381
 
#include <netinet/udp.h>
2382
 
#include <netinet/tcp.h>
2383
 
 
2384
 
#define MAX_IPHDR    128     /* max TCP/IP header size */
2385
 
 
2386
 
 
2387
 
/* The following table contains a hard-coded list of protocol/port pairs.
2388
 
 * Any matching packets are either discarded unconditionally, or, 
2389
 
 * if ok_if_link_up is non-zero when a connection does not currently exist
2390
 
 * (i.e., they go through if the connection is present, but never initiate
2391
 
 * a dial-out).
2392
 
 * This idea came from a post by dm@garage.uun.org (David Mazieres)
2393
 
 */
2394
 
static struct pktfilt_tab { 
2395
 
        int proto; 
2396
 
        u_short port; 
2397
 
        u_short ok_if_link_up; 
2398
 
} pktfilt_tab[] = {
2399
 
        { IPPROTO_UDP,  520,    1 },    /* RIP, ok to pass if link is up */
2400
 
        { IPPROTO_UDP,  123,    1 },    /* NTP, don't keep up the link for it */
2401
 
        { -1,           0,      0 }     /* terminator entry has port == -1 */
2402
 
};
2403
 
 
2404
 
 
2405
 
static int
2406
 
ip_hard_filter(us, mp, outbound)
2407
 
    upperstr_t *us;
2408
 
    mblk_t *mp;
2409
 
    int outbound;
2410
 
{
2411
 
    struct ip *ip;
2412
 
    struct pktfilt_tab *pft;
2413
 
    mblk_t *temp_mp;
2414
 
    int proto;
2415
 
    int len, hlen;
2416
 
 
2417
 
 
2418
 
    /* Note, the PPP header has already been pulled up in all cases */
2419
 
    proto = PPP_PROTOCOL(mp->b_rptr);
2420
 
    if (us->flags & US_DBGLOG)
2421
 
        DPRINT3("ppp/%d: filter, proto=0x%x, out=%d\n", us->mn, proto, outbound);
2422
 
 
2423
 
    switch (proto)
2424
 
    {
2425
 
    case PPP_IP:
2426
 
        if ((mp->b_wptr - mp->b_rptr) == PPP_HDRLEN && mp->b_cont != 0) {
2427
 
            temp_mp = mp->b_cont;
2428
 
            len = msgdsize(temp_mp);
2429
 
            hlen = (len < MAX_IPHDR) ? len : MAX_IPHDR;
2430
 
            PULLUP(temp_mp, hlen);
2431
 
            if (temp_mp == 0) {
2432
 
                DPRINT2("ppp/%d: filter, pullup next failed, len=%d\n", 
2433
 
                        us->mn, hlen);
2434
 
                mp->b_cont = 0;         /* PULLUP() freed the rest */
2435
 
                freemsg(mp);
2436
 
                return 0;
2437
 
            }
2438
 
            ip = (struct ip *)mp->b_cont->b_rptr;
2439
 
        }
2440
 
        else {
2441
 
            len = msgdsize(mp);
2442
 
            hlen = (len < (PPP_HDRLEN+MAX_IPHDR)) ? len : (PPP_HDRLEN+MAX_IPHDR);
2443
 
            PULLUP(mp, hlen);
2444
 
            if (mp == 0) {
2445
 
                DPRINT2("ppp/%d: filter, pullup failed, len=%d\n", 
2446
 
                        us->mn, hlen);
2447
 
                return 0;
2448
 
            }
2449
 
            ip = (struct ip *)(mp->b_rptr + PPP_HDRLEN);
2450
 
        }
2451
 
 
2452
 
        /* For IP traffic, certain packets (e.g., RIP) may be either
2453
 
         *   1.  ignored - dropped completely
2454
 
         *   2.  will not initiate a connection, but
2455
 
         *       will be passed if a connection is currently up.
2456
 
         */
2457
 
        for (pft=pktfilt_tab; pft->proto != -1; pft++) {
2458
 
            if (ip->ip_p == pft->proto) {
2459
 
                switch(pft->proto) {
2460
 
                case IPPROTO_UDP:
2461
 
                    if (((struct udphdr *) &((int *)ip)[ip->ip_hl])->uh_dport
2462
 
                                == htons(pft->port)) goto endfor;
2463
 
                    break;
2464
 
                case IPPROTO_TCP:
2465
 
                    if (((struct tcphdr *) &((int *)ip)[ip->ip_hl])->th_dport
2466
 
                                == htons(pft->port)) goto endfor;
2467
 
                    break;
2468
 
                }       
2469
 
            }
2470
 
        }
2471
 
        endfor:
2472
 
        if (pft->proto != -1) {
2473
 
            if (us->flags & US_DBGLOG)
2474
 
                DPRINT3("ppp/%d: found IP pkt, proto=0x%x (%d)\n", 
2475
 
                                us->mn, pft->proto, pft->port);
2476
 
            /* Discard if not connected, or if not pass_with_link_up */
2477
 
            /* else, if link is up let go by, but don't update time */
2478
 
            return pft->ok_if_link_up? -1: 0;
2479
 
        }
2480
 
        break;
2481
 
    } /* end switch (proto) */
2482
 
 
2483
 
    return 1;
2484
 
}
2485
 
#endif /* FILTER_PACKETS */
2486