xref: /freebsd/usr.sbin/ppp/bundle.c (revision 565e35e50e2cdac423588a3d18742544bde128b0)
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  *	$Id: bundle.c,v 1.1.2.43 1998/04/07 23:45:41 brian Exp $
27  */
28 
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <net/if.h>
33 #include <arpa/inet.h>
34 #include <net/route.h>
35 #include <net/if_dl.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/ioctl.h>
44 #include <termios.h>
45 #include <unistd.h>
46 
47 #include "command.h"
48 #include "mbuf.h"
49 #include "log.h"
50 #include "id.h"
51 #include "defs.h"
52 #include "timer.h"
53 #include "fsm.h"
54 #include "iplist.h"
55 #include "lqr.h"
56 #include "hdlc.h"
57 #include "throughput.h"
58 #include "slcompress.h"
59 #include "ipcp.h"
60 #include "filter.h"
61 #include "descriptor.h"
62 #include "route.h"
63 #include "lcp.h"
64 #include "ccp.h"
65 #include "link.h"
66 #include "mp.h"
67 #include "bundle.h"
68 #include "async.h"
69 #include "physical.h"
70 #include "modem.h"
71 #include "auth.h"
72 #include "lcpproto.h"
73 #include "chap.h"
74 #include "tun.h"
75 #include "prompt.h"
76 #include "chat.h"
77 #include "datalink.h"
78 #include "ip.h"
79 
80 static const char *PhaseNames[] = {
81   "Dead", "Establish", "Authenticate", "Network", "Terminate"
82 };
83 
84 const char *
85 bundle_PhaseName(struct bundle *bundle)
86 {
87   return bundle->phase <= PHASE_TERMINATE ?
88     PhaseNames[bundle->phase] : "unknown";
89 }
90 
91 void
92 bundle_NewPhase(struct bundle *bundle, u_int new)
93 {
94   if (new == bundle->phase)
95     return;
96 
97   if (new <= PHASE_TERMINATE)
98     LogPrintf(LogPHASE, "bundle: %s\n", PhaseNames[new]);
99 
100   switch (new) {
101   case PHASE_DEAD:
102     bundle->phase = new;
103     break;
104 
105   case PHASE_ESTABLISH:
106     bundle->phase = new;
107     break;
108 
109   case PHASE_AUTHENTICATE:
110     bundle->phase = new;
111     bundle_DisplayPrompt(bundle);
112     break;
113 
114   case PHASE_NETWORK:
115     ipcp_Setup(&bundle->ncp.ipcp);
116     FsmUp(&bundle->ncp.ipcp.fsm);
117     FsmOpen(&bundle->ncp.ipcp.fsm);
118     /* Fall through */
119 
120   case PHASE_TERMINATE:
121     bundle->phase = new;
122     bundle_DisplayPrompt(bundle);
123     break;
124   }
125 }
126 
127 static int
128 bundle_CleanInterface(const struct bundle *bundle)
129 {
130   int s;
131   struct ifreq ifrq;
132   struct ifaliasreq ifra;
133 
134   s = ID0socket(AF_INET, SOCK_DGRAM, 0);
135   if (s < 0) {
136     LogPrintf(LogERROR, "bundle_CleanInterface: socket(): %s\n",
137               strerror(errno));
138     return (-1);
139   }
140   strncpy(ifrq.ifr_name, bundle->ifname, sizeof ifrq.ifr_name - 1);
141   ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
142   while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) {
143     memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
144     strncpy(ifra.ifra_name, bundle->ifname, sizeof ifra.ifra_name - 1);
145     ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
146     ifra.ifra_addr = ifrq.ifr_addr;
147     if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) {
148       if (ifra.ifra_addr.sa_family == AF_INET)
149         LogPrintf(LogERROR,
150                   "bundle_CleanInterface: Can't get dst for %s on %s !\n",
151                   inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
152                   bundle->ifname);
153       return 0;
154     }
155     ifra.ifra_broadaddr = ifrq.ifr_dstaddr;
156     if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
157       if (ifra.ifra_addr.sa_family == AF_INET)
158         LogPrintf(LogERROR,
159                   "bundle_CleanInterface: Can't delete %s address on %s !\n",
160                   inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
161                   bundle->ifname);
162       return 0;
163     }
164   }
165 
166   return 1;
167 }
168 
169 static void
170 bundle_LayerStart(void *v, struct fsm *fp)
171 {
172   /* The given FSM is about to start up ! */
173 }
174 
175 
176 static void
177 bundle_Notify(struct bundle *bundle, char c)
178 {
179   if (bundle->notify.fd != -1) {
180     if (write(bundle->notify.fd, &c, 1) == 1)
181       LogPrintf(LogPHASE, "Parent notified of success.\n");
182     else
183       LogPrintf(LogPHASE, "Failed to notify parent of success.\n");
184     close(bundle->notify.fd);
185     bundle->notify.fd = -1;
186   }
187 }
188 
189 static void
190 bundle_vLayerUp(void *v, struct fsm *fp)
191 {
192   bundle_LayerUp((struct bundle *)v, fp);
193 }
194 
195 void
196 bundle_LayerUp(struct bundle *bundle, struct fsm *fp)
197 {
198   /*
199    * The given fsm is now up
200    * If it's an LCP (including MP initialisation), set our mtu
201    * (This routine is also called from mp_Init() with it's LCP)
202    * If it's an NCP, tell our -background parent to go away.
203    * If it's the first NCP, start the idle timer.
204    */
205 
206   if (fp->proto == PROTO_LCP) {
207     if (bundle->ncp.mp.active) {
208       int speed;
209       struct datalink *dl;
210 
211       for (dl = bundle->links, speed = 0; dl; dl = dl->next)
212         speed += modem_Speed(dl->physical);
213       if (speed)
214         tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru, speed);
215     } else
216       tun_configure(bundle, fsm2lcp(fp)->his_mru,
217                     modem_Speed(link2physical(fp->link)));
218   } else if (fp->proto == PROTO_IPCP) {
219     bundle_StartIdleTimer(bundle);
220     bundle_Notify(bundle, EX_NORMAL);
221   }
222 }
223 
224 static void
225 bundle_LayerDown(void *v, struct fsm *fp)
226 {
227   /*
228    * The given FSM has been told to come down.
229    * If it's our last NCP, stop the idle timer.
230    * If it's our last NCP *OR* LCP, enter TERMINATE phase.
231    * If it's an LCP and we're in multilink mode, adjust our tun speed.
232    */
233 
234   struct bundle *bundle = (struct bundle *)v;
235 
236   if (fp->proto == PROTO_IPCP) {
237     bundle_StopIdleTimer(bundle);
238     bundle_NewPhase(bundle, PHASE_TERMINATE);
239   } else if (fp->proto == PROTO_LCP) {
240     int speed, others_active;
241     struct datalink *dl;
242 
243     others_active = 0;
244     for (dl = bundle->links, speed = 0; dl; dl = dl->next)
245       if (fp != &dl->physical->link.lcp.fsm &&
246           dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP) {
247         speed += modem_Speed(dl->physical);
248         others_active++;
249       }
250     if (bundle->ncp.mp.active && speed)
251       tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru, speed);
252 
253     if (!others_active)
254       bundle_NewPhase(bundle, PHASE_TERMINATE);
255   }
256 }
257 
258 static void
259 bundle_LayerFinish(void *v, struct fsm *fp)
260 {
261   /* The given fsm is now down (fp cannot be NULL)
262    *
263    * If it's the last LCP, FsmDown all NCPs
264    * If it's the last NCP, FsmClose all LCPs
265    */
266 
267   struct bundle *bundle = (struct bundle *)v;
268   struct datalink *dl;
269 
270   if (fp->proto == PROTO_IPCP) {
271     for (dl = bundle->links; dl; dl = dl->next)
272       datalink_Close(dl, 0);
273     FsmDown(fp);
274     FsmClose(fp);
275   } else if (fp->proto == PROTO_LCP) {
276     int others_active;
277 
278     others_active = 0;
279     for (dl = bundle->links; dl; dl = dl->next)
280       if (fp != &dl->physical->link.lcp.fsm &&
281           dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP)
282         others_active++;
283 
284     if (!others_active) {
285       FsmDown(&bundle->ncp.ipcp.fsm);
286       FsmClose(&bundle->ncp.ipcp.fsm);		/* ST_INITIAL please */
287     }
288   }
289 }
290 
291 int
292 bundle_LinkIsUp(const struct bundle *bundle)
293 {
294   return bundle->ncp.ipcp.fsm.state == ST_OPENED;
295 }
296 
297 void
298 bundle_Close(struct bundle *bundle, const char *name, int staydown)
299 {
300   /*
301    * Please close the given datalink.
302    * If name == NULL or name is the last datalink, enter TERMINATE phase
303    * and FsmClose all NCPs (except our MP)
304    * If it isn't the last datalink, just Close that datalink.
305    */
306 
307   struct datalink *dl, *this_dl;
308   int others_active;
309 
310   if (bundle->phase == PHASE_TERMINATE || bundle->phase == PHASE_DEAD)
311     return;
312 
313   others_active = 0;
314   this_dl = NULL;
315 
316   for (dl = bundle->links; dl; dl = dl->next) {
317     if (name && !strcasecmp(name, dl->name))
318       this_dl = dl;
319     if (name == NULL || this_dl == dl) {
320       if (staydown)
321         datalink_StayDown(dl);
322     } else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP)
323       others_active++;
324   }
325 
326   if (name && this_dl == NULL) {
327     LogPrintf(LogWARN, "%s: Invalid datalink name\n", name);
328     return;
329   }
330 
331   if (!others_active) {
332     if (bundle->ncp.ipcp.fsm.state > ST_CLOSED ||
333         bundle->ncp.ipcp.fsm.state == ST_STARTING)
334       FsmClose(&bundle->ncp.ipcp.fsm);
335     else {
336       if (bundle->ncp.ipcp.fsm.state > ST_INITIAL) {
337         FsmClose(&bundle->ncp.ipcp.fsm);
338         FsmDown(&bundle->ncp.ipcp.fsm);
339       }
340       for (dl = bundle->links; dl; dl = dl->next)
341         datalink_Close(dl, staydown);
342     }
343   } else if (this_dl && this_dl->state != DATALINK_CLOSED &&
344              this_dl->state != DATALINK_HANGUP)
345     datalink_Close(this_dl, staydown);
346 }
347 
348 static int
349 bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
350 {
351   struct bundle *bundle = descriptor2bundle(d);
352   struct datalink *dl;
353   struct descriptor *desc;
354   int result;
355 
356   result = 0;
357   for (dl = bundle->links; dl; dl = dl->next)
358     result += descriptor_UpdateSet(&dl->desc, r, w, e, n);
359 
360   for (desc = bundle->desc.next; desc; desc = desc->next)
361     result += descriptor_UpdateSet(desc, r, w, e, n);
362 
363   return result;
364 }
365 
366 static int
367 bundle_IsSet(struct descriptor *d, const fd_set *fdset)
368 {
369   struct bundle *bundle = descriptor2bundle(d);
370   struct datalink *dl;
371   struct descriptor *desc;
372 
373   for (dl = bundle->links; dl; dl = dl->next)
374     if (descriptor_IsSet(&dl->desc, fdset))
375       return 1;
376 
377   for (desc = bundle->desc.next; desc; desc = desc->next)
378     if (descriptor_IsSet(desc, fdset))
379       return 1;
380 
381   return 0;
382 }
383 
384 static void
385 bundle_DescriptorRead(struct descriptor *d, struct bundle *bundle,
386                       const fd_set *fdset)
387 {
388   struct datalink *dl;
389   struct descriptor *desc;
390 
391   for (dl = bundle->links; dl; dl = dl->next)
392     if (descriptor_IsSet(&dl->desc, fdset))
393       descriptor_Read(&dl->desc, bundle, fdset);
394 
395   for (desc = bundle->desc.next; desc; desc = desc->next)
396     if (descriptor_IsSet(desc, fdset))
397       descriptor_Read(desc, bundle, fdset);
398 }
399 
400 static void
401 bundle_DescriptorWrite(struct descriptor *d, struct bundle *bundle,
402                        const fd_set *fdset)
403 {
404   struct datalink *dl;
405   struct descriptor *desc;
406 
407   for (dl = bundle->links; dl; dl = dl->next)
408     if (descriptor_IsSet(&dl->desc, fdset))
409       descriptor_Write(&dl->desc, bundle, fdset);
410 
411   for (desc = bundle->desc.next; desc; desc = desc->next)
412     if (descriptor_IsSet(desc, fdset))
413       descriptor_Write(desc, bundle, fdset);
414 }
415 
416 
417 #define MAX_TUN 256
418 /*
419  * MAX_TUN is set at 256 because that is the largest minor number
420  * we can use (certainly with mknod(1) anyway).  The search for a
421  * device aborts when it reaches the first `Device not configured'
422  * (ENXIO) or the third `No such file or directory' (ENOENT) error.
423  */
424 struct bundle *
425 bundle_Create(const char *prefix, struct prompt *prompt, int type)
426 {
427   int s, enoentcount, err;
428   struct ifreq ifrq;
429   static struct bundle bundle;		/* there can be only one */
430 
431   if (bundle.ifname != NULL) {	/* Already allocated ! */
432     LogPrintf(LogERROR, "bundle_Create:  There's only one BUNDLE !\n");
433     return NULL;
434   }
435 
436   err = ENOENT;
437   enoentcount = 0;
438   for (bundle.unit = 0; bundle.unit <= MAX_TUN; bundle.unit++) {
439     snprintf(bundle.dev, sizeof bundle.dev, "%s%d", prefix, bundle.unit);
440     bundle.tun_fd = ID0open(bundle.dev, O_RDWR);
441     if (bundle.tun_fd >= 0)
442       break;
443     if (errno == ENXIO) {
444       bundle.unit = MAX_TUN;
445       err = errno;
446     } else if (errno == ENOENT) {
447       if (++enoentcount > 2)
448 	bundle.unit = MAX_TUN;
449     } else
450       err = errno;
451   }
452 
453   if (bundle.unit > MAX_TUN) {
454     prompt_Printf(prompt, "No tunnel device is available (%s).\n",
455                   strerror(err));
456     return NULL;
457   }
458 
459   LogSetTun(bundle.unit);
460 
461   s = socket(AF_INET, SOCK_DGRAM, 0);
462   if (s < 0) {
463     LogPrintf(LogERROR, "bundle_Create: socket(): %s\n", strerror(errno));
464     close(bundle.tun_fd);
465     return NULL;
466   }
467 
468   bundle.ifname = strrchr(bundle.dev, '/');
469   if (bundle.ifname == NULL)
470     bundle.ifname = bundle.dev;
471   else
472     bundle.ifname++;
473 
474   /*
475    * Now, bring up the interface.
476    */
477   memset(&ifrq, '\0', sizeof ifrq);
478   strncpy(ifrq.ifr_name, bundle.ifname, sizeof ifrq.ifr_name - 1);
479   ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
480   if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
481     LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCGIFFLAGS): %s\n",
482 	      strerror(errno));
483     close(s);
484     close(bundle.tun_fd);
485     bundle.ifname = NULL;
486     return NULL;
487   }
488   ifrq.ifr_flags |= IFF_UP;
489   if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
490     LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCSIFFLAGS): %s\n",
491 	      strerror(errno));
492     close(s);
493     close(bundle.tun_fd);
494     bundle.ifname = NULL;
495     return NULL;
496   }
497 
498   close(s);
499 
500   if ((bundle.ifIndex = GetIfIndex(bundle.ifname)) < 0) {
501     LogPrintf(LogERROR, "OpenTunnel: Can't find ifindex.\n");
502     close(bundle.tun_fd);
503     bundle.ifname = NULL;
504     return NULL;
505   }
506 
507   prompt_Printf(prompt, "Using interface: %s\n", bundle.ifname);
508   LogPrintf(LogPHASE, "Using interface: %s\n", bundle.ifname);
509 
510   bundle.routing_seq = 0;
511   bundle.phase = PHASE_DEAD;
512   bundle.CleaningUp = 0;
513 
514   bundle.fsm.LayerStart = bundle_LayerStart;
515   bundle.fsm.LayerUp = bundle_vLayerUp;
516   bundle.fsm.LayerDown = bundle_LayerDown;
517   bundle.fsm.LayerFinish = bundle_LayerFinish;
518   bundle.fsm.object = &bundle;
519 
520   bundle.cfg.idle_timeout = NCP_IDLE_TIMEOUT;
521   bundle.phys_type = type;
522 
523   bundle.links = datalink_Create("default", &bundle, &bundle.fsm, type);
524   if (bundle.links == NULL) {
525     LogPrintf(LogERROR, "Cannot create data link: %s\n", strerror(errno));
526     close(bundle.tun_fd);
527     bundle.ifname = NULL;
528     return NULL;
529   }
530 
531   bundle.desc.type = BUNDLE_DESCRIPTOR;
532   bundle.desc.next = NULL;
533   bundle.desc.UpdateSet = bundle_UpdateSet;
534   bundle.desc.IsSet = bundle_IsSet;
535   bundle.desc.Read = bundle_DescriptorRead;
536   bundle.desc.Write = bundle_DescriptorWrite;
537 
538   ipcp_Init(&bundle.ncp.ipcp, &bundle, &bundle.links->physical->link,
539             &bundle.fsm);
540 
541   memset(&bundle.filter, '\0', sizeof bundle.filter);
542   bundle.filter.in.fragok = bundle.filter.in.logok = 1;
543   bundle.filter.in.name = "IN";
544   bundle.filter.out.fragok = bundle.filter.out.logok = 1;
545   bundle.filter.out.name = "OUT";
546   bundle.filter.dial.name = "DIAL";
547   bundle.filter.dial.logok = 1;
548   bundle.filter.alive.name = "ALIVE";
549   bundle.filter.alive.logok = 1;
550   memset(&bundle.idle.timer, '\0', sizeof bundle.idle.timer);
551   bundle.idle.done = 0;
552   bundle.notify.fd = -1;
553 
554   /* Clean out any leftover crud */
555   bundle_CleanInterface(&bundle);
556 
557   if (prompt) {
558     /* Retrospectively introduce ourselves to the prompt */
559     prompt->bundle = &bundle;
560     bundle_RegisterDescriptor(&bundle, &prompt->desc);
561   }
562 
563   return &bundle;
564 }
565 
566 static void
567 bundle_DownInterface(struct bundle *bundle)
568 {
569   struct ifreq ifrq;
570   int s;
571 
572   DeleteIfRoutes(bundle, 1);
573 
574   s = ID0socket(AF_INET, SOCK_DGRAM, 0);
575   if (s < 0) {
576     LogPrintf(LogERROR, "bundle_DownInterface: socket: %s\n", strerror(errno));
577     return;
578   }
579 
580   memset(&ifrq, '\0', sizeof ifrq);
581   strncpy(ifrq.ifr_name, bundle->ifname, sizeof ifrq.ifr_name - 1);
582   ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
583   if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
584     LogPrintf(LogERROR, "bundle_DownInterface: ioctl(SIOCGIFFLAGS): %s\n",
585        strerror(errno));
586     close(s);
587     return;
588   }
589   ifrq.ifr_flags &= ~IFF_UP;
590   if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
591     LogPrintf(LogERROR, "bundle_DownInterface: ioctl(SIOCSIFFLAGS): %s\n",
592        strerror(errno));
593     close(s);
594     return;
595   }
596   close(s);
597 }
598 
599 void
600 bundle_Destroy(struct bundle *bundle)
601 {
602   struct datalink *dl;
603   struct descriptor *desc, *ndesc;
604 
605   if (bundle->phys_type & PHYS_DEMAND) {
606     IpcpCleanInterface(&bundle->ncp.ipcp);
607     bundle_DownInterface(bundle);
608   }
609 
610   dl = bundle->links;
611   while (dl)
612     dl = datalink_Destroy(dl);
613 
614   bundle_Notify(bundle, EX_ERRDEAD);
615 
616   desc = bundle->desc.next;
617   while (desc) {
618     ndesc = desc->next;
619     if (desc->type == PROMPT_DESCRIPTOR)
620       prompt_Destroy((struct prompt *)desc, 1);
621     else
622       LogPrintf(LogERROR, "bundle_Destroy: Don't know how to delete descriptor"
623                 " type %d\n", desc->type);
624     desc = ndesc;
625   }
626   bundle->desc.next = NULL;
627   bundle->ifname = NULL;
628 }
629 
630 struct rtmsg {
631   struct rt_msghdr m_rtm;
632   char m_space[64];
633 };
634 
635 void
636 bundle_SetRoute(struct bundle *bundle, int cmd, struct in_addr dst,
637                 struct in_addr gateway, struct in_addr mask, int bang)
638 {
639   struct rtmsg rtmes;
640   int s, nb, wb;
641   char *cp;
642   const char *cmdstr;
643   struct sockaddr_in rtdata;
644 
645   if (bang)
646     cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!");
647   else
648     cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
649   s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
650   if (s < 0) {
651     LogPrintf(LogERROR, "bundle_SetRoute: socket(): %s\n", strerror(errno));
652     return;
653   }
654   memset(&rtmes, '\0', sizeof rtmes);
655   rtmes.m_rtm.rtm_version = RTM_VERSION;
656   rtmes.m_rtm.rtm_type = cmd;
657   rtmes.m_rtm.rtm_addrs = RTA_DST;
658   rtmes.m_rtm.rtm_seq = ++bundle->routing_seq;
659   rtmes.m_rtm.rtm_pid = getpid();
660   rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
661 
662   memset(&rtdata, '\0', sizeof rtdata);
663   rtdata.sin_len = 16;
664   rtdata.sin_family = AF_INET;
665   rtdata.sin_port = 0;
666   rtdata.sin_addr = dst;
667 
668   cp = rtmes.m_space;
669   memcpy(cp, &rtdata, 16);
670   cp += 16;
671   if (cmd == RTM_ADD)
672     if (gateway.s_addr == INADDR_ANY) {
673       /* Add a route through the interface */
674       struct sockaddr_dl dl;
675       const char *iname;
676       int ilen;
677 
678       iname = Index2Nam(bundle->ifIndex);
679       ilen = strlen(iname);
680       dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen;
681       dl.sdl_family = AF_LINK;
682       dl.sdl_index = bundle->ifIndex;
683       dl.sdl_type = 0;
684       dl.sdl_nlen = ilen;
685       dl.sdl_alen = 0;
686       dl.sdl_slen = 0;
687       strncpy(dl.sdl_data, iname, sizeof dl.sdl_data);
688       memcpy(cp, &dl, dl.sdl_len);
689       cp += dl.sdl_len;
690       rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
691     } else {
692       rtdata.sin_addr = gateway;
693       memcpy(cp, &rtdata, 16);
694       cp += 16;
695       rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
696     }
697 
698   if (dst.s_addr == INADDR_ANY)
699     mask.s_addr = INADDR_ANY;
700 
701   if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) {
702     rtdata.sin_addr = mask;
703     memcpy(cp, &rtdata, 16);
704     cp += 16;
705     rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
706   }
707 
708   nb = cp - (char *) &rtmes;
709   rtmes.m_rtm.rtm_msglen = nb;
710   wb = ID0write(s, &rtmes, nb);
711   if (wb < 0) {
712     LogPrintf(LogTCPIP, "bundle_SetRoute failure:\n");
713     LogPrintf(LogTCPIP, "bundle_SetRoute:  Cmd = %s\n", cmd);
714     LogPrintf(LogTCPIP, "bundle_SetRoute:  Dst = %s\n", inet_ntoa(dst));
715     LogPrintf(LogTCPIP, "bundle_SetRoute:  Gateway = %s\n", inet_ntoa(gateway));
716     LogPrintf(LogTCPIP, "bundle_SetRoute:  Mask = %s\n", inet_ntoa(mask));
717 failed:
718     if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST ||
719                            (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST)))
720       if (!bang)
721         LogPrintf(LogWARN, "Add route failed: %s already exists\n",
722                   inet_ntoa(dst));
723       else {
724         rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE;
725         if ((wb = ID0write(s, &rtmes, nb)) < 0)
726           goto failed;
727       }
728     else if (cmd == RTM_DELETE &&
729              (rtmes.m_rtm.rtm_errno == ESRCH ||
730               (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) {
731       if (!bang)
732         LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n",
733                   inet_ntoa(dst));
734     } else if (rtmes.m_rtm.rtm_errno == 0)
735       LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr,
736                 inet_ntoa(dst), strerror(errno));
737     else
738       LogPrintf(LogWARN, "%s route failed: %s: %s\n",
739 		cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
740   }
741   LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
742             wb, cmdstr, dst.s_addr, gateway.s_addr);
743   close(s);
744 }
745 
746 void
747 bundle_LinkLost(struct bundle *bundle, struct physical *p, int staydown)
748 {
749   /*
750    * Locate the appropriate datalink, and Down it.
751    *
752    * The LayerFinish() called from the datalinks LCP will
753    * potentially Down our NCPs (if it's the last link).
754    *
755    * The LinkClosed() called when the datalink is finally in
756    * the CLOSED state MAY cause the entire datalink to be deleted
757    * and MAY cause a program exit.
758    */
759 
760   if (p->type == PHYS_STDIN || bundle->CleaningUp)
761     staydown = 1;
762   datalink_Down(p->dl, staydown);
763 }
764 
765 void
766 bundle_LinkClosed(struct bundle *bundle, struct datalink *dl)
767 {
768   /*
769    * Our datalink has closed.
770    * UpdateSet() will remove 1OFF and STDIN links.
771    * If it's the last data link, enter phase DEAD.
772    */
773 
774   struct datalink *odl;
775   int other_links;
776 
777   other_links = 0;
778   for (odl = bundle->links; odl; odl = odl->next)
779     if (odl != dl && odl->state != DATALINK_CLOSED)
780       other_links++;
781 
782   if (!other_links) {
783     if (dl->physical->type != PHYS_DEMAND)
784       bundle_DownInterface(bundle);
785     bundle_NewPhase(bundle, PHASE_DEAD);
786     bundle_DisplayPrompt(bundle);
787   }
788 }
789 
790 void
791 bundle_Open(struct bundle *bundle, const char *name, int mask)
792 {
793   /*
794    * Please open the given datalink, or all if name == NULL
795    */
796   struct datalink *dl;
797 
798   for (dl = bundle->links; dl; dl = dl->next)
799     if (name == NULL || !strcasecmp(dl->name, name)) {
800       if (mask & dl->physical->type)
801         datalink_Up(dl, 1, 1);
802       if (name != NULL)
803         break;
804     }
805 }
806 
807 struct datalink *
808 bundle2datalink(struct bundle *bundle, const char *name)
809 {
810   struct datalink *dl;
811 
812   if (name != NULL) {
813     for (dl = bundle->links; dl; dl = dl->next)
814       if (!strcasecmp(dl->name, name))
815         return dl;
816   } else if (bundle->links && !bundle->links->next)
817     return bundle->links;
818 
819   return NULL;
820 }
821 
822 int
823 bundle_FillQueues(struct bundle *bundle)
824 {
825   int total;
826 
827   if (bundle->ncp.mp.active) {
828     total = mp_FillQueues(bundle);
829   } else {
830     total = link_QueueLen(&bundle->links->physical->link);
831     if (total == 0 && bundle->links->physical->out == NULL)
832       total = IpFlushPacket(&bundle->links->physical->link, bundle);
833   }
834 
835   return total + ip_QueueLen();
836 }
837 
838 int
839 bundle_ShowLinks(struct cmdargs const *arg)
840 {
841   if (arg->cx)
842     datalink_Show(arg->cx, arg->prompt);
843   else {
844     struct datalink *dl;
845 
846     for (dl = arg->bundle->links; dl; dl = dl->next)
847       datalink_Show(dl, arg->prompt);
848   }
849 
850   return 0;
851 }
852 
853 static void
854 bundle_IdleTimeout(void *v)
855 {
856   struct bundle *bundle = (struct bundle *)v;
857 
858   bundle->idle.done = 0;
859   LogPrintf(LogPHASE, "IPCP Idle timer expired.\n");
860   bundle_Close(bundle, NULL, 1);
861 }
862 
863 /*
864  *  Start Idle timer. If timeout is reached, we call bundle_Close() to
865  *  close LCP and link.
866  */
867 void
868 bundle_StartIdleTimer(struct bundle *bundle)
869 {
870   if (!(bundle->phys_type & (PHYS_DEDICATED|PHYS_PERM)) &&
871       bundle->cfg.idle_timeout) {
872     StopTimer(&bundle->idle.timer);
873     bundle->idle.timer.func = bundle_IdleTimeout;
874     bundle->idle.timer.name = "idle";
875     bundle->idle.timer.load = bundle->cfg.idle_timeout * SECTICKS;
876     bundle->idle.timer.state = TIMER_STOPPED;
877     bundle->idle.timer.arg = bundle;
878     StartTimer(&bundle->idle.timer);
879     bundle->idle.done = time(NULL) + bundle->cfg.idle_timeout;
880   }
881 }
882 
883 void
884 bundle_SetIdleTimer(struct bundle *bundle, int value)
885 {
886   bundle->cfg.idle_timeout = value;
887   if (bundle_LinkIsUp(bundle))
888     bundle_StartIdleTimer(bundle);
889 }
890 
891 void
892 bundle_StopIdleTimer(struct bundle *bundle)
893 {
894   StopTimer(&bundle->idle.timer);
895   bundle->idle.done = 0;
896 }
897 
898 int
899 bundle_RemainingIdleTime(struct bundle *bundle)
900 {
901   if (bundle->idle.done)
902     return bundle->idle.done - time(NULL);
903   return -1;
904 }
905 
906 int
907 bundle_IsDead(struct bundle *bundle)
908 {
909   return !bundle->links || (bundle->phase == PHASE_DEAD && bundle->CleaningUp);
910 }
911 
912 void
913 bundle_RegisterDescriptor(struct bundle *bundle, struct descriptor *d)
914 {
915   d->next = bundle->desc.next;
916   bundle->desc.next = d;
917 }
918 
919 void
920 bundle_UnRegisterDescriptor(struct bundle *bundle, struct descriptor *d)
921 {
922   struct descriptor **desc;
923 
924   for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next)
925     if (*desc == d) {
926       *desc = d->next;
927       break;
928     }
929 }
930 
931 void
932 bundle_DelPromptDescriptors(struct bundle *bundle, struct server *s)
933 {
934   struct descriptor **desc;
935   struct prompt *p;
936 
937   desc = &bundle->desc.next;
938   while (*desc) {
939     if ((*desc)->type == PROMPT_DESCRIPTOR) {
940       p = (struct prompt *)*desc;
941       if (p->owner == s) {
942         prompt_Destroy(p, 1);
943         desc = &bundle->desc.next;
944         continue;
945       }
946     }
947     desc = &(*desc)->next;
948   }
949 }
950 
951 void
952 bundle_DisplayPrompt(struct bundle *bundle)
953 {
954   struct descriptor **desc;
955 
956   for (desc = &bundle->desc.next; *desc; desc = &(*desc)->next)
957     if ((*desc)->type == PROMPT_DESCRIPTOR)
958       prompt_Required((struct prompt *)*desc);
959 }
960 
961 void
962 bundle_WriteTermPrompt(struct bundle *bundle, struct datalink *dl,
963                        const char *data, int len)
964 {
965   struct descriptor *desc;
966   struct prompt *p;
967 
968   for (desc = bundle->desc.next; desc; desc = desc->next)
969     if (desc->type == PROMPT_DESCRIPTOR) {
970       p = (struct prompt *)desc;
971       if (prompt_IsTermMode(p, dl))
972         prompt_Printf(p, "%.*s", len, data);
973     }
974 }
975 
976 void
977 bundle_SetTtyCommandMode(struct bundle *bundle, struct datalink *dl)
978 {
979   struct descriptor *desc;
980   struct prompt *p;
981 
982   for (desc = bundle->desc.next; desc; desc = desc->next)
983     if (desc->type == PROMPT_DESCRIPTOR) {
984       p = (struct prompt *)desc;
985       if (prompt_IsTermMode(p, dl))
986         prompt_TtyCommandMode(p);
987     }
988 }
989 
990 static void
991 bundle_GenPhysType(struct bundle *bundle)
992 {
993   struct datalink *dl;
994 
995   bundle->phys_type = 0;
996   for (dl = bundle->links; dl; dl = dl->next)
997     bundle->phys_type |= dl->physical->type;
998 }
999 
1000 void
1001 bundle_DatalinkClone(struct bundle *bundle, struct datalink *dl,
1002                      const char *name)
1003 {
1004   struct datalink *ndl = datalink_Clone(dl, name);
1005 
1006   ndl->next = dl->next;
1007   dl->next = ndl;
1008   bundle_GenPhysType(bundle);
1009 }
1010 
1011 void
1012 bundle_DatalinkRemove(struct bundle *bundle, struct datalink *dl)
1013 {
1014   struct datalink **dlp;
1015 
1016   if (dl->state == DATALINK_CLOSED)
1017     for (dlp = &bundle->links; *dlp; dlp = &(*dlp)->next)
1018       if (*dlp == dl) {
1019         *dlp = datalink_Destroy(dl);
1020         break;
1021       }
1022   bundle_GenPhysType(bundle);
1023 }
1024 
1025 void
1026 bundle_CleanDatalinks(struct bundle *bundle)
1027 {
1028   struct datalink **dlp = &bundle->links;
1029 
1030   while (*dlp)
1031     if ((*dlp)->state == DATALINK_CLOSED &&
1032         (*dlp)->physical->type & (PHYS_STDIN|PHYS_1OFF))
1033       *dlp = datalink_Destroy(*dlp);
1034     else
1035       dlp = &(*dlp)->next;
1036   bundle_GenPhysType(bundle);
1037 }
1038