]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ppp/mp.c
This commit was generated by cvs2svn to compensate for changes in r80486,
[FreeBSD/FreeBSD.git] / usr.sbin / ppp / mp.c
1 /*-
2  * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <netinet/in.h>
31 #include <netinet/in_systm.h>
32 #include <netinet/ip.h>
33 #include <arpa/inet.h>
34 #include <net/if_dl.h>
35 #include <sys/socket.h>
36 #include <sys/un.h>
37
38 #include <errno.h>
39 #include <paths.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/stat.h>
44 #include <termios.h>
45 #include <unistd.h>
46
47 #include "layer.h"
48 #ifndef NONAT
49 #include "nat_cmd.h"
50 #endif
51 #include "vjcomp.h"
52 #include "ua.h"
53 #include "defs.h"
54 #include "command.h"
55 #include "mbuf.h"
56 #include "log.h"
57 #include "timer.h"
58 #include "fsm.h"
59 #include "iplist.h"
60 #include "throughput.h"
61 #include "slcompress.h"
62 #include "lqr.h"
63 #include "hdlc.h"
64 #include "ipcp.h"
65 #include "auth.h"
66 #include "lcp.h"
67 #include "async.h"
68 #include "ccp.h"
69 #include "link.h"
70 #include "descriptor.h"
71 #include "physical.h"
72 #include "chat.h"
73 #include "proto.h"
74 #include "filter.h"
75 #include "mp.h"
76 #include "chap.h"
77 #include "cbcp.h"
78 #include "datalink.h"
79 #ifndef NORADIUS
80 #include "radius.h"
81 #endif
82 #include "bundle.h"
83 #include "ip.h"
84 #include "prompt.h"
85 #include "id.h"
86 #include "arp.h"
87
88 void
89 peerid_Init(struct peerid *peer)
90 {
91   peer->enddisc.class = 0;
92   *peer->enddisc.address = '\0';
93   peer->enddisc.len = 0;
94   *peer->authname = '\0';
95 }
96
97 int
98 peerid_Equal(const struct peerid *p1, const struct peerid *p2)
99 {
100   return !strcmp(p1->authname, p2->authname) &&
101          p1->enddisc.class == p2->enddisc.class &&
102          p1->enddisc.len == p2->enddisc.len &&
103          !memcmp(p1->enddisc.address, p2->enddisc.address, p1->enddisc.len);
104 }
105
106 static u_int32_t
107 inc_seq(unsigned is12bit, u_int32_t seq)
108 {
109   seq++;
110   if (is12bit) {
111     if (seq & 0xfffff000)
112       seq = 0;
113   } else if (seq & 0xff000000)
114     seq = 0;
115   return seq;
116 }
117
118 static int
119 isbefore(unsigned is12bit, u_int32_t seq1, u_int32_t seq2)
120 {
121   u_int32_t max = (is12bit ? 0xfff : 0xffffff) - 0x200;
122
123   if (seq1 > max) {
124     if (seq2 < 0x200 || seq2 > seq1)
125       return 1;
126   } else if ((seq1 > 0x200 || seq2 <= max) && seq1 < seq2)
127     return 1;
128
129   return 0;
130 }
131
132 static int
133 mp_ReadHeader(struct mp *mp, struct mbuf *m, struct mp_header *header)
134 {
135   if (mp->local_is12bit) {
136     u_int16_t val;
137
138     ua_ntohs(MBUF_CTOP(m), &val);
139     if (val & 0x3000) {
140       log_Printf(LogWARN, "Oops - MP header without required zero bits\n");
141       return 0;
142     }
143     header->begin = val & 0x8000 ? 1 : 0;
144     header->end = val & 0x4000 ? 1 : 0;
145     header->seq = val & 0x0fff;
146     return 2;
147   } else {
148     ua_ntohl(MBUF_CTOP(m), &header->seq);
149     if (header->seq & 0x3f000000) {
150       log_Printf(LogWARN, "Oops - MP header without required zero bits\n");
151       return 0;
152     }
153     header->begin = header->seq & 0x80000000 ? 1 : 0;
154     header->end = header->seq & 0x40000000 ? 1 : 0;
155     header->seq &= 0x00ffffff;
156     return 4;
157   }
158 }
159
160 static void
161 mp_LayerStart(void *v, struct fsm *fp)
162 {
163   /* The given FSM (ccp) is about to start up ! */
164 }
165
166 static void
167 mp_LayerUp(void *v, struct fsm *fp)
168 {
169   /* The given fsm (ccp) is now up */
170
171   bundle_CalculateBandwidth(fp->bundle);        /* Against ccp_MTUOverhead */
172 }
173
174 static void
175 mp_LayerDown(void *v, struct fsm *fp)
176 {
177   /* The given FSM (ccp) has been told to come down */
178 }
179
180 static void
181 mp_LayerFinish(void *v, struct fsm *fp)
182 {
183   /* The given fsm (ccp) is now down */
184   if (fp->state == ST_CLOSED && fp->open_mode == OPEN_PASSIVE)
185     fsm_Open(fp);               /* CCP goes to ST_STOPPED */
186 }
187
188 static void
189 mp_UpDown(void *v)
190 {
191   struct mp *mp = (struct mp *)v;
192   int percent;
193
194   percent = MAX(mp->link.stats.total.in.OctetsPerSecond,
195                 mp->link.stats.total.out.OctetsPerSecond) * 800 /
196             mp->bundle->bandwidth;
197   if (percent >= mp->cfg.autoload.max) {
198     log_Printf(LogDEBUG, "%d%% saturation - bring a link up ?\n", percent);
199     bundle_AutoAdjust(mp->bundle, percent, AUTO_UP);
200   } else if (percent <= mp->cfg.autoload.min) {
201     log_Printf(LogDEBUG, "%d%% saturation - bring a link down ?\n", percent);
202     bundle_AutoAdjust(mp->bundle, percent, AUTO_DOWN);
203   }
204 }
205
206 void
207 mp_StopAutoloadTimer(struct mp *mp)
208 {
209   throughput_stop(&mp->link.stats.total);
210 }
211
212 void
213 mp_CheckAutoloadTimer(struct mp *mp)
214 {
215   if (mp->link.stats.total.SamplePeriod != mp->cfg.autoload.period) {
216     throughput_destroy(&mp->link.stats.total);
217     throughput_init(&mp->link.stats.total, mp->cfg.autoload.period);
218     throughput_callback(&mp->link.stats.total, mp_UpDown, mp);
219   }
220
221   if (bundle_WantAutoloadTimer(mp->bundle))
222     throughput_start(&mp->link.stats.total, "MP throughput", 1);
223   else
224     mp_StopAutoloadTimer(mp);
225 }
226
227 void
228 mp_RestartAutoloadTimer(struct mp *mp)
229 {
230   if (mp->link.stats.total.SamplePeriod != mp->cfg.autoload.period)
231     mp_CheckAutoloadTimer(mp);
232   else
233     throughput_clear(&mp->link.stats.total, THROUGHPUT_OVERALL, NULL);
234 }
235
236 void
237 mp_Init(struct mp *mp, struct bundle *bundle)
238 {
239   mp->peer_is12bit = mp->local_is12bit = 0;
240   mp->peer_mrru = mp->local_mrru = 0;
241
242   peerid_Init(&mp->peer);
243
244   mp->out.seq = 0;
245   mp->out.link = 0;
246   mp->seq.min_in = 0;
247   mp->seq.next_in = 0;
248   mp->inbufs = NULL;
249   mp->bundle = bundle;
250
251   mp->link.type = LOGICAL_LINK;
252   mp->link.name = "mp";
253   mp->link.len = sizeof *mp;
254
255   mp->cfg.autoload.period = SAMPLE_PERIOD;
256   mp->cfg.autoload.min = mp->cfg.autoload.max = 0;
257   throughput_init(&mp->link.stats.total, mp->cfg.autoload.period);
258   throughput_callback(&mp->link.stats.total, mp_UpDown, mp);
259   mp->link.stats.parent = NULL;
260   mp->link.stats.gather = 0;    /* Let the physical links gather stats */
261   memset(mp->link.Queue, '\0', sizeof mp->link.Queue);
262   memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in);
263   memset(mp->link.proto_out, '\0', sizeof mp->link.proto_out);
264
265   mp->fsmp.LayerStart = mp_LayerStart;
266   mp->fsmp.LayerUp = mp_LayerUp;
267   mp->fsmp.LayerDown = mp_LayerDown;
268   mp->fsmp.LayerFinish = mp_LayerFinish;
269   mp->fsmp.object = mp;
270
271   mpserver_Init(&mp->server);
272
273   mp->cfg.mrru = 0;
274   mp->cfg.shortseq = NEG_ENABLED|NEG_ACCEPTED;
275   mp->cfg.negenddisc = NEG_ENABLED|NEG_ACCEPTED;
276   mp->cfg.enddisc.class = 0;
277   *mp->cfg.enddisc.address = '\0';
278   mp->cfg.enddisc.len = 0;
279
280   lcp_Init(&mp->link.lcp, mp->bundle, &mp->link, NULL);
281   ccp_Init(&mp->link.ccp, mp->bundle, &mp->link, &mp->fsmp);
282
283   link_EmptyStack(&mp->link);
284   link_Stack(&mp->link, &protolayer);
285   link_Stack(&mp->link, &ccplayer);
286   link_Stack(&mp->link, &vjlayer);
287 #ifndef NONAT
288   link_Stack(&mp->link, &natlayer);
289 #endif
290 }
291
292 int
293 mp_Up(struct mp *mp, struct datalink *dl)
294 {
295   struct lcp *lcp = &dl->physical->link.lcp;
296
297   if (mp->active) {
298     /* We're adding a link - do a last validation on our parameters */
299     if (!peerid_Equal(&dl->peer, &mp->peer)) {
300       log_Printf(LogPHASE, "%s: Inappropriate peer !\n", dl->name);
301       log_Printf(LogPHASE, "  Attached to peer %s/%s\n", mp->peer.authname,
302                  mp_Enddisc(mp->peer.enddisc.class, mp->peer.enddisc.address,
303                             mp->peer.enddisc.len));
304       log_Printf(LogPHASE, "  New link is peer %s/%s\n", dl->peer.authname,
305                  mp_Enddisc(dl->peer.enddisc.class, dl->peer.enddisc.address,
306                             dl->peer.enddisc.len));
307       return MP_FAILED;
308     }
309     if (mp->local_mrru != lcp->want_mrru ||
310         mp->peer_mrru != lcp->his_mrru ||
311         mp->local_is12bit != lcp->want_shortseq ||
312         mp->peer_is12bit != lcp->his_shortseq) {
313       log_Printf(LogPHASE, "%s: Invalid MRRU/SHORTSEQ MP parameters !\n",
314                 dl->name);
315       return MP_FAILED;
316     }
317     return MP_ADDED;
318   } else {
319     /* First link in multilink mode */
320
321     mp->local_mrru = lcp->want_mrru;
322     mp->peer_mrru = lcp->his_mrru;
323     mp->local_is12bit = lcp->want_shortseq;
324     mp->peer_is12bit = lcp->his_shortseq;
325     mp->peer = dl->peer;
326
327     throughput_destroy(&mp->link.stats.total);
328     throughput_init(&mp->link.stats.total, mp->cfg.autoload.period);
329     throughput_callback(&mp->link.stats.total, mp_UpDown, mp);
330     memset(mp->link.Queue, '\0', sizeof mp->link.Queue);
331     memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in);
332     memset(mp->link.proto_out, '\0', sizeof mp->link.proto_out);
333
334     /* Tell the link who it belongs to */
335     dl->physical->link.stats.parent = &mp->link.stats.total;
336
337     mp->out.seq = 0;
338     mp->out.link = 0;
339     mp->seq.min_in = 0;
340     mp->seq.next_in = 0;
341
342     /*
343      * Now we create our server socket.
344      * If it already exists, join it.  Otherwise, create and own it
345      */
346     switch (mpserver_Open(&mp->server, &mp->peer)) {
347     case MPSERVER_CONNECTED:
348       log_Printf(LogPHASE, "mp: Transfer link on %s\n",
349                 mp->server.socket.sun_path);
350       mp->server.send.dl = dl;          /* Defer 'till it's safe to send */
351       return MP_LINKSENT;
352     case MPSERVER_FAILED:
353       return MP_FAILED;
354     case MPSERVER_LISTENING:
355       log_Printf(LogPHASE, "mp: Listening on %s\n", mp->server.socket.sun_path);
356       log_Printf(LogPHASE, "    First link: %s\n", dl->name);
357
358       /* Re-point our IPCP layer at our MP link */
359       ipcp_SetLink(&mp->bundle->ncp.ipcp, &mp->link);
360
361       /* Our lcp's already up 'cos of the NULL parent */
362       if (ccp_SetOpenMode(&mp->link.ccp)) {
363         fsm_Up(&mp->link.ccp.fsm);
364         fsm_Open(&mp->link.ccp.fsm);
365       }
366
367       mp->active = 1;
368       break;
369     }
370   }
371
372   return MP_UP;
373 }
374
375 void
376 mp_Down(struct mp *mp)
377 {
378   if (mp->active) {
379     struct mbuf *next;
380
381     /* Stop that ! */
382     mp_StopAutoloadTimer(mp);
383
384     /* Don't want any more of these */
385     mpserver_Close(&mp->server);
386
387     /* CCP goes down with a bang */
388     fsm2initial(&mp->link.ccp.fsm);
389
390     /* Received fragments go in the bit-bucket */
391     while (mp->inbufs) {
392       next = mp->inbufs->m_nextpkt;
393       m_freem(mp->inbufs);
394       mp->inbufs = next;
395     }
396
397     peerid_Init(&mp->peer);
398     mp->active = 0;
399   }
400 }
401
402 void
403 mp_linkInit(struct mp_link *mplink)
404 {
405   mplink->seq = 0;
406   mplink->bandwidth = 0;
407 }
408
409 static void
410 mp_Assemble(struct mp *mp, struct mbuf *m, struct physical *p)
411 {
412   struct mp_header mh, h;
413   struct mbuf *q, *last;
414   int32_t seq;
415
416   /*
417    * When `m' and `p' are NULL, it means our oldest link has gone down.
418    * We want to determine a new min, and process any intermediate stuff
419    * as normal
420    */
421
422   if (m && mp_ReadHeader(mp, m, &mh) == 0) {
423     m_freem(m);
424     return;
425   }
426
427   if (p) {
428     seq = p->dl->mp.seq;
429     p->dl->mp.seq = mh.seq;
430   } else
431     seq = mp->seq.min_in;
432
433   if (mp->seq.min_in == seq) {
434     /*
435      * We've received new data on the link that has our min (oldest) seq.
436      * Figure out which link now has the smallest (oldest) seq.
437      */
438     struct datalink *dl;
439
440     mp->seq.min_in = (u_int32_t)-1;
441     for (dl = mp->bundle->links; dl; dl = dl->next)
442       if (dl->state == DATALINK_OPEN &&
443           (mp->seq.min_in == -1 ||
444            isbefore(mp->local_is12bit, dl->mp.seq, mp->seq.min_in)))
445         mp->seq.min_in = dl->mp.seq;
446   }
447
448   /*
449    * Now process as many of our fragments as we can, adding our new
450    * fragment in as we go, and ordering with the oldest at the top of
451    * the queue.
452    */
453
454   last = NULL;
455   seq = mp->seq.next_in;
456   q = mp->inbufs;
457   while (q || m) {
458     if (!q) {
459       if (last)
460         last->m_nextpkt = m;
461       else
462         mp->inbufs = m;
463       q = m;
464       m = NULL;
465       h = mh;
466     } else {
467       mp_ReadHeader(mp, q, &h);
468
469       if (m && isbefore(mp->local_is12bit, mh.seq, h.seq)) {
470         /* Our received fragment fits in before this one, so link it in */
471         if (last)
472           last->m_nextpkt = m;
473         else
474           mp->inbufs = m;
475         m->m_nextpkt = q;
476         q = m;
477         h = mh;
478         m = NULL;
479       }
480     }
481
482     if (h.seq != seq) {
483       /* we're missing something :-( */
484       if (isbefore(mp->local_is12bit, seq, mp->seq.min_in)) {
485         /* we're never gonna get it */
486         struct mbuf *next;
487
488         /* Zap all older fragments */
489         while (mp->inbufs != q) {
490           log_Printf(LogDEBUG, "Drop frag\n");
491           next = mp->inbufs->m_nextpkt;
492           m_freem(mp->inbufs);
493           mp->inbufs = next;
494         }
495
496         /*
497          * Zap everything until the next `end' fragment OR just before
498          * the next `begin' fragment OR 'till seq.min_in - whichever
499          * comes first.
500          */
501         do {
502           mp_ReadHeader(mp, mp->inbufs, &h);
503           if (h.begin) {
504             /* We might be able to process this ! */
505             h.seq--;  /* We're gonna look for fragment with h.seq+1 */
506             break;
507           }
508           next = mp->inbufs->m_nextpkt;
509           log_Printf(LogDEBUG, "Drop frag %u\n", h.seq);
510           m_freem(mp->inbufs);
511           mp->inbufs = next;
512         } while (mp->inbufs && (isbefore(mp->local_is12bit, mp->seq.min_in,
513                                          h.seq) || h.end));
514
515         /*
516          * Continue processing things from here.
517          * This deals with the possibility that we received a fragment
518          * on the slowest link that invalidates some of our data (because
519          * of the hole at `q'), but where there are subsequent `whole'
520          * packets that have already been received.
521          */
522
523         mp->seq.next_in = seq = inc_seq(mp->local_is12bit, h.seq);
524         last = NULL;
525         q = mp->inbufs;
526       } else
527         /* we may still receive the missing fragment */
528         break;
529     } else if (h.end) {
530       /* We've got something, reassemble */
531       struct mbuf **frag = &q;
532       int len;
533       u_long first = -1;
534
535       do {
536         *frag = mp->inbufs;
537         mp->inbufs = mp->inbufs->m_nextpkt;
538         len = mp_ReadHeader(mp, *frag, &h);
539         if (first == -1)
540           first = h.seq;
541         (*frag)->m_offset += len;
542         (*frag)->m_len -= len;
543         (*frag)->m_nextpkt = NULL;
544         if (frag == &q && !h.begin) {
545           log_Printf(LogWARN, "Oops - MP frag %lu should have a begin flag\n",
546                     (u_long)h.seq);
547           m_freem(q);
548           q = NULL;
549         } else if (frag != &q && h.begin) {
550           log_Printf(LogWARN, "Oops - MP frag %lu should have an end flag\n",
551                     (u_long)h.seq - 1);
552           /*
553            * Stuff our fragment back at the front of the queue and zap
554            * our half-assembed packet.
555            */
556           (*frag)->m_nextpkt = mp->inbufs;
557           mp->inbufs = *frag;
558           *frag = NULL;
559           m_freem(q);
560           q = NULL;
561           frag = &q;
562           h.end = 0;    /* just in case it's a whole packet */
563         } else
564           do
565             frag = &(*frag)->m_next;
566           while (*frag != NULL);
567       } while (!h.end);
568
569       if (q) {
570         q = m_pullup(q);
571         log_Printf(LogDEBUG, "MP: Reassembled frags %ld-%lu, length %d\n",
572                    first, (u_long)h.seq, m_length(q));
573         link_PullPacket(&mp->link, MBUF_CTOP(q), q->m_len, mp->bundle);
574         m_freem(q);
575       }
576
577       mp->seq.next_in = seq = inc_seq(mp->local_is12bit, h.seq);
578       last = NULL;
579       q = mp->inbufs;
580     } else {
581       /* Look for the next fragment */
582       seq = inc_seq(mp->local_is12bit, seq);
583       last = q;
584       q = q->m_nextpkt;
585     }
586   }
587
588   if (m) {
589     /* We still have to find a home for our new fragment */
590     last = NULL;
591     for (q = mp->inbufs; q; last = q, q = q->m_nextpkt) {
592       mp_ReadHeader(mp, q, &h);
593       if (isbefore(mp->local_is12bit, mh.seq, h.seq))
594         break;
595     }
596     /* Our received fragment fits in here */
597     if (last)
598       last->m_nextpkt = m;
599     else
600       mp->inbufs = m;
601     m->m_nextpkt = q;
602   }
603 }
604
605 struct mbuf *
606 mp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
607 {
608   struct physical *p = link2physical(l);
609
610   if (!bundle->ncp.mp.active)
611     /* Let someone else deal with it ! */
612     return bp;
613
614   if (p == NULL) {
615     log_Printf(LogWARN, "DecodePacket: Can't do MP inside MP !\n");
616     m_freem(bp);
617   } else {
618     m_settype(bp, MB_MPIN);
619     mp_Assemble(&bundle->ncp.mp, bp, p);
620   }
621
622   return NULL;
623 }
624
625 static void
626 mp_Output(struct mp *mp, struct bundle *bundle, struct link *l,
627           struct mbuf *m, u_int32_t begin, u_int32_t end)
628 {
629   char prepend[4];
630
631   /* Stuff an MP header on the front of our packet and send it */
632
633   if (mp->peer_is12bit) {
634     u_int16_t val;
635
636     val = (begin << 15) | (end << 14) | (u_int16_t)mp->out.seq;
637     ua_htons(&val, prepend);
638     m = m_prepend(m, prepend, 2, 0);
639   } else {
640     u_int32_t val;
641
642     val = (begin << 31) | (end << 30) | (u_int32_t)mp->out.seq;
643     ua_htonl(&val, prepend);
644     m = m_prepend(m, prepend, 4, 0);
645   }
646   if (log_IsKept(LogDEBUG))
647     log_Printf(LogDEBUG, "MP[frag %d]: Send %d bytes on link `%s'\n",
648                mp->out.seq, m_length(m), l->name);
649   mp->out.seq = inc_seq(mp->peer_is12bit, mp->out.seq);
650
651   if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) {
652     log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name);
653     return;
654   }
655
656   link_PushPacket(l, m, bundle, LINK_QUEUES(l) - 1, PROTO_MP);
657 }
658
659 int
660 mp_FillQueues(struct bundle *bundle)
661 {
662   struct mp *mp = &bundle->ncp.mp;
663   struct datalink *dl, *fdl;
664   size_t total, add, len;
665   int thislink, nlinks;
666   u_int32_t begin, end;
667   struct mbuf *m, *mo;
668
669   thislink = nlinks = 0;
670   for (fdl = NULL, dl = bundle->links; dl; dl = dl->next) {
671     /* Include non-open links here as mp->out.link will stay more correct */
672     if (!fdl) {
673       if (thislink == mp->out.link)
674         fdl = dl;
675       else
676         thislink++;
677     }
678     nlinks++;
679   }
680
681   if (!fdl) {
682     fdl = bundle->links;
683     if (!fdl)
684       return 0;
685     thislink = 0;
686   }
687
688   total = 0;
689   for (dl = fdl; nlinks > 0; dl = dl->next, nlinks--, thislink++) {
690     if (!dl) {
691       dl = bundle->links;
692       thislink = 0;
693     }
694
695     if (dl->state != DATALINK_OPEN)
696       continue;
697
698     if (dl->physical->out)
699       /* this link has suffered a short write.  Let it continue */
700       continue;
701
702     add = link_QueueLen(&dl->physical->link);
703     if (add) {
704       /* this link has got stuff already queued.  Let it continue */
705       total += add;
706       continue;
707     }
708
709     if (!link_QueueLen(&mp->link)) {
710       struct datalink *other;
711       int mrutoosmall;
712
713       /*
714        * If there's only a single open link in our bundle and we haven't got
715        * MP level link compression, queue outbound traffic directly via that
716        * link's protocol stack rather than using the MP link.  This results
717        * in the outbound traffic going out as PROTO_IP rather than PROTO_MP.
718        */
719       for (other = dl->next; other; other = other->next)
720         if (other->state == DATALINK_OPEN)
721           break;
722
723       mrutoosmall = 0;
724       if (!other) {
725         if (dl->physical->link.lcp.his_mru < mp->peer_mrru) {
726           /*
727            * Actually, forget it.  This test is done against the MRRU rather
728            * than the packet size so that we don't end up sending some data
729            * in MP fragments and some data in PROTO_IP packets.  That's just
730            * too likely to upset some ppp implementations.
731            */
732           mrutoosmall = 1;
733           other = dl;
734         }
735       }
736
737       if (!ip_PushPacket(other ? &mp->link : &dl->physical->link, bundle))
738         /* Nothing else to send */
739         break;
740
741       if (mrutoosmall)
742         log_Printf(LogDEBUG, "Don't send data as PROTO_IP, MRU < MRRU\n");
743       else if (!other)
744         log_Printf(LogDEBUG, "Sending data as PROTO_IP, not PROTO_MP\n");
745
746       if (!other) {
747         add = link_QueueLen(&dl->physical->link);
748         if (add) {
749           /* this link has got stuff already queued.  Let it continue */
750           total += add;
751           continue;
752         }
753       }
754     }
755
756     m = link_Dequeue(&mp->link);
757     if (m) {
758       len = m_length(m);
759       begin = 1;
760       end = 0;
761
762       while (!end) {
763         if (dl->state == DATALINK_OPEN) {
764           /* Write at most his_mru bytes to the physical link */
765           if (len <= dl->physical->link.lcp.his_mru) {
766             mo = m;
767             end = 1;
768             m_settype(mo, MB_MPOUT);
769           } else {
770             /* It's > his_mru, chop the packet (`m') into bits */
771             mo = m_get(dl->physical->link.lcp.his_mru, MB_MPOUT);
772             len -= mo->m_len;
773             m = mbuf_Read(m, MBUF_CTOP(mo), mo->m_len);
774           }
775           mp_Output(mp, bundle, &dl->physical->link, mo, begin, end);
776           begin = 0;
777         }
778
779         if (!end) {
780           nlinks--;
781           dl = dl->next;
782           if (!dl) {
783             dl = bundle->links;
784             thislink = 0;
785           } else
786             thislink++;
787         }
788       }
789     }
790   }
791   mp->out.link = thislink;              /* Start here next time */
792
793   return total;
794 }
795
796 int
797 mp_SetDatalinkBandwidth(struct cmdargs const *arg)
798 {
799   int val;
800
801   if (arg->argc != arg->argn+1)
802     return -1;
803
804   val = atoi(arg->argv[arg->argn]);
805   if (val <= 0) {
806     log_Printf(LogWARN, "The link bandwidth must be greater than zero\n");
807     return 1;
808   }
809   arg->cx->mp.bandwidth = val;
810
811   if (arg->cx->state == DATALINK_OPEN)
812     bundle_CalculateBandwidth(arg->bundle);
813
814   return 0;
815 }
816
817 int
818 mp_ShowStatus(struct cmdargs const *arg)
819 {
820   struct mp *mp = &arg->bundle->ncp.mp;
821
822   prompt_Printf(arg->prompt, "Multilink is %sactive\n", mp->active ? "" : "in");
823   if (mp->active) {
824     struct mbuf *m, *lm;
825     int bufs = 0;
826
827     lm = NULL;
828     prompt_Printf(arg->prompt, "Socket:         %s\n",
829                   mp->server.socket.sun_path);
830     for (m = mp->inbufs; m; m = m->m_nextpkt) {
831       bufs++;
832       lm = m;
833     }
834     prompt_Printf(arg->prompt, "Pending frags:  %d", bufs);
835     if (bufs) {
836       struct mp_header mh;
837       unsigned long first, last;
838
839       first = mp_ReadHeader(mp, mp->inbufs, &mh) ? mh.seq : 0;
840       last = mp_ReadHeader(mp, lm, &mh) ? mh.seq : 0;
841       prompt_Printf(arg->prompt, " (Have %lu - %lu, want %lu, lowest %lu)\n",
842                     first, last, (unsigned long)mp->seq.next_in,
843                     (unsigned long)mp->seq.min_in);
844       prompt_Printf(arg->prompt, "                First has %sbegin bit and "
845                     "%send bit", mh.begin ? "" : "no ", mh.end ? "" : "no ");
846     }
847     prompt_Printf(arg->prompt, "\n");
848   }
849
850   prompt_Printf(arg->prompt, "\nMy Side:\n");
851   if (mp->active) {
852     prompt_Printf(arg->prompt, " Output SEQ:    %u\n", mp->out.seq);
853     prompt_Printf(arg->prompt, " MRRU:          %u\n", mp->local_mrru);
854     prompt_Printf(arg->prompt, " Short Seq:     %s\n",
855                   mp->local_is12bit ? "on" : "off");
856   }
857   prompt_Printf(arg->prompt, " Discriminator: %s\n",
858                 mp_Enddisc(mp->cfg.enddisc.class, mp->cfg.enddisc.address,
859                            mp->cfg.enddisc.len));
860
861   prompt_Printf(arg->prompt, "\nHis Side:\n");
862   if (mp->active) {
863     prompt_Printf(arg->prompt, " Auth Name:     %s\n", mp->peer.authname);
864     prompt_Printf(arg->prompt, " Input SEQ:     %u\n", mp->seq.next_in);
865     prompt_Printf(arg->prompt, " MRRU:          %u\n", mp->peer_mrru);
866     prompt_Printf(arg->prompt, " Short Seq:     %s\n",
867                   mp->peer_is12bit ? "on" : "off");
868   }
869   prompt_Printf(arg->prompt,   " Discriminator: %s\n",
870                 mp_Enddisc(mp->peer.enddisc.class, mp->peer.enddisc.address,
871                            mp->peer.enddisc.len));
872
873   prompt_Printf(arg->prompt, "\nDefaults:\n");
874
875   prompt_Printf(arg->prompt, " MRRU:          ");
876   if (mp->cfg.mrru)
877     prompt_Printf(arg->prompt, "%d (multilink enabled)\n", mp->cfg.mrru);
878   else
879     prompt_Printf(arg->prompt, "disabled\n");
880   prompt_Printf(arg->prompt, " Short Seq:     %s\n",
881                   command_ShowNegval(mp->cfg.shortseq));
882   prompt_Printf(arg->prompt, " Discriminator: %s\n",
883                   command_ShowNegval(mp->cfg.negenddisc));
884   prompt_Printf(arg->prompt, " AutoLoad:      min %d%%, max %d%%,"
885                 " period %d secs\n", mp->cfg.autoload.min,
886                 mp->cfg.autoload.max, mp->cfg.autoload.period);
887
888   return 0;
889 }
890
891 const char *
892 mp_Enddisc(u_char c, const char *address, int len)
893 {
894   static char result[100];      /* Used immediately after it's returned */
895   int f, header;
896
897   switch (c) {
898     case ENDDISC_NULL:
899       sprintf(result, "Null Class");
900       break;
901
902     case ENDDISC_LOCAL:
903       snprintf(result, sizeof result, "Local Addr: %.*s", len, address);
904       break;
905
906     case ENDDISC_IP:
907       if (len == 4)
908         snprintf(result, sizeof result, "IP %s",
909                  inet_ntoa(*(const struct in_addr *)address));
910       else
911         sprintf(result, "IP[%d] ???", len);
912       break;
913
914     case ENDDISC_MAC:
915       if (len == 6) {
916         const u_char *m = (const u_char *)address;
917         snprintf(result, sizeof result, "MAC %02x:%02x:%02x:%02x:%02x:%02x",
918                  m[0], m[1], m[2], m[3], m[4], m[5]);
919       } else
920         sprintf(result, "MAC[%d] ???", len);
921       break;
922
923     case ENDDISC_MAGIC:
924       sprintf(result, "Magic: 0x");
925       header = strlen(result);
926       if (len > sizeof result - header - 1)
927         len = sizeof result - header - 1;
928       for (f = 0; f < len; f++)
929         sprintf(result + header + 2 * f, "%02x", address[f]);
930       break;
931
932     case ENDDISC_PSN:
933       snprintf(result, sizeof result, "PSN: %.*s", len, address);
934       break;
935
936      default:
937       sprintf(result, "%d: ", (int)c);
938       header = strlen(result);
939       if (len > sizeof result - header - 1)
940         len = sizeof result - header - 1;
941       for (f = 0; f < len; f++)
942         sprintf(result + header + 2 * f, "%02x", address[f]);
943       break;
944   }
945   return result;
946 }
947
948 int
949 mp_SetEnddisc(struct cmdargs const *arg)
950 {
951   struct mp *mp = &arg->bundle->ncp.mp;
952   struct in_addr addr;
953
954   switch (bundle_Phase(arg->bundle)) {
955     case PHASE_DEAD:
956       break;
957     case PHASE_ESTABLISH:
958       /* Make sure none of our links are DATALINK_LCP or greater */
959       if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) {
960         log_Printf(LogWARN, "enddisc: Only changable before"
961                    " LCP negotiations\n");
962         return 1;
963       }
964       break;
965     default:
966       log_Printf(LogWARN, "enddisc: Only changable at phase DEAD/ESTABLISH\n");
967       return 1;
968   }
969
970   if (arg->argc == arg->argn) {
971     mp->cfg.enddisc.class = 0;
972     *mp->cfg.enddisc.address = '\0';
973     mp->cfg.enddisc.len = 0;
974   } else if (arg->argc > arg->argn) {
975     if (!strcasecmp(arg->argv[arg->argn], "label")) {
976       mp->cfg.enddisc.class = ENDDISC_LOCAL;
977       strcpy(mp->cfg.enddisc.address, arg->bundle->cfg.label);
978       mp->cfg.enddisc.len = strlen(mp->cfg.enddisc.address);
979     } else if (!strcasecmp(arg->argv[arg->argn], "ip")) {
980       if (arg->bundle->ncp.ipcp.my_ip.s_addr == INADDR_ANY)
981         addr = arg->bundle->ncp.ipcp.cfg.my_range.ipaddr;
982       else
983         addr = arg->bundle->ncp.ipcp.my_ip;
984       memcpy(mp->cfg.enddisc.address, &addr.s_addr, sizeof addr.s_addr);
985       mp->cfg.enddisc.class = ENDDISC_IP;
986       mp->cfg.enddisc.len = sizeof arg->bundle->ncp.ipcp.my_ip.s_addr;
987     } else if (!strcasecmp(arg->argv[arg->argn], "mac")) {
988       struct sockaddr_dl hwaddr;
989       int s;
990
991       if (arg->bundle->ncp.ipcp.my_ip.s_addr == INADDR_ANY)
992         addr = arg->bundle->ncp.ipcp.cfg.my_range.ipaddr;
993       else
994         addr = arg->bundle->ncp.ipcp.my_ip;
995
996       s = ID0socket(AF_INET, SOCK_DGRAM, 0);
997       if (s < 0) {
998         log_Printf(LogERROR, "set enddisc: socket(): %s\n", strerror(errno));
999         return 2;
1000       }
1001       if (get_ether_addr(s, addr, &hwaddr)) {
1002         mp->cfg.enddisc.class = ENDDISC_MAC;
1003         memcpy(mp->cfg.enddisc.address, hwaddr.sdl_data + hwaddr.sdl_nlen,
1004                hwaddr.sdl_alen);
1005         mp->cfg.enddisc.len = hwaddr.sdl_alen;
1006       } else {
1007         log_Printf(LogWARN, "set enddisc: Can't locate MAC address for %s\n",
1008                   inet_ntoa(addr));
1009         close(s);
1010         return 4;
1011       }
1012       close(s);
1013     } else if (!strcasecmp(arg->argv[arg->argn], "magic")) {
1014       int f;
1015
1016       randinit();
1017       for (f = 0; f < 20; f += sizeof(long))
1018         *(long *)(mp->cfg.enddisc.address + f) = random();
1019       mp->cfg.enddisc.class = ENDDISC_MAGIC;
1020       mp->cfg.enddisc.len = 20;
1021     } else if (!strcasecmp(arg->argv[arg->argn], "psn")) {
1022       if (arg->argc > arg->argn+1) {
1023         mp->cfg.enddisc.class = ENDDISC_PSN;
1024         strcpy(mp->cfg.enddisc.address, arg->argv[arg->argn+1]);
1025         mp->cfg.enddisc.len = strlen(mp->cfg.enddisc.address);
1026       } else {
1027         log_Printf(LogWARN, "PSN endpoint requires additional data\n");
1028         return 5;
1029       }
1030     } else {
1031       log_Printf(LogWARN, "%s: Unrecognised endpoint type\n",
1032                 arg->argv[arg->argn]);
1033       return 6;
1034     }
1035   }
1036
1037   return 0;
1038 }
1039
1040 static int
1041 mpserver_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e,
1042                    int *n)
1043 {
1044   struct mpserver *s = descriptor2mpserver(d);
1045   int result;
1046
1047   result = 0;
1048   if (s->send.dl != NULL) {
1049     /* We've connect()ed */
1050     if (!link_QueueLen(&s->send.dl->physical->link) &&
1051         !s->send.dl->physical->out) {
1052       /* Only send if we've transmitted all our data (i.e. the ConfigAck) */
1053       result -= datalink_RemoveFromSet(s->send.dl, r, w, e);
1054       bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
1055       s->send.dl = NULL;
1056       s->fd = -1;
1057     } else
1058       /* Never read from a datalink that's on death row ! */
1059       result -= datalink_RemoveFromSet(s->send.dl, r, NULL, NULL);
1060   } else if (r && s->fd >= 0) {
1061     if (*n < s->fd + 1)
1062       *n = s->fd + 1;
1063     FD_SET(s->fd, r);
1064     log_Printf(LogTIMER, "mp: fdset(r) %d\n", s->fd);
1065     result++;
1066   }
1067   return result;
1068 }
1069
1070 static int
1071 mpserver_IsSet(struct fdescriptor *d, const fd_set *fdset)
1072 {
1073   struct mpserver *s = descriptor2mpserver(d);
1074   return s->fd >= 0 && FD_ISSET(s->fd, fdset);
1075 }
1076
1077 static void
1078 mpserver_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
1079 {
1080   struct mpserver *s = descriptor2mpserver(d);
1081
1082   bundle_ReceiveDatalink(bundle, s->fd);
1083 }
1084
1085 static int
1086 mpserver_Write(struct fdescriptor *d, struct bundle *bundle,
1087                const fd_set *fdset)
1088 {
1089   /* We never want to write here ! */
1090   log_Printf(LogALERT, "mpserver_Write: Internal error: Bad call !\n");
1091   return 0;
1092 }
1093
1094 void
1095 mpserver_Init(struct mpserver *s)
1096 {
1097   s->desc.type = MPSERVER_DESCRIPTOR;
1098   s->desc.UpdateSet = mpserver_UpdateSet;
1099   s->desc.IsSet = mpserver_IsSet;
1100   s->desc.Read = mpserver_Read;
1101   s->desc.Write = mpserver_Write;
1102   s->send.dl = NULL;
1103   s->fd = -1;
1104   memset(&s->socket, '\0', sizeof s->socket);
1105 }
1106
1107 int
1108 mpserver_Open(struct mpserver *s, struct peerid *peer)
1109 {
1110   int f, l;
1111   mode_t mask;
1112
1113   if (s->fd != -1) {
1114     log_Printf(LogALERT, "Internal error !  mpserver already open\n");
1115     mpserver_Close(s);
1116   }
1117
1118   l = snprintf(s->socket.sun_path, sizeof s->socket.sun_path, "%sppp-%s-%02x-",
1119                _PATH_VARRUN, peer->authname, peer->enddisc.class);
1120
1121   for (f = 0; f < peer->enddisc.len && l < sizeof s->socket.sun_path - 2; f++) {
1122     snprintf(s->socket.sun_path + l, sizeof s->socket.sun_path - l,
1123              "%02x", *(u_char *)(peer->enddisc.address+f));
1124     l += 2;
1125   }
1126
1127   s->socket.sun_family = AF_LOCAL;
1128   s->socket.sun_len = sizeof s->socket;
1129   s->fd = ID0socket(PF_LOCAL, SOCK_DGRAM, 0);
1130   if (s->fd < 0) {
1131     log_Printf(LogERROR, "mpserver: socket(): %s\n", strerror(errno));
1132     return MPSERVER_FAILED;
1133   }
1134
1135   setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, (struct sockaddr *)&s->socket,
1136              sizeof s->socket);
1137   mask = umask(0177);
1138
1139   /*
1140    * Try to bind the socket.  If we succeed we play server, if we fail
1141    * we connect() and hand the link off.
1142    */
1143
1144   if (ID0bind_un(s->fd, &s->socket) < 0) {
1145     if (errno != EADDRINUSE) {
1146       log_Printf(LogPHASE, "mpserver: can't create bundle socket %s (%s)\n",
1147                 s->socket.sun_path, strerror(errno));
1148       umask(mask);
1149       close(s->fd);
1150       s->fd = -1;
1151       return MPSERVER_FAILED;
1152     }
1153
1154     /* So we're the sender */
1155     umask(mask);
1156     if (ID0connect_un(s->fd, &s->socket) < 0) {
1157       log_Printf(LogPHASE, "mpserver: can't connect to bundle socket %s (%s)\n",
1158                 s->socket.sun_path, strerror(errno));
1159       if (errno == ECONNREFUSED)
1160         log_Printf(LogPHASE, "          The previous server died badly !\n");
1161       close(s->fd);
1162       s->fd = -1;
1163       return MPSERVER_FAILED;
1164     }
1165
1166     /* Donate our link to the other guy */
1167     return MPSERVER_CONNECTED;
1168   }
1169
1170   return MPSERVER_LISTENING;
1171 }
1172
1173 void
1174 mpserver_Close(struct mpserver *s)
1175 {
1176   if (s->send.dl != NULL) {
1177     bundle_SendDatalink(s->send.dl, s->fd, &s->socket);
1178     s->send.dl = NULL;
1179     s->fd = -1;
1180   } else if (s->fd >= 0) {
1181     close(s->fd);
1182     if (ID0unlink(s->socket.sun_path) == -1)
1183       log_Printf(LogERROR, "%s: Failed to remove: %s\n", s->socket.sun_path,
1184                 strerror(errno));
1185     memset(&s->socket, '\0', sizeof s->socket);
1186     s->fd = -1;
1187   }
1188 }
1189
1190 void
1191 mp_LinkLost(struct mp *mp, struct datalink *dl)
1192 {
1193   if (mp->seq.min_in == dl->mp.seq)
1194     /* We've lost the link that's holding everything up ! */
1195     mp_Assemble(mp, NULL, NULL);
1196 }
1197
1198 void
1199 mp_DeleteQueue(struct mp *mp)
1200 {
1201   link_DeleteQueue(&mp->link);
1202 }