2 ppp_if.c - Streams PPP interface module
4 top level module handles if_ and packetizing PPP packets.
6 Copyright (C) 1990 Brad K. Clements, All Rights Reserved
7 See copyright notice in NOTES
12 #include <sys/types.h>
22 #define PPP_STATS 1 /* keep statistics */
25 #include <net/net_globals.h>
26 #include <sys/param.h>
27 #include <sys/stream.h>
28 #include <sys/stropts.h>
29 #include <sys/strconf.h>
31 #include <sys/device.h>
36 #include <sys/systm.h>
39 #include <sys/socket.h>
40 #include <sys/errno.h>
41 #include <sys/ioctl.h>
45 #include <net/route.h>
46 #include <net/netisr.h>
47 #include <netinet/in.h>
48 #include <netinet/in_var.h>
49 #define _NETINET_IN_SYSTM_H_
50 typedef u_long n_long
;
51 #include <netinet/ip.h>
53 #include <net/ppp_defs.h>
54 #include <net/ppp_str.h>
58 #include <net/vjcompress.h>
62 #define INCR(comp) ++p->pii_stats.comp
67 #define MAX_PKTSIZE 4096 /* max packet size including framing */
68 #define PPP_FRAMING 6 /* 4-byte header + 2-byte FCS */
69 #define MAX_IPHDR 128 /* max TCP/IP header size */
70 #define MAX_VJHDR 20 /* max VJ compressed header size (?) */
73 * Network protocols we support.
76 #define NUM_NP 1 /* # protocols supported */
79 * Structure used within the ppp_if streams module.
83 struct ifnet pii_ifnet
;
84 queue_t
*pii_writeq
; /* used by ppp_output */
85 enum NPmode pii_npmode
[NUM_NP
];
86 mblk_t
*pii_npq
; /* list of packets queued up */
87 mblk_t
**pii_npq_tail
;
89 struct vjcompress pii_sc_comp
; /* vjc control buffer */
92 struct pppstat pii_stats
;
93 struct ppp_comp_stats pii_cstats
;
98 * Values for pii_flags.
100 #define PII_FLAGS_INUSE 0x1 /* in use by a stream */
101 #define PII_FLAGS_ATTACHED 0x8 /* already if_attached */
102 #define PII_FLAGS_VJC_ON 0x10 /* VJ TCP header compression enabled */
103 #define PII_FLAGS_VJC_NOCCID 0x20 /* VJ: don't compress conn. id */
104 #define PII_FLAGS_VJC_REJ 0x40 /* receive: reject VJ comp */
105 #define PII_FLAGS_DEBUG 0x80 /* enable debug printout */
108 #include <sys/syslog.h>
109 #define DLOG(s,a) if (p->pii_flags&PII_FLAGS_DEBUG) bsdlog(LOG_INFO, s, a)
115 #include <net/nit_if.h>
116 #include <netinet/if_ether.h>
117 /* Use a fake link level header to make etherfind and tcpdump happy. */
118 static struct ether_header header
= {{1}, {2}, ETHERTYPE_IP
};
119 static struct nit_if nif
= {(caddr_t
)&header
, sizeof(header
), 0, 0};
122 static int ppp_if_open(), ppp_if_close(), ppp_if_rput(), ppp_if_wput(),
123 ppp_if_wsrv(), ppp_if_rsrv();
125 static struct module_info minfo
={
126 0xbad,"ppp_if",0, INFPSZ
, 16384, 4096
129 static struct qinit r_init
= {
130 ppp_if_rput
, ppp_if_rsrv
, ppp_if_open
, ppp_if_close
, NULL
, &minfo
, NULL
132 static struct qinit w_init
= {
133 ppp_if_wput
, ppp_if_wsrv
, ppp_if_open
, ppp_if_close
, NULL
, &minfo
, NULL
135 struct streamtab ppp_ifinfo
= {
136 &r_init
, &w_init
, NULL
, NULL
139 typedef struct ppp_if_info PII
;
143 int ppp_output(), ppp_ioctl();
144 static void if_release_addrs(), if_delete_route();
146 strconf_t pppconf
= {
147 "pppif", &ppp_ifinfo
, STR_NEW_OPEN
, 0, SQLVL_DEFAULT
, (void *) 0
150 int ppp_load(int cmd
, struct uio
*uiop
)
156 rc
= str_install(STR_LOAD_MOD
, &pppconf
);
159 rc
= str_install(STR_UNLOAD_MOD
, &pppconf
);
165 if ((rc
== 0) && !(pii
= xmalloc(sizeof(PII
) * NUM_PPP
, 0, pinned_heap
)))
168 bzero(pii
, sizeof(PII
) * NUM_PPP
);
177 register struct ifnet
*ifp
= &pii
[unit
].pii_ifnet
;
179 ifp
->if_name
= "ppp";
180 ifp
->if_type
= IFT_PTPSERIAL
;
181 ifp
->if_mtu
= PPP_MTU
;
182 ifp
->if_flags
= IFF_POINTOPOINT
;
184 ifp
->if_ioctl
= ppp_ioctl
;
185 ifp
->if_output
= ppp_output
;
186 ifp
->if_snd
.ifq_maxlen
= IFQ_MAXLEN
;
189 pii
[unit
].pii_flags
|= PII_FLAGS_ATTACHED
;
197 struct ifnet
*ifp
= &pii
[unit
].pii_ifnet
;
201 if (!(pii
[unit
].pii_flags
& PII_FLAGS_ATTACHED
))
204 /* remove interface from interface list */
205 for (p
= &ifp
; *p
; p
= &((*p
)->if_next
)) {
209 /* mark it down and flush it's que */
212 /* free any addresses hanging off the intf */
213 if_release_addrs(ifp
);
215 pii
[unit
].pii_flags
&= ~PII_FLAGS_ATTACHED
;
226 if_release_addrs(ifp
)
227 register struct ifnet
*ifp
;
229 register struct in_ifaddr
**addr
;
230 register struct ifaddr
*ifa
, *ifanxt
;
233 if_delete_route(ifp
);
235 for (addr
= &in_ifaddr
; *addr
; ) {
236 if ((*addr
)->ia_ifp
== ifp
)
237 *addr
= (*addr
)->ia_next
;
239 addr
= &((*addr
)->ia_next
);
243 * Free all mbufs holding down this interface's address(es).
245 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifanxt
) {
246 ifanxt
= ifa
->ifa_next
;
249 ifp
->if_addrlist
= 0;
253 * Delete routes to the specified interface.
254 * Hacked from rtrequest().
260 extern int rttrash
; /* routes not in table but not freed */
261 register struct mbuf
**mprev
, *m
;
262 register struct rtentry
*route
;
265 /* search host rt tbl */
267 for (i = 0; i < RTHASHSIZ; i++) {
270 route = mtod(m, struct rtentry *);
271 if (route->rt_ifp == ifp) {
273 if (route->rt_refcnt > 0) {
274 route->rt_flags &= ~RTF_UP;
286 /* search net rt tbl */
288 for (i = 0; i < RTHASHSIZ; i++) {
291 route = mtod(m, struct rtentry *);
292 if (route->rt_ifp == ifp) {
294 if (route->rt_refcnt > 0) {
295 route->rt_flags &= ~RTF_UP;
313 for (x
= 0; x
< NUM_PPP
; x
++) {
314 if (pii
[x
].pii_flags
& PII_FLAGS_INUSE
)
326 for (x
= 0; x
< NUM_PPP
; x
++)
327 if (!(pii
[x
].pii_flags
& PII_FLAGS_INUSE
))
329 if (x
== NUM_PPP
) { /* all buffers in use */
333 p
->pii_flags
|= PII_FLAGS_INUSE
;
346 vj_compress_init(&p
->pii_sc_comp
, -1);
349 bzero(&p
->pii_stats
, sizeof(p
->pii_stats
));
351 if (!(p
->pii_flags
& PII_FLAGS_ATTACHED
))
352 ppp_attach(p
- pii
); /* attach it */
354 p
->pii_ifnet
.if_mtu
= PPP_MTU
;
355 p
->pii_writeq
= WR(q
);
356 /* set write Q and read Q to point here */
357 WR(q
)->q_ptr
= q
->q_ptr
= (caddr_t
) p
;
358 p
->pii_ifnet
.if_flags
|= IFF_RUNNING
;
359 p
->pii_flags
&= PII_FLAGS_INUSE
| PII_FLAGS_ATTACHED
| PII_FLAGS_DEBUG
;
360 for (n
= 0; n
< NUM_NP
; ++n
)
361 p
->pii_npmode
[n
] = NPMODE_ERROR
;
362 p
->pii_npmode
[NP_IP
] = NPMODE_PASS
; /* for backwards compatibility */
364 p
->pii_npq_tail
= &p
->pii_npq
;
366 DLOG("ppp_if%d: init\n", p
- pii
);
370 ppp_if_open(q
, dev
, flag
, sflag
)
385 queue_t
*q
; /* queue info */
387 PII
*p
= (PII
*) q
->q_ptr
;
392 if_down(&p
->pii_ifnet
);
393 p
->pii_ifnet
.if_flags
&= ~IFF_RUNNING
;
394 p
->pii_flags
&= ~PII_FLAGS_INUSE
;
396 for (mp
= p
->pii_npq
; mp
!= NULL
; mp
= mq
) {
401 p
->pii_npq_tail
= &p
->pii_npq
;
402 p
->pii_writeq
= NULL
;
403 DLOG("ppp_if%d: closed\n", p
- pii
);
405 return(0); /* no work to be done */
414 register struct iocblk
*i
;
416 int bits
, flags
, error
, unit
, s
;
420 mblk_t
*mq
, **mqnext
;
421 struct ppp_stats
*psp
;
423 switch (mp
->b_datap
->db_type
) {
426 if (*mp
->b_rptr
& FLUSHW
)
427 flushq(q
, FLUSHDATA
);
428 putnext(q
, mp
); /* send it along too */
432 putq(q
, mp
); /* queue it for my service routine */
436 i
= (struct iocblk
*) mp
->b_rptr
;
437 p
= (PII
*) q
->q_ptr
;
438 switch ((unsigned int)i
->ioc_cmd
) {
440 case SIOCSIFVJCOMP
: /* enable or disable VJ compression */
442 if (i
->ioc_count
== TRANSPARENT
) {
443 bits
= *(u_int
*) mp
->b_cont
->b_rptr
;
444 DLOG("ppp_if: SIFVJCOMP %d\n", bits
);
446 p
->pii_flags
|= PII_FLAGS_VJC_ON
;
448 p
->pii_flags
&= ~PII_FLAGS_VJC_ON
;
450 p
->pii_flags
|= PII_FLAGS_VJC_NOCCID
;
452 p
->pii_flags
&= ~PII_FLAGS_VJC_NOCCID
;
454 p
->pii_flags
|= PII_FLAGS_VJC_REJ
;
456 p
->pii_flags
&= ~PII_FLAGS_VJC_REJ
;
457 bits
>>= 4; /* now max conn id. */
459 vj_compress_init(&p
->pii_sc_comp
, bits
);
460 mp
->b_datap
->db_type
= M_IOCACK
;
469 case SIOCGETU
: /* get unit number */
471 * Allocate a unit if we don't already have one.
474 if (p
== (PII
*) 0) {
479 ppp_if_init(RD(q
), p
);
482 && (mp
->b_cont
= allocb(sizeof(int), BPRI_MED
)) == NULL
)
485 *(int *) mp
->b_cont
->b_wptr
= p
->pii_ifnet
.if_unit
;
486 mp
->b_cont
->b_wptr
+= i
->ioc_count
= sizeof(int);
487 mp
->b_datap
->db_type
= M_IOCACK
;
489 i
->ioc_error
= error
;
491 mp
->b_datap
->db_type
= M_IOCNAK
;
496 case SIOCSETU
: /* set unit number */
497 if ((i
->ioc_count
== sizeof(int)) ||
498 (i
->ioc_count
== TRANSPARENT
)) {
499 unit
= *(int *)mp
->b_cont
->b_rptr
;
500 if (p
!= NULL
|| (unsigned) unit
> NUM_PPP
) {
501 mp
->b_datap
->db_type
= M_IOCNAK
;
502 i
->ioc_error
= EINVAL
;
507 if (p
->pii_flags
& PII_FLAGS_INUSE
) {
509 oq
->q_ptr
= RD(oq
)->q_ptr
= NULL
;
510 q
->q_ptr
= RD(q
)->q_ptr
= (caddr_t
) p
;
513 ppp_if_init(RD(q
), p
);
515 mp
->b_datap
->db_type
= M_IOCACK
;
524 /* catch it on the way past to set our debug flag as well */
525 if (i
->ioc_count
== TRANSPARENT
) {
526 flags
= *(int *)mp
->b_cont
->b_rptr
;
528 p
->pii_flags
|= PII_FLAGS_DEBUG
;
530 p
->pii_flags
&= ~PII_FLAGS_DEBUG
;
537 if (i
->ioc_count
== TRANSPARENT
&& p
!= NULL
) {
538 npi
= *((struct npioctl
**) mp
->b_cont
->b_rptr
);
539 switch (npi
->protocol
) {
547 i
->ioc_error
= EAFNOSUPPORT
;
549 mp
->b_datap
->db_type
= M_IOCNAK
;
553 if (i
->ioc_cmd
== SIOCSETNPMODE
) {
554 if (p
->pii_npmode
[npix
] == NPMODE_QUEUE
555 && npi
->mode
!= NPMODE_QUEUE
) {
556 for (mqnext
= &p
->pii_npq
; (mq
= *mqnext
) != NULL
; ) {
557 if (PPP_PROTOCOL(mq
->b_rptr
) != npi
->protocol
){
558 mqnext
= &mq
->b_next
;
561 *mqnext
= mq
->b_next
;
562 if (npi
->mode
== NPMODE_PASS
) {
563 putq(q
, mq
); /* q it for service routine */
568 p
->pii_npq_tail
= mqnext
;
570 p
->pii_npmode
[npix
] = npi
->mode
;
573 npi
->mode
= p
->pii_npmode
[npix
];
574 mp
->b_datap
->db_type
= M_IOCACK
;
581 default: /* unknown IOCTL call */
582 putnext(q
, mp
); /* pass it along */
587 putnext(q
, mp
); /* don't know what to do with this, so send it along*/
598 p
= (PII
*) q
->q_ptr
;
600 while ((mp
= getq(q
)) != NULL
) {
602 * we can only get M_DATA types into our Queue,
603 * due to our Put function
605 if (!canput(q
->q_next
)) {
610 /* increment count of outgoing packets */
614 /* just pass it along, nothing to do in this direction */
627 switch (mp
->b_datap
->db_type
) {
630 if (*mp
->b_rptr
& FLUSHR
)
631 flushq(q
, FLUSHDATA
);
632 putnext(q
, mp
); /* send it along too */
636 putq(q
, mp
); /* queue it for my service routine */
640 p
= (PII
*) q
->q_ptr
;
642 switch (*(u_char
*) mp
->b_rptr
) {
643 case IF_INPUT_ERROR
:
644 p
->pii_ifnet
.if_ierrors
++;
646 DLOG("ppp_if: input error inc to %d\n",
647 p
->pii_ifnet
.if_ierrors
);
649 case IF_OUTPUT_ERROR
:
650 p
->pii_ifnet
.if_oerrors
++;
652 DLOG("ppp_if: output error inc to %d\n",
653 p
->pii_ifnet
.if_oerrors
);
656 bcopy(mp
->b_rptr
+ sizeof(u_long
), &p
->pii_cstats
,
657 sizeof(struct ppp_comp_stats
));
661 putnext(q
, mp
); /* send it up to pppd */
668 putnext(q
, mp
); /* send along other message types */
676 register mblk_t
*mp
,*m0
;
678 register mblk_t
*mvjc
;
679 unsigned char *cp
, *iphdr
;
683 struct mbuf
*mb1
, *mb2
, *mbtail
;
685 int len
, xlen
, count
, s
, pklen
;
687 int address
, control
;
690 p
= (PII
*) q
->q_ptr
;
692 while ((mp
= getq(q
)) != NULL
) {
694 * we can only get M_DATA types into our Queue,
695 * due to our Put function
699 if (!canput(q
->q_next
)) {
708 dlen
= len
- PPP_HDRLEN
;
710 p
->pii_stats
.ppp_ibytes
+= len
;
713 /* make sure ppp_header is completely in first block */
714 if (mp
->b_wptr
- mp
->b_rptr
< PPP_HDRLEN
715 && !pullupmsg(mp
, PPP_HDRLEN
)) {
716 DLOG("pullupmsg failed!\n", 0);
718 p
->pii_ifnet
.if_ierrors
++;
721 m0
= mp
; /* remember first message block */
724 switch (PPP_PROTOCOL(mp
->b_rptr
)) {
726 if ((p
->pii_flags
& PII_FLAGS_VJC_REJ
)
727 || p
->pii_npmode
[NP_IP
] != NPMODE_PASS
) {
728 DLOG("VJC rejected\n", 0);
732 address
= PPP_ADDRESS(mp
->b_rptr
);
733 control
= PPP_CONTROL(mp
->b_rptr
);
734 mp
->b_rptr
+= PPP_HDRLEN
;
738 * Make sure the VJ header is in one message block.
740 xlen
= MIN(len
, MAX_VJHDR
);
741 if (mp
->b_rptr
+ xlen
> mp
->b_wptr
&& !pullupmsg(mp
, xlen
)) {
742 DLOG("pullupmsg vjc %d failed\n", xlen
);
748 * Decompress it, then get a buffer and put the
749 * decompressed header in it.
751 xlen
= vj_uncompress_tcp(mp
->b_rptr
, mp
->b_wptr
- mp
->b_rptr
,
752 len
, &p
->pii_sc_comp
, &iphdr
, &hlen
);
754 DLOG("ppp: vj_uncompress failed on type Compressed\n", 0);
758 if (!(mvjc
= allocb(hlen
+ PPP_HDRLEN
, BPRI_MED
))) {
759 DLOG("allocb mvjc failed (%d)\n", hlen
+ PPP_HDRLEN
);
763 dlen
= len
- xlen
+ hlen
;
769 bcopy(iphdr
, cp
+ PPP_HDRLEN
, hlen
);
770 mvjc
->b_wptr
= cp
+ PPP_HDRLEN
+ hlen
;
776 case PPP_VJC_UNCOMP
:
777 if ((p
->pii_flags
& PII_FLAGS_VJC_REJ
)
778 || p
->pii_npmode
[NP_IP
] != NPMODE_PASS
) {
779 DLOG("VJU rejected\n", 0);
785 * Make sure the IP header is in one message block.
787 xlen
= MIN(len
, MAX_IPHDR
+ PPP_HDRLEN
);
788 if (mp
->b_rptr
+ xlen
> mp
->b_wptr
&& !pullupmsg(mp
, xlen
)) {
789 DLOG("pullupmsg vju %d failed\n", xlen
);
795 * "Uncompress" it. Basically this just copies information
796 * into p->pii_sc_comp and restores the protocol field of
799 if (!vj_uncompress_uncomp(mp
->b_rptr
+ PPP_HDRLEN
,
801 DLOG("ppp: vj_uncompress failed on type Uncompresed\n", 0);
805 mp
->b_rptr
[3] = PPP_IP
;
810 switch (PPP_PROTOCOL(mp
->b_rptr
)) {
812 if (!canput(q
->q_next
)) {
817 p
->pii_ifnet
.if_ipackets
++;
823 * Don't let packets through until IPCP is up.
826 p
->pii_ifnet
.if_ipackets
++;
828 if (!(p
->pii_ifnet
.if_flags
& IFF_UP
)
829 || p
->pii_npmode
[NP_IP
] != NPMODE_PASS
) {
830 DLOG("pkt ignored - IP down\n", 0);
836 * Get the first mbuf and put the struct ifnet * in.
838 MGETHDR(mb1
, M_DONTWAIT
, MT_DATA
);
841 p
->pii_ifnet
.if_ierrors
++;
846 mb1
->m_pkthdr
.rcvif
= &(p
->pii_ifnet
);
847 mb1
->m_pkthdr
.len
= dlen
;
851 rptr
= mp
->b_rptr
+ PPP_HDRLEN
;
852 xlen
= mp
->b_wptr
- rptr
;
854 if (xlen
== 0) { /* move to the next mblk */
858 xlen
= mp
->b_wptr
- (rptr
= mp
->b_rptr
);
862 MGET(mb2
, M_DONTWAIT
, MT_DATA
);
864 /* if we couldn't get a buffer, drop the packet */
865 p
->pii_ifnet
.if_ierrors
++;
866 m_freem(mb1
); /* discard what we've used already */
872 mbtail
->m_next
= mb2
;
875 count
= MIN(xlen
, len
);
876 bcopy((char *) rptr
, mtod(mb2
, char *) + mb2
->m_len
, count
);
888 if (p
->pii_ifnet
.if_flags
& IFF_PROMISC
) {
889 struct mbuf
*m
= mb1
;
894 } while (m
= m
->m_next
);
895 nif
.nif_bodylen
= len
- sizeof(struct ifnet
*);
896 mb1
->m_off
+= sizeof(struct ifnet
*);
897 snit_intr(&p
->pii_ifnet
, mb1
, &nif
);
898 mb1
->m_off
-= sizeof(struct ifnet
*);
902 if (IF_QFULL(&ipintrq)) {
904 p->pii_ifnet.if_ierrors++;
909 find_input_type(0x0800, mb1
, ifp
, 0);
914 /* ifp output procedure */
916 ppp_output(ifp
, m0
, dst
)
919 struct sockaddr
*dst
;
921 register PII
*p
= &pii
[ifp
->if_unit
];
933 if (!(ifp
->if_flags
& IFF_UP
)) {
938 switch (dst
->sa_family
) {
942 if (ifp
->if_flags
& IFF_PROMISC
) {
948 } while (m
= m
->m_next
);
949 nif
.nif_bodylen
= len
;
950 snit_intr(ifp
, m0
, &nif
);
954 npmode
= p
->pii_npmode
[NP_IP
];
959 DLOG("ppp: af%d not supported\n", dst
->sa_family
);
960 error
= EAFNOSUPPORT
;
964 if (!p
->pii_writeq
) {
965 DLOG("ppp_if%d: no queue\n", p
- pii
);
966 error
= EHOSTUNREACH
;
979 if ((protocol
== PPP_IP
) && (p
->pii_flags
& PII_FLAGS_VJC_ON
)) {
980 register struct ip
*ip
;
981 ip
= mtod(m0
, struct ip
*);
982 if (ip
->ip_p
== IPPROTO_TCP
) {
983 type
= vj_compress_tcp(ip
, m0
->m_len
, &p
->pii_sc_comp
,
984 !(p
->pii_flags
& PII_FLAGS_VJC_NOCCID
),
987 case TYPE_UNCOMPRESSED_TCP
:
988 protocol
= PPP_VJC_UNCOMP
;
990 case TYPE_COMPRESSED_TCP
:
991 protocol
= PPP_VJC_COMP
;
992 len
= vjhdr
- (u_char
*) ip
;
1002 for (m1
= m0
; m1
; m1
= m1
->m_next
)
1005 if (!(mp
= allocb(len
, BPRI_MED
))) {
1006 DLOG("ppp_if%d: allocb failed\n", p
- pii
);
1012 p
->pii_stats
.ppp_obytes
+= len
;
1015 *mp
->b_wptr
++ = PPP_ALLSTATIONS
;
1016 *mp
->b_wptr
++ = PPP_UI
;
1018 *mp
->b_wptr
++ = protocol
;
1019 for (m1
= m0
; m1
; m1
= m1
->m_next
) { /* copy all data */
1020 bcopy(mtod(m1
, char *), (char *) mp
->b_wptr
, m1
->m_len
);
1021 mp
->b_wptr
+= m1
->m_len
;
1024 p
->pii_ifnet
.if_opackets
++;
1025 DLOG("ppp_output npmode is %d\n",npmode
);
1026 if (npmode
== NPMODE_PASS
) {
1027 putq(p
->pii_writeq
, mp
);
1030 *p
->pii_npq_tail
= mp
;
1031 p
->pii_npq_tail
= &mp
;
1038 p
->pii_ifnet
.if_oerrors
++;
1044 * if_ ioctl requests
1046 ppp_ioctl(ifp
, cmd
, data
)
1047 register struct ifnet
*ifp
;
1051 register struct ifaddr
*ifa
= (struct ifaddr
*) data
;
1052 register struct ifreq
*ifr
= (struct ifreq
*) data
;
1053 struct ppp_stats
*psp
;
1054 struct ppp_comp_stats
*pcp
;
1061 /* This happens every time IFF_PROMISC has been changed. */
1069 /* clear the flags that can be cleared */
1070 ifp
->if_flags
&= (IFF_CANTCHANGE
);
1071 /* or in the flags that can be changed */
1072 ifp
->if_flags
|= (ifr
->ifr_flags
& ~IFF_CANTCHANGE
);
1076 ifr
->ifr_flags
= ifp
->if_flags
;
1080 if( ifa
->ifa_addr
->sa_family
!= AF_INET
)
1081 error
= EAFNOSUPPORT
;
1084 case SIOCSIFDSTADDR
:
1085 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
1086 error
= EAFNOSUPPORT
;
1094 if (ifr
->ifr_mtu
> MAX_PKTSIZE
- PPP_FRAMING
) {
1098 ifp
->if_mtu
= ifr
->ifr_mtu
;
1102 ifr
->ifr_mtu
= ifp
->if_mtu
;
1106 p
= &pii
[ifp
->if_unit
];
1107 psp
= (struct ppp_stats
*) &((struct ifpppstatsreq
*)data
)->stats
;
1108 bzero(psp
, sizeof(struct ppp_stats
));
1110 psp
->p
= p
->pii_stats
;
1112 #if defined(VJC) && !defined(VJ_NO_STATS)
1113 psp
->vj
= p
->pii_sc_comp
.stats
;
1117 case SIOCGPPPCSTATS
:
1118 p
= &pii
[ifp
->if_unit
];
1119 bzero(&p
->pii_cstats
, sizeof(struct ppp_comp_stats
));
1121 /* Make a message to send on the interface's write stream */
1124 putctl1(q
, M_CTL
, IF_GET_CSTATS
);
1126 * We assume the message gets passed along immediately, so
1127 * by the time the putctl1 returns, the request has been
1128 * processed, the values returned and p->pii_cstats has
1129 * been updated. If not, we just get zeroes.
1132 pcp
= (struct ppp_comp_stats
*)&((struct ifpppcstatsreq
*)data
)->stats
;
1133 bcopy(&p
->pii_cstats
, pcp
, sizeof(struct ppp_comp_stats
));