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