CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / modules / if_ppp.c
blob8dde067203781691c6684f30255fc9d60bb780a5
1 /*
2 * if_ppp.c - a network interface connected to a STREAMS module.
4 * Copyright (c) 1994 The Australian National University.
5 * All rights reserved.
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.
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 HAVE BEEN ADVISED OF THE POSSIBILITY
18 * OF SUCH DAMAGE.
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.
27 * $Id: if_ppp.c,v 1.1.1.4 2003/10/14 08:09:53 sparq Exp $
31 * This file is used under SunOS 4 and Digital UNIX.
33 * This file provides the glue between PPP and IP.
36 #define INET 1
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/errno.h>
41 #include <sys/mbuf.h>
42 #include <sys/socket.h>
43 #include <net/if.h>
44 #include <net/netisr.h>
45 #include <net/ppp_defs.h>
46 #include <net/pppio.h>
47 #include <netinet/in.h>
48 #include <netinet/in_var.h>
49 #ifdef __osf__
50 #include <sys/ioctl.h>
51 #include <net/if_types.h>
52 #else
53 #include <sys/sockio.h>
54 #endif
55 #include "ppp_mod.h"
57 #include <sys/stream.h>
59 #ifdef SNIT_SUPPORT
60 #include <sys/time.h>
61 #include <net/nit_if.h>
62 #include <netinet/if_ether.h>
63 #endif
65 #ifdef __osf__
66 #define SIOCSIFMTU SIOCSIPMTU
67 #define SIOCGIFMTU SIOCRIPMTU
68 #define IFA_ADDR(ifa) (*(ifa)->ifa_addr)
69 #else
70 #define IFA_ADDR(ifa) ((ifa)->ifa_addr)
71 #endif
73 #define ifr_mtu ifr_metric
75 static int if_ppp_open __P((queue_t *, int, int, int));
76 static int if_ppp_close __P((queue_t *, int));
77 static int if_ppp_wput __P((queue_t *, mblk_t *));
78 static int if_ppp_rput __P((queue_t *, mblk_t *));
80 #define PPP_IF_ID 0x8021
81 static struct module_info minfo = {
82 PPP_IF_ID, "if_ppp", 0, INFPSZ, 4096, 128
85 static struct qinit rinit = {
86 if_ppp_rput, NULL, if_ppp_open, if_ppp_close, NULL, &minfo, NULL
89 static struct qinit winit = {
90 if_ppp_wput, NULL, NULL, NULL, NULL, &minfo, NULL
93 struct streamtab if_pppinfo = {
94 &rinit, &winit, NULL, NULL
97 typedef struct if_ppp_state {
98 int unit;
99 queue_t *q;
100 int flags;
101 } if_ppp_t;
103 /* Values for flags */
104 #define DBGLOG 1
106 static int if_ppp_count; /* Number of currently-active streams */
108 static int ppp_nalloc; /* Number of elements of ifs and states */
109 static struct ifnet **ifs; /* Array of pointers to interface structs */
110 static if_ppp_t **states; /* Array of pointers to state structs */
112 static int if_ppp_output __P((struct ifnet *, struct mbuf *,
113 struct sockaddr *));
114 static int if_ppp_ioctl __P((struct ifnet *, u_int, caddr_t));
115 static struct mbuf *make_mbufs __P((mblk_t *, int));
116 static mblk_t *make_message __P((struct mbuf *, int));
118 #ifdef SNIT_SUPPORT
119 /* Fake ether header for SNIT */
120 static struct ether_header snit_ehdr = {{0}, {0}, ETHERTYPE_IP};
121 #endif
123 #ifndef __osf__
124 static void ppp_if_detach __P((struct ifnet *));
127 * Detach all the interfaces before unloading.
128 * Not sure this works.
131 if_ppp_unload()
133 int i;
135 if (if_ppp_count > 0)
136 return EBUSY;
137 for (i = 0; i < ppp_nalloc; ++i)
138 if (ifs[i] != 0)
139 ppp_if_detach(ifs[i]);
140 if (ifs) {
141 FREE(ifs, ppp_nalloc * sizeof (struct ifnet *));
142 FREE(states, ppp_nalloc * sizeof (struct if_ppp_t *));
144 ppp_nalloc = 0;
145 return 0;
147 #endif /* __osf__ */
150 * STREAMS module entry points.
152 static int
153 if_ppp_open(q, dev, flag, sflag)
154 queue_t *q;
155 int dev;
156 int flag, sflag;
158 if_ppp_t *sp;
160 if (q->q_ptr == 0) {
161 sp = (if_ppp_t *) ALLOC_SLEEP(sizeof (if_ppp_t));
162 if (sp == 0)
163 return OPENFAIL;
164 bzero(sp, sizeof (if_ppp_t));
165 q->q_ptr = (caddr_t) sp;
166 WR(q)->q_ptr = (caddr_t) sp;
167 sp->unit = -1; /* no interface unit attached at present */
168 sp->q = WR(q);
169 sp->flags = 0;
170 ++if_ppp_count;
172 return 0;
175 static int
176 if_ppp_close(q, flag)
177 queue_t *q;
178 int flag;
180 if_ppp_t *sp;
181 struct ifnet *ifp;
183 sp = (if_ppp_t *) q->q_ptr;
184 if (sp != 0) {
185 if (sp->flags & DBGLOG)
186 printf("if_ppp closed, q=%x sp=%x\n", q, sp);
187 if (sp->unit >= 0) {
188 if (sp->unit < ppp_nalloc) {
189 states[sp->unit] = 0;
190 ifp = ifs[sp->unit];
191 if (ifp != 0)
192 ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
193 #ifdef DEBUG
194 } else {
195 printf("if_ppp: unit %d nonexistent!\n", sp->unit);
196 #endif
199 FREE(sp, sizeof (if_ppp_t));
200 --if_ppp_count;
202 return 0;
205 static int
206 if_ppp_wput(q, mp)
207 queue_t *q;
208 mblk_t *mp;
210 if_ppp_t *sp;
211 struct iocblk *iop;
212 int error, unit;
213 struct ifnet *ifp;
215 sp = (if_ppp_t *) q->q_ptr;
216 switch (mp->b_datap->db_type) {
217 case M_DATA:
219 * Now why would we be getting data coming in here??
221 if (sp->flags & DBGLOG)
222 printf("if_ppp: got M_DATA len=%d\n", msgdsize(mp));
223 freemsg(mp);
224 break;
226 case M_IOCTL:
227 iop = (struct iocblk *) mp->b_rptr;
228 error = EINVAL;
230 if (sp->flags & DBGLOG)
231 printf("if_ppp: got ioctl cmd=%x count=%d\n",
232 iop->ioc_cmd, iop->ioc_count);
234 switch (iop->ioc_cmd) {
235 case PPPIO_NEWPPA: /* well almost */
236 if (iop->ioc_count != sizeof(int) || sp->unit >= 0)
237 break;
238 if ((error = NOTSUSER()) != 0)
239 break;
240 unit = *(int *)mp->b_cont->b_rptr;
242 /* Check that this unit isn't already in use */
243 if (unit < ppp_nalloc && states[unit] != 0) {
244 error = EADDRINUSE;
245 break;
248 /* Extend ifs and states arrays if necessary. */
249 error = ENOSR;
250 if (unit >= ppp_nalloc) {
251 int newn;
252 struct ifnet **newifs;
253 if_ppp_t **newstates;
255 newn = unit + 4;
256 if (sp->flags & DBGLOG)
257 printf("if_ppp: extending ifs to %d\n", newn);
258 newifs = (struct ifnet **)
259 ALLOC_NOSLEEP(newn * sizeof (struct ifnet *));
260 if (newifs == 0)
261 break;
262 bzero(newifs, newn * sizeof (struct ifnet *));
263 newstates = (if_ppp_t **)
264 ALLOC_NOSLEEP(newn * sizeof (struct if_ppp_t *));
265 if (newstates == 0) {
266 FREE(newifs, newn * sizeof (struct ifnet *));
267 break;
269 bzero(newstates, newn * sizeof (struct if_ppp_t *));
270 bcopy(ifs, newifs, ppp_nalloc * sizeof(struct ifnet *));
271 bcopy(states, newstates, ppp_nalloc * sizeof(if_ppp_t *));
272 if (ifs) {
273 FREE(ifs, ppp_nalloc * sizeof(struct ifnet *));
274 FREE(states, ppp_nalloc * sizeof(if_ppp_t *));
276 ifs = newifs;
277 states = newstates;
278 ppp_nalloc = newn;
281 /* Allocate a new ifnet struct if necessary. */
282 ifp = ifs[unit];
283 if (ifp == 0) {
284 ifp = (struct ifnet *) ALLOC_NOSLEEP(sizeof (struct ifnet));
285 if (ifp == 0)
286 break;
287 bzero(ifp, sizeof (struct ifnet));
288 ifs[unit] = ifp;
289 ifp->if_name = "ppp";
290 ifp->if_unit = unit;
291 ifp->if_mtu = PPP_MTU;
292 ifp->if_flags = IFF_POINTOPOINT | IFF_RUNNING;
293 #ifndef __osf__
294 #ifdef IFF_MULTICAST
295 ifp->if_flags |= IFF_MULTICAST;
296 #endif
297 #endif /* __osf__ */
298 ifp->if_output = if_ppp_output;
299 #ifdef __osf__
300 ifp->if_version = "Point-to-Point Protocol, version 2.3.11";
301 ifp->if_mediamtu = PPP_MTU;
302 ifp->if_type = IFT_PPP;
303 ifp->if_hdrlen = PPP_HDRLEN;
304 ifp->if_addrlen = 0;
305 ifp->if_flags |= IFF_NOARP | IFF_SIMPLEX | IFF_NOTRAILERS;
306 #ifdef IFF_VAR_MTU
307 ifp->if_flags |= IFF_VAR_MTU;
308 #endif
309 #ifdef NETMASTERCPU
310 ifp->if_affinity = NETMASTERCPU;
311 #endif
312 #endif
313 ifp->if_ioctl = if_ppp_ioctl;
314 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
315 if_attach(ifp);
316 if (sp->flags & DBGLOG)
317 printf("if_ppp: created unit %d\n", unit);
318 } else {
319 ifp->if_mtu = PPP_MTU;
320 ifp->if_flags |= IFF_RUNNING;
323 states[unit] = sp;
324 sp->unit = unit;
326 error = 0;
327 iop->ioc_count = 0;
328 if (sp->flags & DBGLOG)
329 printf("if_ppp: attached unit %d, sp=%x q=%x\n", unit,
330 sp, sp->q);
331 break;
333 case PPPIO_DEBUG:
334 error = -1;
335 if (iop->ioc_count == sizeof(int)) {
336 if (*(int *)mp->b_cont->b_rptr == PPPDBG_LOG + PPPDBG_IF) {
337 printf("if_ppp: debug log enabled, q=%x sp=%x\n", q, sp);
338 sp->flags |= DBGLOG;
339 error = 0;
340 iop->ioc_count = 0;
343 break;
345 default:
346 error = -1;
347 break;
350 if (sp->flags & DBGLOG)
351 printf("if_ppp: ioctl result %d\n", error);
352 if (error < 0)
353 putnext(q, mp);
354 else if (error == 0) {
355 mp->b_datap->db_type = M_IOCACK;
356 qreply(q, mp);
357 } else {
358 mp->b_datap->db_type = M_IOCNAK;
359 iop->ioc_count = 0;
360 iop->ioc_error = error;
361 qreply(q, mp);
363 break;
365 default:
366 putnext(q, mp);
368 return 0;
371 static int
372 if_ppp_rput(q, mp)
373 queue_t *q;
374 mblk_t *mp;
376 if_ppp_t *sp;
377 int proto, s;
378 struct mbuf *mb;
379 struct ifqueue *inq;
380 struct ifnet *ifp;
381 int len;
383 sp = (if_ppp_t *) q->q_ptr;
384 switch (mp->b_datap->db_type) {
385 case M_DATA:
387 * Convert the message into an mbuf chain
388 * and inject it into the network code.
390 if (sp->flags & DBGLOG)
391 printf("if_ppp: rput pkt len %d data %x %x %x %x %x %x %x %x\n",
392 msgdsize(mp), mp->b_rptr[0], mp->b_rptr[1], mp->b_rptr[2],
393 mp->b_rptr[3], mp->b_rptr[4], mp->b_rptr[5], mp->b_rptr[6],
394 mp->b_rptr[7]);
396 if (sp->unit < 0) {
397 freemsg(mp);
398 break;
400 if (sp->unit >= ppp_nalloc || (ifp = ifs[sp->unit]) == 0) {
401 #ifdef DEBUG
402 printf("if_ppp: no unit %d!\n", sp->unit);
403 #endif
404 freemsg(mp);
405 break;
408 if ((ifp->if_flags & IFF_UP) == 0) {
409 freemsg(mp);
410 break;
412 ++ifp->if_ipackets;
414 proto = PPP_PROTOCOL(mp->b_rptr);
415 adjmsg(mp, PPP_HDRLEN);
416 len = msgdsize(mp);
417 mb = make_mbufs(mp, sizeof(struct ifnet *));
418 freemsg(mp);
419 if (mb == NULL) {
420 if (sp->flags & DBGLOG)
421 printf("if_ppp%d: make_mbufs failed\n", ifp->if_unit);
422 ++ifp->if_ierrors;
423 break;
426 #ifdef SNIT_SUPPORT
427 if (proto == PPP_IP && (ifp->if_flags & IFF_PROMISC)) {
428 struct nit_if nif;
430 nif.nif_header = (caddr_t) &snit_ehdr;
431 nif.nif_hdrlen = sizeof(snit_ehdr);
432 nif.nif_bodylen = len;
433 nif.nif_promisc = 0;
434 snit_intr(ifp, mb, &nif);
436 #endif
439 * For Digital UNIX, there's space set aside in the header mbuf
440 * for the interface info.
442 * For Sun it's smuggled around via a pointer at the front of the mbuf.
444 #ifdef __osf__
445 mb->m_pkthdr.rcvif = ifp;
446 mb->m_pkthdr.len = len;
447 #else
448 mb->m_off -= sizeof(struct ifnet *);
449 mb->m_len += sizeof(struct ifnet *);
450 *mtod(mb, struct ifnet **) = ifp;
451 #endif
453 inq = 0;
454 switch (proto) {
455 case PPP_IP:
456 inq = &ipintrq;
457 schednetisr(NETISR_IP);
460 if (inq != 0) {
461 s = splhigh();
462 if (IF_QFULL(inq)) {
463 IF_DROP(inq);
464 ++ifp->if_ierrors;
465 if (sp->flags & DBGLOG)
466 printf("if_ppp: inq full, proto=%x\n", proto);
467 m_freem(mb);
468 } else {
469 IF_ENQUEUE(inq, mb);
471 splx(s);
472 } else {
473 if (sp->flags & DBGLOG)
474 printf("if_ppp%d: proto=%x?\n", ifp->if_unit, proto);
475 ++ifp->if_ierrors;
476 m_freem(mb);
478 break;
480 default:
481 putnext(q, mp);
483 return 0;
487 * Network code wants to output a packet.
488 * Turn it into a STREAMS message and send it down.
490 static int
491 if_ppp_output(ifp, m0, dst)
492 struct ifnet *ifp;
493 struct mbuf *m0;
494 struct sockaddr *dst;
496 mblk_t *mp;
497 int proto, s;
498 if_ppp_t *sp;
499 u_char *p;
501 if ((ifp->if_flags & IFF_UP) == 0) {
502 m_freem(m0);
503 return ENETDOWN;
506 if ((unsigned)ifp->if_unit >= ppp_nalloc) {
507 #ifdef DEBUG
508 printf("if_ppp_output: unit %d?\n", ifp->if_unit);
509 #endif
510 m_freem(m0);
511 return EINVAL;
513 sp = states[ifp->if_unit];
514 if (sp == 0) {
515 #ifdef DEBUG
516 printf("if_ppp_output: no queue?\n");
517 #endif
518 m_freem(m0);
519 return ENETDOWN;
522 if (sp->flags & DBGLOG) {
523 p = mtod(m0, u_char *);
524 printf("if_ppp_output%d: af=%d data=%x %x %x %x %x %x %x %x q=%x\n",
525 ifp->if_unit, dst->sa_family, p[0], p[1], p[2], p[3], p[4],
526 p[5], p[6], p[7], sp->q);
529 switch (dst->sa_family) {
530 case AF_INET:
531 proto = PPP_IP;
532 #ifdef SNIT_SUPPORT
533 if (ifp->if_flags & IFF_PROMISC) {
534 struct nit_if nif;
535 struct mbuf *m;
536 int len;
538 for (len = 0, m = m0; m != NULL; m = m->m_next)
539 len += m->m_len;
540 nif.nif_header = (caddr_t) &snit_ehdr;
541 nif.nif_hdrlen = sizeof(snit_ehdr);
542 nif.nif_bodylen = len;
543 nif.nif_promisc = 0;
544 snit_intr(ifp, m0, &nif);
546 #endif
547 break;
549 default:
550 m_freem(m0);
551 return EAFNOSUPPORT;
554 ++ifp->if_opackets;
555 mp = make_message(m0, PPP_HDRLEN);
556 m_freem(m0);
557 if (mp == 0) {
558 ++ifp->if_oerrors;
559 return ENOBUFS;
561 mp->b_rptr -= PPP_HDRLEN;
562 mp->b_rptr[0] = PPP_ALLSTATIONS;
563 mp->b_rptr[1] = PPP_UI;
564 mp->b_rptr[2] = proto >> 8;
565 mp->b_rptr[3] = proto;
567 s = splstr();
568 if (sp->flags & DBGLOG)
569 printf("if_ppp: putnext(%x, %x), r=%x w=%x p=%x\n",
570 sp->q, mp, mp->b_rptr, mp->b_wptr, proto);
571 putnext(sp->q, mp);
572 splx(s);
574 return 0;
578 * Socket ioctl routine for ppp interfaces.
580 static int
581 if_ppp_ioctl(ifp, cmd, data)
582 struct ifnet *ifp;
583 u_int cmd;
584 caddr_t data;
586 int s, error;
587 struct ifreq *ifr = (struct ifreq *) data;
588 struct ifaddr *ifa = (struct ifaddr *) data;
589 u_short mtu;
591 error = 0;
592 s = splimp();
593 switch (cmd) {
594 case SIOCSIFFLAGS:
595 if ((ifp->if_flags & IFF_RUNNING) == 0)
596 ifp->if_flags &= ~IFF_UP;
597 break;
599 case SIOCSIFADDR:
600 if (IFA_ADDR(ifa).sa_family != AF_INET)
601 error = EAFNOSUPPORT;
602 break;
604 case SIOCSIFDSTADDR:
605 if (IFA_ADDR(ifa).sa_family != AF_INET)
606 error = EAFNOSUPPORT;
607 break;
609 case SIOCSIFMTU:
610 if ((error = NOTSUSER()) != 0)
611 break;
612 #ifdef __osf__
613 /* this hack is necessary because ifioctl checks ifr_data
614 * in 4.0 and 5.0, but ifr_data and ifr_metric overlay each
615 * other in the definition of struct ifreq so pppd can't set both.
617 bcopy(ifr->ifr_data, &mtu, sizeof (u_short));
618 ifr->ifr_mtu = mtu;
619 #endif
621 if (ifr->ifr_mtu < PPP_MINMTU || ifr->ifr_mtu > PPP_MAXMTU) {
622 error = EINVAL;
623 break;
625 ifp->if_mtu = ifr->ifr_mtu;
626 break;
628 case SIOCGIFMTU:
629 ifr->ifr_mtu = ifp->if_mtu;
630 break;
632 case SIOCADDMULTI:
633 case SIOCDELMULTI:
634 switch(ifr->ifr_addr.sa_family) {
635 case AF_INET:
636 break;
637 default:
638 error = EAFNOSUPPORT;
639 break;
641 break;
643 default:
644 error = EINVAL;
646 splx(s);
647 return (error);
651 * Turn a STREAMS message into an mbuf chain.
653 static struct mbuf *
654 make_mbufs(mp, off)
655 mblk_t *mp;
656 int off;
658 struct mbuf *head, **prevp, *m;
659 int len, space, n;
660 unsigned char *cp, *dp;
662 len = msgdsize(mp);
663 if (len == 0)
664 return 0;
665 prevp = &head;
666 space = 0;
667 cp = mp->b_rptr;
668 #ifdef __osf__
669 MGETHDR(m, M_DONTWAIT, MT_DATA);
670 m->m_len = 0;
671 space = MHLEN;
672 *prevp = m;
673 prevp = &m->m_next;
674 dp = mtod(m, unsigned char *);
675 len -= space;
676 off = 0;
677 #endif
678 for (;;) {
679 while (cp >= mp->b_wptr) {
680 mp = mp->b_cont;
681 if (mp == 0) {
682 *prevp = 0;
683 return head;
685 cp = mp->b_rptr;
687 n = mp->b_wptr - cp;
688 if (space == 0) {
689 MGET(m, M_DONTWAIT, MT_DATA);
690 *prevp = m;
691 if (m == 0) {
692 if (head != 0)
693 m_freem(head);
694 return 0;
696 if (len + off > 2 * MLEN) {
697 #ifdef __osf__
698 MCLGET(m, M_DONTWAIT);
699 #else
700 MCLGET(m);
701 #endif
703 #ifdef __osf__
704 space = ((m->m_flags & M_EXT) ? MCLBYTES : MLEN);
705 #else
706 space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;
707 m->m_off += off;
708 #endif
709 m->m_len = 0;
710 len -= space;
711 dp = mtod(m, unsigned char *);
712 off = 0;
713 prevp = &m->m_next;
715 if (n > space)
716 n = space;
717 bcopy(cp, dp, n);
718 cp += n;
719 dp += n;
720 space -= n;
721 m->m_len += n;
726 * Turn an mbuf chain into a STREAMS message.
728 #define ALLOCB_MAX 4096
730 static mblk_t *
731 make_message(m, off)
732 struct mbuf *m;
733 int off;
735 mblk_t *head, **prevp, *mp;
736 int len, space, n, nb;
737 unsigned char *cp, *dp;
738 struct mbuf *nm;
740 len = 0;
741 for (nm = m; nm != 0; nm = nm->m_next)
742 len += nm->m_len;
743 prevp = &head;
744 space = 0;
745 cp = mtod(m, unsigned char *);
746 nb = m->m_len;
747 for (;;) {
748 while (nb <= 0) {
749 m = m->m_next;
750 if (m == 0) {
751 *prevp = 0;
752 return head;
754 cp = mtod(m, unsigned char *);
755 nb = m->m_len;
757 if (space == 0) {
758 space = len + off;
759 if (space > ALLOCB_MAX)
760 space = ALLOCB_MAX;
761 mp = allocb(space, BPRI_LO);
762 *prevp = mp;
763 if (mp == 0) {
764 if (head != 0)
765 freemsg(head);
766 return 0;
768 dp = mp->b_rptr += off;
769 space -= off;
770 len -= space;
771 off = 0;
772 prevp = &mp->b_cont;
774 n = nb < space? nb: space;
775 bcopy(cp, dp, n);
776 cp += n;
777 dp += n;
778 nb -= n;
779 space -= n;
780 mp->b_wptr = dp;
785 * Digital UNIX doesn't allow for removing ifnet structures
786 * from the list. But then we're not using this as a loadable
787 * module anyway, so that's OK.
789 * Under SunOS, this should allow the module to be unloaded.
790 * Unfortunately, it doesn't seem to detach all the references,
791 * so your system may well crash after you unload this module :-(
793 #ifndef __osf__
796 * Remove an interface from the system.
797 * This routine contains magic.
799 #include <net/route.h>
800 #include <netinet/in_pcb.h>
801 #include <netinet/ip_var.h>
802 #include <netinet/tcp.h>
803 #include <netinet/tcp_timer.h>
804 #include <netinet/tcp_var.h>
805 #include <netinet/udp.h>
806 #include <netinet/udp_var.h>
808 static void
809 ppp_if_detach(ifp)
810 struct ifnet *ifp;
812 int s;
813 struct inpcb *pcb;
814 struct ifaddr *ifa;
815 struct in_ifaddr **inap;
816 struct ifnet **ifpp;
818 s = splhigh();
821 * Clear the interface from any routes currently cached in
822 * TCP or UDP protocol control blocks.
824 for (pcb = tcb.inp_next; pcb != &tcb; pcb = pcb->inp_next)
825 if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
826 in_losing(pcb);
827 for (pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next)
828 if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
829 in_losing(pcb);
832 * Delete routes through all addresses of the interface.
834 for (ifa = ifp->if_addrlist; ifa != 0; ifa = ifa->ifa_next) {
835 rtinit(ifa, ifa, SIOCDELRT, RTF_HOST);
836 rtinit(ifa, ifa, SIOCDELRT, 0);
840 * Unlink the interface's address(es) from the in_ifaddr list.
842 for (inap = &in_ifaddr; *inap != 0; ) {
843 if ((*inap)->ia_ifa.ifa_ifp == ifp)
844 *inap = (*inap)->ia_next;
845 else
846 inap = &(*inap)->ia_next;
850 * Delete the interface from the ifnet list.
852 for (ifpp = &ifnet; (*ifpp) != 0; ) {
853 if (*ifpp == ifp)
854 break;
855 ifpp = &(*ifpp)->if_next;
857 if (*ifpp == 0)
858 printf("couldn't find interface ppp%d in ifnet list\n", ifp->if_unit);
859 else
860 *ifpp = ifp->if_next;
862 splx(s);
865 #endif /* __osf__ */