1706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*-
2706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * All rights reserved.
4706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
5706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Redistribution and use in source and binary forms, with or without
6706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * modification, are permitted provided that the following conditions
7706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * are met:
8706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 1. Redistributions of source code must retain the above copyright
9706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer.
10706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 2. Redistributions in binary form must reproduce the above copyright
11706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer in the
12706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    documentation and/or other materials provided with the distribution.
13706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
14706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * SUCH DAMAGE.
25706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
26706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * $FreeBSD: src/usr.sbin/ppp/bundle.c,v 1.136.26.1 2010/12/21 17:10:29 kensmith Exp $
27706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
28706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
29706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/param.h>
30706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/socket.h>
31706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in.h>
32706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/if.h>
33706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/if_tun.h>		/* For TUNS* ioctls */
34706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/route.h>
35706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in_systm.h>
36706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/ip.h>
37706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/un.h>
38706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
39706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <errno.h>
40706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <fcntl.h>
41706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef __OpenBSD__
42706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <util.h>
43706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#else
44706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <libutil.h>
45706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
46706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <paths.h>
47706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdarg.h>
48706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdio.h>
49706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdlib.h>
50706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <string.h>
51706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/uio.h>
52706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/wait.h>
53706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <termios.h>
54706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <unistd.h>
55706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
56706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "layer.h"
57706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "defs.h"
58706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "command.h"
59706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mbuf.h"
60706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "log.h"
61706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "id.h"
62706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "timer.h"
63706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "fsm.h"
64706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iplist.h"
65706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lqr.h"
66706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "hdlc.h"
67706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "throughput.h"
68706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "slcompress.h"
69706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncpaddr.h"
70706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ip.h"
71706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipcp.h"
72706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "filter.h"
73706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "descriptor.h"
74706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "route.h"
75706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lcp.h"
76706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ccp.h"
77706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "link.h"
78706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mp.h"
79706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
80706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "radius.h"
81706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
82706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipv6cp.h"
83706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncp.h"
84706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "bundle.h"
85706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "async.h"
86706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "physical.h"
87706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "auth.h"
88706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "proto.h"
89706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "chap.h"
90706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "tun.h"
91706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "prompt.h"
92706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "chat.h"
93706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "cbcp.h"
94706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "datalink.h"
95706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iface.h"
96706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "server.h"
97706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "probe.h"
98706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NODES
99706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mppe.h"
100706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
101706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
102706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#define SCATTER_SEGMENTS 7  /* version, datalink, name, physical,
103706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                               throughput, throughput, device       */
104706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
105706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#define SEND_MAXFD 3        /* Max file descriptors passed through
106706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                               the local domain socket              */
107706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
108706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int bundle_RemainingIdleTime(struct bundle *);
109706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
110706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic const char * const PhaseNames[] = {
111706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  "Dead", "Establish", "Authenticate", "Network", "Terminate"
112706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh};
113706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
114706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehconst char *
115706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_PhaseName(struct bundle *bundle)
116706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
117706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return bundle->phase <= PHASE_TERMINATE ?
118706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    PhaseNames[bundle->phase] : "unknown";
119706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
120706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
121706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
122706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_NewPhase(struct bundle *bundle, u_int new)
123706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
124706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (new == bundle->phase)
125706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
126706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
127706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (new <= PHASE_TERMINATE)
128706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogPHASE, "bundle: %s\n", PhaseNames[new]);
129706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
130706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  switch (new) {
131706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  case PHASE_DEAD:
132706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->phase = new;
133706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NODES
134706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    MPPE_MasterKeyValid = 0;
135706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
136706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_DisplayPrompts();
137706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    break;
138706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
139706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  case PHASE_ESTABLISH:
140706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->phase = new;
141706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    break;
142706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
143706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  case PHASE_AUTHENTICATE:
144706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->phase = new;
145706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_DisplayPrompts();
146706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    break;
147706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
148706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  case PHASE_NETWORK:
149706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (ncp_fsmStart(&bundle->ncp, bundle)) {
150706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->phase = new;
151706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_DisplayPrompts();
152706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else {
153706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogPHASE, "bundle: All NCPs are disabled\n");
154706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_Close(bundle, NULL, CLOSE_STAYDOWN);
155706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
156706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    break;
157706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
158706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  case PHASE_TERMINATE:
159706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->phase = new;
160706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    mp_Down(&bundle->ncp.mp);
161706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_DisplayPrompts();
162706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    break;
163706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
164706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
165706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
166706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
167706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LayerStart(void *v __unused, struct fsm *fp __unused)
168706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
169706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* The given FSM is about to start up ! */
170706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
171706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
172706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
173706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
174706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Notify(struct bundle *bundle, char c)
175706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
176706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->notify.fd != -1) {
177706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int ret;
178706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
179706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ret = write(bundle->notify.fd, &c, 1);
180706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (c != EX_REDIAL && c != EX_RECONNECT) {
181706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (ret == 1)
182706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogCHAT, "Parent notified of %s\n",
183706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   c == EX_NORMAL ? "success" : "failure");
184706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      else
185706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogERROR, "Failed to notify parent of success\n");
186706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(bundle->notify.fd);
187706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->notify.fd = -1;
188706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else if (ret == 1)
189706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogCHAT, "Parent notified of %s\n", ex_desc(c));
190706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
191706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed to notify parent of %s\n", ex_desc(c));
192706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
193706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
194706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
195706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
196706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_ClearQueues(void *v)
197706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
198706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = (struct bundle *)v;
199706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
200706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
201706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogPHASE, "Clearing choked output queue\n");
202706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->choked.timer);
203706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
204706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
205706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Emergency time:
206706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   *
207706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * We've had a full queue for PACKET_DEL_SECS seconds without being
208706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * able to get rid of any of the packets.  We've probably given up
209706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * on the redials at this point, and the queued data has almost
210706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * definitely been timed out by the layer above.  As this is preventing
211706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * us from reading the TUN_NAME device (we don't want to buffer stuff
212706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * indefinitely), we may as well nuke this data and start with a clean
213706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * slate !
214706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   *
215706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Unfortunately, this has the side effect of shafting any compression
216706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * dictionaries in use (causing the relevant RESET_REQ/RESET_ACK).
217706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
218706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
219706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncp_DeleteQueues(&bundle->ncp);
220706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
221706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    physical_DeleteQueue(dl->physical);
222706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
223706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
224706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
225706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LinkAdded(struct bundle *bundle, struct datalink *dl)
226706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
227706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->phys_type.all |= dl->physical->type;
228706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (dl->state == DATALINK_OPEN)
229706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->phys_type.open |= dl->physical->type;
230706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
231706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
232706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL))
233706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      != bundle->phys_type.open && bundle->session.timer.state == TIMER_STOPPED)
234706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->radius.sessiontime)
235706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_StartSessionTimer(bundle, 0);
236706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
237706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
238706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL))
239706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      != bundle->phys_type.open && bundle->idle.timer.state == TIMER_STOPPED)
240706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /* We may need to start our idle timer */
241706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_StartIdleTimer(bundle, 0);
242706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
243706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
244706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
245706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LinksRemoved(struct bundle *bundle)
246706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
247706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
248706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
249706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->phys_type.all = bundle->phys_type.open = 0;
250706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
251706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_LinkAdded(bundle, dl);
252706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
253706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_CalculateBandwidth(bundle);
254706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  mp_CheckAutoloadTimer(&bundle->ncp.mp);
255706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
256706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL))
257706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      == bundle->phys_type.open) {
258706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
259706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->radius.sessiontime)
260706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_StopSessionTimer(bundle);
261706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
262706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_StopIdleTimer(bundle);
263706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   }
264706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
265706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
266706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
267706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LayerUp(void *v, struct fsm *fp)
268706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
269706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
270706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * The given fsm is now up
271706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's an LCP, adjust our phys_mode.open value and check the
272706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * autoload timer.
273706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the first NCP, calculate our bandwidth
274706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the first NCP, set our ``upat'' time
275706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the first NCP, start the idle timer.
276706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's an NCP, tell our -background parent to go away.
277706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the first NCP, start the autoload timer
278706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
279706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = (struct bundle *)v;
280706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
281706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (fp->proto == PROTO_LCP) {
282706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct physical *p = link2physical(fp->link);
283706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
284706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_LinkAdded(bundle, p->dl);
285706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    mp_CheckAutoloadTimer(&bundle->ncp.mp);
286706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (isncp(fp->proto)) {
287706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (ncp_LayersOpen(&fp->bundle->ncp) == 1) {
288706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_CalculateBandwidth(fp->bundle);
289706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      time(&bundle->upat);
290706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
291706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (bundle->radius.sessiontime)
292706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle_StartSessionTimer(bundle, 0);
293706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
294706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_StartIdleTimer(bundle, 0);
295706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      mp_CheckAutoloadTimer(&fp->bundle->ncp.mp);
296706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
297706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_Notify(bundle, EX_NORMAL);
298706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (fp->proto == PROTO_CCP)
299706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_CalculateBandwidth(fp->bundle);	/* Against ccp_MTUOverhead */
300706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
301706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
302706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
303706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LayerDown(void *v, struct fsm *fp)
304706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
305706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
306706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * The given FSM has been told to come down.
307706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's our last NCP, stop the idle timer.
308706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's our last NCP, clear our ``upat'' value.
309706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's our last NCP, stop the autoload timer
310706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's an LCP, adjust our phys_type.open value and any timers.
311706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's an LCP and we're in multilink mode, adjust our tun
312706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the last LCP, down all NCPs
313706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * speed and make sure our minimum sequence number is adjusted.
314706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
315706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
316706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = (struct bundle *)v;
317706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
318706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (isncp(fp->proto)) {
319706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (ncp_LayersOpen(&fp->bundle->ncp) == 0) {
320706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
321706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (bundle->radius.sessiontime)
322706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle_StopSessionTimer(bundle);
323706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
324706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_StopIdleTimer(bundle);
325706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->upat = 0;
326706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      mp_StopAutoloadTimer(&bundle->ncp.mp);
327706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
328706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (fp->proto == PROTO_LCP) {
329706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct datalink *dl;
330706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct datalink *lost;
331706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int others_active;
332706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
333706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_LinksRemoved(bundle);  /* adjust timers & phys_type values */
334706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
335706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    lost = NULL;
336706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    others_active = 0;
337706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (dl = bundle->links; dl; dl = dl->next) {
338706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (fp == &dl->physical->link.lcp.fsm)
339706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        lost = dl;
340706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP)
341706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        others_active++;
342706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
343706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
344706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->ncp.mp.active) {
345706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_CalculateBandwidth(bundle);
346706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
347706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (lost)
348706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        mp_LinkLost(&bundle->ncp.mp, lost);
349706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      else
350706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogALERT, "Oops, lost an unrecognised datalink (%s) !\n",
351706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   fp->link->name);
352706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
353706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
354706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (!others_active) {
355706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* Down the NCPs.  We don't expect to get fsm_Close()d ourself ! */
356706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ncp2initial(&bundle->ncp);
357706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      mp_Down(&bundle->ncp.mp);
358706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
359706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
360706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
361706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
362706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
363706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LayerFinish(void *v, struct fsm *fp)
364706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
365706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* The given fsm is now down (fp cannot be NULL)
366706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   *
367706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the last NCP, fsm_Close all LCPs
368706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the last NCP, bring any MP layer down
369706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
370706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
371706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = (struct bundle *)v;
372706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
373706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
374706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (isncp(fp->proto) && !ncp_LayersUnfinished(&bundle->ncp)) {
375706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle_Phase(bundle) != PHASE_DEAD)
376706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_NewPhase(bundle, PHASE_TERMINATE);
377706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (dl = bundle->links; dl; dl = dl->next)
378706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (dl->state == DATALINK_OPEN)
379706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        datalink_Close(dl, CLOSE_STAYDOWN);
380706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fsm2initial(fp);
381706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    mp_Down(&bundle->ncp.mp);
382706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
383706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
384706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
385706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
386706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Close(struct bundle *bundle, const char *name, int how)
387706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
388706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
389706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Please close the given datalink.
390706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If name == NULL or name is the last datalink, fsm_Close all NCPs
391706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * (except our MP)
392706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it isn't the last datalink, just Close that datalink.
393706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
394706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
395706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl, *this_dl;
396706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int others_active;
397706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
398706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  others_active = 0;
399706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  this_dl = NULL;
400706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
401706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next) {
402706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (name && !strcasecmp(name, dl->name))
403706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      this_dl = dl;
404706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (name == NULL || this_dl == dl) {
405706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      switch (how) {
406706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        case CLOSE_LCP:
407706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          datalink_DontHangup(dl);
408706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          break;
409706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        case CLOSE_STAYDOWN:
410706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          datalink_StayDown(dl);
411706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          break;
412706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
413706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else if (dl->state != DATALINK_CLOSED && dl->state != DATALINK_HANGUP)
414706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      others_active++;
415706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
416706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
417706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (name && this_dl == NULL) {
418706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "%s: Invalid datalink name\n", name);
419706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
420706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
421706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
422706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!others_active) {
423706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
424706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->radius.sessiontime)
425706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_StopSessionTimer(bundle);
426706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
427706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_StopIdleTimer(bundle);
428706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (ncp_LayersUnfinished(&bundle->ncp))
429706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ncp_Close(&bundle->ncp);
430706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else {
431706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ncp2initial(&bundle->ncp);
432706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      mp_Down(&bundle->ncp.mp);
433706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      for (dl = bundle->links; dl; dl = dl->next)
434706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        datalink_Close(dl, how);
435706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
436706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (this_dl && this_dl->state != DATALINK_CLOSED &&
437706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             this_dl->state != DATALINK_HANGUP)
438706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    datalink_Close(this_dl, how);
439706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
440706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
441706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
442706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Down(struct bundle *bundle, int how)
443706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
444706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
445706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
446706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
447706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    datalink_Down(dl, how);
448706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
449706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
450706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
451706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
452706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
453706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = descriptor2bundle(d);
454706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
455706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int result, nlinks;
456706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_short ifqueue;
457706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  size_t queued;
458706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
459706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  result = 0;
460706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
461706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* If there are aren't many packets queued, look for some more. */
462706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (nlinks = 0, dl = bundle->links; dl; dl = dl->next)
463706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    nlinks++;
464706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
465706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (nlinks) {
466706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    queued = r ? ncp_FillPhysicalQueues(&bundle->ncp, bundle) :
467706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 ncp_QueueLen(&bundle->ncp);
468706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
469706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (r && (bundle->phase == PHASE_NETWORK ||
470706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh              bundle->phys_type.all & PHYS_AUTO)) {
471706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* enough surplus so that we can tell if we're getting swamped */
472706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ifqueue = nlinks > bundle->cfg.ifqueue ? nlinks : bundle->cfg.ifqueue;
473706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (queued < ifqueue) {
474706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /* Not enough - select() for more */
475706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (bundle->choked.timer.state == TIMER_RUNNING)
476706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          timer_Stop(&bundle->choked.timer);	/* Not needed any more */
477706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        FD_SET(bundle->dev.fd, r);
478706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (*n < bundle->dev.fd + 1)
479706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          *n = bundle->dev.fd + 1;
480706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogTIMER, "%s: fdset(r) %d\n", TUN_NAME, bundle->dev.fd);
481706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        result++;
482706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else if (bundle->choked.timer.state == TIMER_STOPPED) {
483706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->choked.timer.func = bundle_ClearQueues;
484706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->choked.timer.name = "output choke";
485706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->choked.timer.load = bundle->cfg.choked.timeout * SECTICKS;
486706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->choked.timer.arg = bundle;
487706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        timer_Start(&bundle->choked.timer);
488706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
489706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
490706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
491706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
492706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
493706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  result += descriptor_UpdateSet(&bundle->radius.desc, r, w, e, n);
494706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
495706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
496706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Which links need a select() ? */
497706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
498706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    result += descriptor_UpdateSet(&dl->desc, r, w, e, n);
499706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
500706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
501706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * This *MUST* be called after the datalink UpdateSet()s as it
502706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * might be ``holding'' one of the datalinks (death-row) and
503706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * wants to be able to de-select() it from the descriptor set.
504706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
505706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  result += descriptor_UpdateSet(&bundle->ncp.mp.server.desc, r, w, e, n);
506706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
507706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return result;
508706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
509706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
510706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
511706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_IsSet(struct fdescriptor *d, const fd_set *fdset)
512706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
513706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = descriptor2bundle(d);
514706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
515706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
516706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
517706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (descriptor_IsSet(&dl->desc, fdset))
518706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
519706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
520706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
521706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (descriptor_IsSet(&bundle->radius.desc, fdset))
522706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
523706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
524706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
525706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
526706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
527706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
528706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return FD_ISSET(bundle->dev.fd, fdset);
529706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
530706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
531706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
532706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DescriptorRead(struct fdescriptor *d __unused, struct bundle *bundle,
533706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      const fd_set *fdset)
534706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
535706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
536706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  unsigned secs;
537706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_int32_t af;
538706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
539706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
540706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    descriptor_Read(&bundle->ncp.mp.server.desc, bundle, fdset);
541706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
542706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
543706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (descriptor_IsSet(&dl->desc, fdset))
544706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      descriptor_Read(&dl->desc, bundle, fdset);
545706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
546706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
547706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (descriptor_IsSet(&bundle->radius.desc, fdset))
548706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    descriptor_Read(&bundle->radius.desc, bundle, fdset);
549706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
550706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
551706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (FD_ISSET(bundle->dev.fd, fdset)) {
552706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct tun_data tun;
553706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int n, pri;
554706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    u_char *data;
555706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    size_t sz;
556706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
557706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->dev.header) {
558706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      data = (u_char *)&tun;
559706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      sz = sizeof tun;
560706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else {
561706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      data = tun.data;
562706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      sz = sizeof tun.data;
563706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
564706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
565706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /* something to read from tun */
566706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
567706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    n = read(bundle->dev.fd, data, sz);
568706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (n < 0) {
569706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogWARN, "%s: read: %s\n", bundle->dev.Name, strerror(errno));
570706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return;
571706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
572706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
573706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->dev.header) {
574706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      n -= sz - sizeof tun.data;
575706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (n <= 0) {
576706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogERROR, "%s: read: Got only %d bytes of data !\n",
577706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   bundle->dev.Name, n);
578706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return;
579706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
580706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      af = ntohl(tun.header.family);
581706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NOINET6
582706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (af != AF_INET && af != AF_INET6)
583706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#else
584706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (af != AF_INET)
585706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
586706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /* XXX: Should be maintaining drop/family counts ! */
587706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return;
588706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else
589706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      af = AF_INET;
590706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
591706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (af == AF_INET && ((struct ip *)tun.data)->ip_dst.s_addr ==
592706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->ncp.ipcp.my_ip.s_addr) {
593706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* we've been asked to send something addressed *to* us :( */
594706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (Enabled(bundle, OPT_LOOPBACK)) {
595706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        pri = PacketCheck(bundle, af, tun.data, n, &bundle->filter.in,
596706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                          NULL, NULL);
597706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (pri >= 0) {
598706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          n += sz - sizeof tun.data;
599706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          write(bundle->dev.fd, data, n);
600706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          log_Printf(LogDEBUG, "Looped back packet addressed to myself\n");
601706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        }
602706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return;
603706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else
604706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
605706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
606706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
607706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
608706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * Process on-demand dialup. Output packets are queued within the tunnel
609706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * device until the appropriate NCP is opened.
610706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
611706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
612706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle_Phase(bundle) == PHASE_DEAD) {
613706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /*
614706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       * Note, we must be in AUTO mode :-/ otherwise our interface should
615706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       * *not* be UP and we can't receive data
616706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       */
617706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      pri = PacketCheck(bundle, af, tun.data, n, &bundle->filter.dial,
618706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                        NULL, NULL);
619706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (pri >= 0)
620706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle_Open(bundle, NULL, PHYS_AUTO, 0);
621706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      else
622706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /*
623706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * Drop the packet.  If we were to queue it, we'd just end up with
624706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * a pile of timed-out data in our output queue by the time we get
625706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * around to actually dialing.  We'd also prematurely reach the
626706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * threshold at which we stop select()ing to read() the tun
627706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * device - breaking auto-dial.
628706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         */
629706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return;
630706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
631706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
632706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    secs = 0;
633706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    pri = PacketCheck(bundle, af, tun.data, n, &bundle->filter.out,
634706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      NULL, &secs);
635706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (pri >= 0) {
636706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* Prepend the number of seconds timeout given in the filter */
637706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      tun.header.timeout = secs;
638706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ncp_Enqueue(&bundle->ncp, af, pri, (char *)&tun, n + sizeof tun.header);
639706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
640706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
641706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
642706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
643706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
644706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DescriptorWrite(struct fdescriptor *d __unused, struct bundle *bundle,
645706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       const fd_set *fdset)
646706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
647706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
648706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int result = 0;
649706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
650706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* This is not actually necessary as struct mpserver doesn't Write() */
651706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
652706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (descriptor_Write(&bundle->ncp.mp.server.desc, bundle, fdset) == 1)
653706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      result++;
654706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
655706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
656706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (descriptor_IsSet(&dl->desc, fdset))
657706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      switch (descriptor_Write(&dl->desc, bundle, fdset)) {
658706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      case -1:
659706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        datalink_ComeDown(dl, CLOSE_NORMAL);
660706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
661706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      case 1:
662706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        result++;
663706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
664706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
665706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return result;
666706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
667706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
668706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
669706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LockTun(struct bundle *bundle)
670706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
671706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  FILE *lockfile;
672706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char pidfile[PATH_MAX];
673706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
674706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  snprintf(pidfile, sizeof pidfile, "%stun%d.pid", _PATH_VARRUN, bundle->unit);
675706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  lockfile = ID0fopen(pidfile, "w");
676706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (lockfile != NULL) {
677706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fprintf(lockfile, "%d\n", (int)getpid());
678706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fclose(lockfile);
679706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
680706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef RELEASE_CRUNCH
681706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  else
682706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "Warning: Can't create %s: %s\n",
683706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               pidfile, strerror(errno));
684706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
685706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
686706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
687706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
688706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_UnlockTun(struct bundle *bundle)
689706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
690706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char pidfile[PATH_MAX];
691706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
692706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  snprintf(pidfile, sizeof pidfile, "%stun%d.pid", _PATH_VARRUN, bundle->unit);
693706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ID0unlink(pidfile);
694706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
695706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
696706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstruct bundle *
697706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Create(const char *prefix, int type, int unit)
698706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
699706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  static struct bundle bundle;		/* there can be only one */
700706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int enoentcount, err, minunit, maxunit;
701706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  const char *ifname;
702706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#if defined(__FreeBSD__) && !defined(NOKLDLOAD)
703706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int kldtried;
704706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
705706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#if defined(TUNSIFMODE) || defined(TUNSLMODE) || defined(TUNSIFHEAD)
706706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int iff;
707706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
708706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
709706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle.iface != NULL) {	/* Already allocated ! */
710706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogALERT, "bundle_Create:  There's only one BUNDLE !\n");
711706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return NULL;
712706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
713706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
714706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (unit == -1) {
715706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    minunit = 0;
716706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    maxunit = -1;
717706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else {
718706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    minunit = unit;
719706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    maxunit = unit + 1;
720706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
721706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  err = ENOENT;
722706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  enoentcount = 0;
723706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#if defined(__FreeBSD__) && !defined(NOKLDLOAD)
724706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  kldtried = 0;
725706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
726706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (bundle.unit = minunit; bundle.unit != maxunit; bundle.unit++) {
727706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    snprintf(bundle.dev.Name, sizeof bundle.dev.Name, "%s%d",
728706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             prefix, bundle.unit);
729706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle.dev.fd = ID0open(bundle.dev.Name, O_RDWR);
730706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle.dev.fd >= 0)
731706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
732706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else if (errno == ENXIO || errno == ENOENT) {
733706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#if defined(__FreeBSD__) && !defined(NOKLDLOAD)
734706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (bundle.unit == minunit && !kldtried++) {
735706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /*
736706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * Attempt to load the tunnel interface KLD if it isn't loaded
737706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * already.
738706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         */
739706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (loadmodules(LOAD_VERBOSLY, "if_tun", NULL))
740706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          bundle.unit--;
741706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        continue;
742706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
743706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
744706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (errno != ENOENT || ++enoentcount > 2) {
745706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        err = errno;
746706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	break;
747706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
748706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else
749706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      err = errno;
750706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
751706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
752706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle.dev.fd < 0) {
753706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (unit == -1)
754706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogWARN, "No available tunnel devices found (%s)\n",
755706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                strerror(err));
756706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
757706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogWARN, "%s%d: %s\n", prefix, unit, strerror(err));
758706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return NULL;
759706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
760706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
761706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_SetTun(bundle.unit);
762706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
763706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ifname = strrchr(bundle.dev.Name, '/');
764706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ifname == NULL)
765706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifname = bundle.dev.Name;
766706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  else
767706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifname++;
768706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
769706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.iface = iface_Create(ifname);
770706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle.iface == NULL) {
771706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    close(bundle.dev.fd);
772706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return NULL;
773706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
774706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
775706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef TUNSIFMODE
776706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Make sure we're POINTOPOINT & IFF_MULTICAST */
777706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iff = IFF_POINTOPOINT | IFF_MULTICAST;
778706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ID0ioctl(bundle.dev.fd, TUNSIFMODE, &iff) < 0)
779706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "bundle_Create: ioctl(TUNSIFMODE): %s\n",
780706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	       strerror(errno));
781706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
782706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
783706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef TUNSLMODE
784706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Make sure we're not prepending sockaddrs */
785706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iff = 0;
786706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ID0ioctl(bundle.dev.fd, TUNSLMODE, &iff) < 0)
787706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "bundle_Create: ioctl(TUNSLMODE): %s\n",
788706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	       strerror(errno));
789706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
790706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
791706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef TUNSIFHEAD
792706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* We want the address family please ! */
793706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iff = 1;
794706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ID0ioctl(bundle.dev.fd, TUNSIFHEAD, &iff) < 0) {
795706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "bundle_Create: ioctl(TUNSIFHEAD): %s\n",
796706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	       strerror(errno));
797706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle.dev.header = 0;
798706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else
799706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle.dev.header = 1;
800706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#else
801706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef __OpenBSD__
802706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Always present for OpenBSD */
803706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.dev.header = 1;
804706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#else
805706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
806706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If TUNSIFHEAD isn't available and we're not OpenBSD, assume
807706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * everything's AF_INET (hopefully the tun device won't pass us
808706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * anything else !).
809706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
810706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.dev.header = 0;
811706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
812706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
813706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
814706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogPHASE, "Using interface: %s\n", ifname);
815706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
816706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.bandwidth = 0;
817706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.routing_seq = 0;
818706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.phase = PHASE_DEAD;
819706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.CleaningUp = 0;
820706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.NatEnabled = 0;
821706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
822706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.fsm.LayerStart = bundle_LayerStart;
823706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.fsm.LayerUp = bundle_LayerUp;
824706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.fsm.LayerDown = bundle_LayerDown;
825706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.fsm.LayerFinish = bundle_LayerFinish;
826706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.fsm.object = &bundle;
827706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
828706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.cfg.idle.timeout = NCP_IDLE_TIMEOUT;
829706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.cfg.idle.min_timeout = 0;
830706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *bundle.cfg.auth.name = '\0';
831706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *bundle.cfg.auth.key = '\0';
832706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.cfg.optmask = (1ull << OPT_IDCHECK) | (1ull << OPT_LOOPBACK) |
833706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       (1ull << OPT_SROUTES) | (1ull << OPT_TCPMSSFIXUP) |
834706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       (1ull << OPT_THROUGHPUT) | (1ull << OPT_UTMP) |
835706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       (1ull << OPT_NAS_IP_ADDRESS) |
836706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       (1ull << OPT_NAS_IDENTIFIER);
837706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NOINET6
838706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  opt_enable(&bundle, OPT_IPCP);
839706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (probe.ipv6_available)
840706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    opt_enable(&bundle, OPT_IPV6CP);
841706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
842706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *bundle.cfg.label = '\0';
843706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.cfg.ifqueue = DEF_IFQUEUE;
844706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.cfg.choked.timeout = CHOKED_TIMEOUT;
845706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.phys_type.all = type;
846706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.phys_type.open = 0;
847706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.upat = 0;
848706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
849706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.links = datalink_Create("deflink", &bundle, type);
850706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle.links == NULL) {
851706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogALERT, "Cannot create data link: %s\n", strerror(errno));
852706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    iface_Destroy(bundle.iface);
853706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle.iface = NULL;
854706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    close(bundle.dev.fd);
855706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return NULL;
856706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
857706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
858706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.desc.type = BUNDLE_DESCRIPTOR;
859706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.desc.UpdateSet = bundle_UpdateSet;
860706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.desc.IsSet = bundle_IsSet;
861706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.desc.Read = bundle_DescriptorRead;
862706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.desc.Write = bundle_DescriptorWrite;
863706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
864706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncp_Init(&bundle.ncp, &bundle);
865706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
866706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(&bundle.filter, '\0', sizeof bundle.filter);
867706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.in.fragok = bundle.filter.in.logok = 1;
868706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.in.name = "IN";
869706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.out.fragok = bundle.filter.out.logok = 1;
870706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.out.name = "OUT";
871706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.dial.name = "DIAL";
872706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.dial.logok = 1;
873706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.alive.name = "ALIVE";
874706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.filter.alive.logok = 1;
875706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  {
876706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int i;
877706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (i = 0; i < MAXFILTERS; i++) {
878706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle.filter.in.rule[i].f_action = A_NONE;
879706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle.filter.out.rule[i].f_action = A_NONE;
880706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle.filter.dial.rule[i].f_action = A_NONE;
881706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle.filter.alive.rule[i].f_action = A_NONE;
882706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
883706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
884706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(&bundle.idle.timer, '\0', sizeof bundle.idle.timer);
885706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.idle.done = 0;
886706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle.notify.fd = -1;
887706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(&bundle.choked.timer, '\0', sizeof bundle.choked.timer);
888706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
889706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  radius_Init(&bundle.radius);
890706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
891706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
892706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Clean out any leftover crud */
893706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iface_Clear(bundle.iface, &bundle.ncp, 0, IFACE_CLEAR_ALL);
894706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
895706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_LockTun(&bundle);
896706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
897706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return &bundle;
898706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
899706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
900706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
901706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DownInterface(struct bundle *bundle)
902706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
903706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  route_IfDelete(bundle, 1);
904706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iface_ClearFlags(bundle->iface->name, IFF_UP);
905706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
906706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
907706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
908706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Destroy(struct bundle *bundle)
909706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
910706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
911706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
912706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
913706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Clean up the interface.  We don't really need to do the timer_Stop()s,
914706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * mp_Down(), iface_Clear() and bundle_DownInterface() unless we're getting
915706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * out under exceptional conditions such as a descriptor exception.
916706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
917706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->idle.timer);
918706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->choked.timer);
919706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  mp_Down(&bundle->ncp.mp);
920706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iface_Clear(bundle->iface, &bundle->ncp, 0, IFACE_CLEAR_ALL);
921706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_DownInterface(bundle);
922706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
923706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
924706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Tell the radius server the bad news */
925706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  radius_Destroy(&bundle->radius);
926706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
927706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
928706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Again, these are all DATALINK_CLOSED unless we're abending */
929706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  dl = bundle->links;
930706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  while (dl)
931706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    dl = datalink_Destroy(dl);
932706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
933706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncp_Destroy(&bundle->ncp);
934706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
935706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  close(bundle->dev.fd);
936706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_UnlockTun(bundle);
937706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
938706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* In case we never made PHASE_NETWORK */
939706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_Notify(bundle, EX_ERRDEAD);
940706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
941706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iface_Destroy(bundle->iface);
942706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->iface = NULL;
943706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
944706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
945706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
946706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LinkClosed(struct bundle *bundle, struct datalink *dl)
947706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
948706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
949706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Our datalink has closed.
950706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * CleanDatalinks() (called from DoLoop()) will remove closed
951706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * BACKGROUND, FOREGROUND and DIRECT links.
952706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If it's the last data link, enter phase DEAD.
953706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   *
954706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * NOTE: dl may not be in our list (bundle_SendDatalink()) !
955706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
956706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
957706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *odl;
958706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int other_links;
959706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
960706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_SetTtyCommandMode(dl);
961706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
962706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  other_links = 0;
963706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (odl = bundle->links; odl; odl = odl->next)
964706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (odl != dl && odl->state != DATALINK_CLOSED)
965706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      other_links++;
966706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
967706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!other_links) {
968706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (dl->physical->type != PHYS_AUTO)	/* Not in -auto mode */
969706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_DownInterface(bundle);
970706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ncp2initial(&bundle->ncp);
971706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    mp_Down(&bundle->ncp.mp);
972706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_NewPhase(bundle, PHASE_DEAD);
973706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
974706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->radius.sessiontime)
975706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_StopSessionTimer(bundle);
976706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
977706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_StopIdleTimer(bundle);
978706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
979706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
980706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
981706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
982706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Open(struct bundle *bundle, const char *name, int mask, int force)
983706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
984706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
985706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Please open the given datalink, or all if name == NULL
986706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
987706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
988706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
989706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
990706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (name == NULL || !strcasecmp(dl->name, name)) {
991706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if ((mask & dl->physical->type) &&
992706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          (dl->state == DATALINK_CLOSED ||
993706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh           (force && dl->state == DATALINK_OPENING &&
994706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            dl->dial.timer.state == TIMER_RUNNING) ||
995706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh           dl->state == DATALINK_READY)) {
996706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        timer_Stop(&dl->dial.timer);	/* We're finished with this */
997706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        datalink_Up(dl, 1, 1);
998706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (mask & PHYS_AUTO)
999706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          break;			/* Only one AUTO link at a time */
1000706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1001706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (name != NULL)
1002706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
1003706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1004706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1005706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1006706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstruct datalink *
1007706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle2datalink(struct bundle *bundle, const char *name)
1008706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1009706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1010706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1011706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (name != NULL) {
1012706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (dl = bundle->links; dl; dl = dl->next)
1013706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (!strcasecmp(dl->name, name))
1014706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return dl;
1015706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (bundle->links && !bundle->links->next)
1016706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return bundle->links;
1017706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1018706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return NULL;
1019706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1020706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1021706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1022706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_ShowLinks(struct cmdargs const *arg)
1023706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1024706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1025706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct pppThroughput *t;
1026706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  unsigned long long octets;
1027706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int secs;
1028706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1029706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = arg->bundle->links; dl; dl = dl->next) {
1030706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    octets = MAX(dl->physical->link.stats.total.in.OctetsPerSecond,
1031706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 dl->physical->link.stats.total.out.OctetsPerSecond);
1032706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1033706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "Name: %s [%s, %s]",
1034706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  dl->name, mode2Nam(dl->physical->type), datalink_State(dl));
1035706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (dl->physical->link.stats.total.rolling && dl->state == DATALINK_OPEN)
1036706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, " bandwidth %d, %llu bps (%llu bytes/sec)",
1037706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    dl->mp.bandwidth ? dl->mp.bandwidth :
1038706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                                       physical_GetSpeed(dl->physical),
1039706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    octets * 8, octets);
1040706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "\n");
1041706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1042706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1043706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  t = &arg->bundle->ncp.mp.link.stats.total;
1044706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  octets = MAX(t->in.OctetsPerSecond, t->out.OctetsPerSecond);
1045706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  secs = t->downtime ? 0 : throughput_uptime(t);
1046706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (secs > t->SamplePeriod)
1047706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    secs = t->SamplePeriod;
1048706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (secs)
1049706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "Currently averaging %llu bps (%llu bytes/sec)"
1050706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  " over the last %d secs\n", octets * 8, octets, secs);
1051706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1052706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
1053706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1054706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1055706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic const char *
1056706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehoptval(struct bundle *bundle, int opt)
1057706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1058706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return Enabled(bundle, opt) ? "enabled" : "disabled";
1059706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1060706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1061706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1062706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_ShowStatus(struct cmdargs const *arg)
1063706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1064706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int remaining;
1065706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1066706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, "Phase %s\n", bundle_PhaseName(arg->bundle));
1067706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Device:        %s\n", arg->bundle->dev.Name);
1068706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Interface:     %s @ %lubps",
1069706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                arg->bundle->iface->name, arg->bundle->bandwidth);
1070706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1071706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->bundle->upat) {
1072706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int secs = bundle_Uptime(arg->bundle);
1073706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1074706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, ", up time %d:%02d:%02d", secs / 3600,
1075706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  (secs / 60) % 60, secs % 60);
1076706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1077706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, "\n Queued:        %lu of %u\n",
1078706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                (unsigned long)ncp_QueueLen(&arg->bundle->ncp),
1079706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                arg->bundle->cfg.ifqueue);
1080706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1081706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, "\nDefaults:\n");
1082706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Label:             %s\n",
1083706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                arg->bundle->cfg.label);
1084706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Auth name:         %s\n",
1085706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                arg->bundle->cfg.auth.name);
1086706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Diagnostic socket: ");
1087706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (*server.cfg.sockname != '\0') {
1088706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "%s", server.cfg.sockname);
1089706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (server.cfg.mask != (mode_t)-1)
1090706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, ", mask 0%03o", (int)server.cfg.mask);
1091706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "%s\n", server.fd == -1 ? " (not open)" : "");
1092706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (server.cfg.port != 0)
1093706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "TCP port %d%s\n", server.cfg.port,
1094706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  server.fd == -1 ? " (not open)" : "");
1095706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  else
1096706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "none\n");
1097706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1098706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Choked Timer:      %us\n",
1099706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                arg->bundle->cfg.choked.timeout);
1100706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1101706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
1102706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  radius_Show(&arg->bundle->radius, arg->prompt);
1103706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
1104706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1105706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Idle Timer:        ");
1106706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->bundle->cfg.idle.timeout) {
1107706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "%us", arg->bundle->cfg.idle.timeout);
1108706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (arg->bundle->cfg.idle.min_timeout)
1109706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, ", min %us",
1110706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    arg->bundle->cfg.idle.min_timeout);
1111706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    remaining = bundle_RemainingIdleTime(arg->bundle);
1112706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (remaining != -1)
1113706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, " (%ds remaining)", remaining);
1114706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "\n");
1115706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else
1116706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "disabled\n");
1117706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1118706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Filter Decap:      %-20.20s",
1119706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_FILTERDECAP));
1120706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " ID check:          %s\n",
1121706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_IDCHECK));
1122706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Iface-Alias:       %-20.20s",
1123706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_IFACEALIAS));
1124706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NOINET6
1125706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " IPCP:              %s\n",
1126706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_IPCP));
1127706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " IPV6CP:            %-20.20s",
1128706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_IPV6CP));
1129706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
1130706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Keep-Session:      %s\n",
1131706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_KEEPSESSION));
1132706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Loopback:          %-20.20s",
1133706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_LOOPBACK));
1134706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " PasswdAuth:        %s\n",
1135706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_PASSWDAUTH));
1136706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Proxy:             %-20.20s",
1137706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_PROXY));
1138706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Proxyall:          %s\n",
1139706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_PROXYALL));
1140706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Sticky Routes:     %-20.20s",
1141706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_SROUTES));
1142706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " TCPMSS Fixup:      %s\n",
1143706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_TCPMSSFIXUP));
1144706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Throughput:        %-20.20s",
1145706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_THROUGHPUT));
1146706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " Utmp Logging:      %s\n",
1147706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_UTMP));
1148706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " NAS-IP-Address:    %-20.20s",
1149706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_NAS_IP_ADDRESS));
1150706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, " NAS-Identifier:    %s\n",
1151706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                optval(arg->bundle, OPT_NAS_IDENTIFIER));
1152706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1153706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
1154706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1155706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1156706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
1157706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_IdleTimeout(void *v)
1158706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1159706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = (struct bundle *)v;
1160706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1161706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogPHASE, "Idle timer expired\n");
1162706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_StopIdleTimer(bundle);
1163706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_Close(bundle, NULL, CLOSE_STAYDOWN);
1164706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1165706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1166706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*
1167706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *  Start Idle timer. If timeout is reached, we call bundle_Close() to
1168706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *  close LCP and link.
1169706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
1170706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1171706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_StartIdleTimer(struct bundle *bundle, unsigned secs)
1172706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1173706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->idle.timer);
1174706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL)) !=
1175706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->phys_type.open && bundle->cfg.idle.timeout) {
1176706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    time_t now = time(NULL);
1177706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1178706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (secs == 0)
1179706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      secs = bundle->cfg.idle.timeout;
1180706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1181706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /* We want at least `secs' */
1182706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->cfg.idle.min_timeout > secs && bundle->upat) {
1183706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      unsigned up = now - bundle->upat;
1184706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1185706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (bundle->cfg.idle.min_timeout > up &&
1186706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          bundle->cfg.idle.min_timeout - up > (long long)secs)
1187706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /* Only increase from the current `remaining' value */
1188706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        secs = bundle->cfg.idle.min_timeout - up;
1189706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1190706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->idle.timer.func = bundle_IdleTimeout;
1191706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->idle.timer.name = "idle";
1192706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->idle.timer.load = secs * SECTICKS;
1193706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->idle.timer.arg = bundle;
1194706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    timer_Start(&bundle->idle.timer);
1195706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->idle.done = now + secs;
1196706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1197706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1198706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1199706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1200706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_SetIdleTimer(struct bundle *bundle, unsigned timeout,
1201706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		    unsigned min_timeout)
1202706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1203706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->cfg.idle.timeout = timeout;
1204706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->cfg.idle.min_timeout = min_timeout;
1205706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ncp_LayersOpen(&bundle->ncp))
1206706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_StartIdleTimer(bundle, 0);
1207706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1208706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1209706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1210706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_StopIdleTimer(struct bundle *bundle)
1211706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1212706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->idle.timer);
1213706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->idle.done = 0;
1214706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1215706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1216706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
1217706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_RemainingIdleTime(struct bundle *bundle)
1218706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1219706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->idle.done)
1220706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return bundle->idle.done - time(NULL);
1221706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return -1;
1222706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1223706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1224706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
1225706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1226706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
1227706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_SessionTimeout(void *v)
1228706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1229706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = (struct bundle *)v;
1230706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1231706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogPHASE, "Session-Timeout timer expired\n");
1232706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_StopSessionTimer(bundle);
1233706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_Close(bundle, NULL, CLOSE_STAYDOWN);
1234706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1235706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1236706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1237706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_StartSessionTimer(struct bundle *bundle, unsigned secs)
1238706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1239706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->session.timer);
1240706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL)) !=
1241706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->phys_type.open && bundle->radius.sessiontime) {
1242706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    time_t now = time(NULL);
1243706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1244706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (secs == 0)
1245706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      secs = bundle->radius.sessiontime;
1246706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1247706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->session.timer.func = bundle_SessionTimeout;
1248706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->session.timer.name = "session";
1249706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->session.timer.load = secs * SECTICKS;
1250706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->session.timer.arg = bundle;
1251706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    timer_Start(&bundle->session.timer);
1252706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->session.done = now + secs;
1253706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1254706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1255706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1256706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1257706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_StopSessionTimer(struct bundle *bundle)
1258706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1259706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  timer_Stop(&bundle->session.timer);
1260706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->session.done = 0;
1261706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1262706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1263706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
1264706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1265706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1266706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_IsDead(struct bundle *bundle)
1267706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1268706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return !bundle->links || (bundle->phase == PHASE_DEAD && bundle->CleaningUp);
1269706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1270706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1271706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct datalink *
1272706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DatalinkLinkout(struct bundle *bundle, struct datalink *dl)
1273706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1274706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink **dlp;
1275706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1276706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dlp = &bundle->links; *dlp; dlp = &(*dlp)->next)
1277706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (*dlp == dl) {
1278706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      *dlp = dl->next;
1279706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      dl->next = NULL;
1280706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_LinksRemoved(bundle);
1281706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return dl;
1282706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1283706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1284706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return NULL;
1285706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1286706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1287706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
1288706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DatalinkLinkin(struct bundle *bundle, struct datalink *dl)
1289706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1290706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink **dlp = &bundle->links;
1291706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1292706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  while (*dlp)
1293706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    dlp = &(*dlp)->next;
1294706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1295706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *dlp = dl;
1296706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  dl->next = NULL;
1297706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1298706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_LinkAdded(bundle, dl);
1299706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  mp_CheckAutoloadTimer(&bundle->ncp.mp);
1300706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1301706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1302706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1303706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_CleanDatalinks(struct bundle *bundle)
1304706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1305706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink **dlp = &bundle->links;
1306706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int found = 0;
1307706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1308706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  while (*dlp)
1309706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if ((*dlp)->state == DATALINK_CLOSED &&
1310706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        (*dlp)->physical->type &
1311706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        (PHYS_DIRECT|PHYS_BACKGROUND|PHYS_FOREGROUND)) {
1312706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      *dlp = datalink_Destroy(*dlp);
1313706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      found++;
1314706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else
1315706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      dlp = &(*dlp)->next;
1316706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1317706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (found)
1318706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle_LinksRemoved(bundle);
1319706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1320706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1321706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1322706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DatalinkClone(struct bundle *bundle, struct datalink *dl,
1323706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                     const char *name)
1324706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1325706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle2datalink(bundle, name)) {
1326706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "Clone: %s: name already exists\n", name);
1327706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
1328706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1329706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1330706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_DatalinkLinkin(bundle, datalink_Clone(dl, name));
1331706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 1;
1332706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1333706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1334706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1335706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_DatalinkRemove(struct bundle *bundle, struct datalink *dl)
1336706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1337706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  dl = bundle_DatalinkLinkout(bundle, dl);
1338706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (dl)
1339706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    datalink_Destroy(dl);
1340706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1341706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1342706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1343706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_SetLabel(struct bundle *bundle, const char *label)
1344706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1345706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (label)
1346706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    strncpy(bundle->cfg.label, label, sizeof bundle->cfg.label - 1);
1347706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  else
1348706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    *bundle->cfg.label = '\0';
1349706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1350706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1351706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehconst char *
1352706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_GetLabel(struct bundle *bundle)
1353706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1354706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return *bundle->cfg.label ? bundle->cfg.label : NULL;
1355706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1356706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1357706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1358706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_LinkSize()
1359706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1360706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct iovec iov[SCATTER_SEGMENTS];
1361706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int niov, expect, f;
1362706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1363706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iov[0].iov_len = strlen(Version) + 1;
1364706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iov[0].iov_base = NULL;
1365706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  niov = 1;
1366706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (datalink2iov(NULL, iov, &niov, SCATTER_SEGMENTS, NULL, NULL) == -1) {
1367706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "Cannot determine space required for link\n");
1368706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
1369706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1370706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1371706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (f = expect = 0; f < niov; f++)
1372706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    expect += iov[f].iov_len;
1373706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1374706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return expect;
1375706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1376706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1377706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1378706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_ReceiveDatalink(struct bundle *bundle, int s)
1379706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1380706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int) * SEND_MAXFD];
1381706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int niov, expect, f, *fd, nfd, onfd;
1382706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ssize_t got;
1383706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct iovec iov[SCATTER_SEGMENTS];
1384706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct cmsghdr *cmsg;
1385706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct msghdr msg;
1386706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1387706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  pid_t pid;
1388706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1389706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogPHASE, "Receiving datalink\n");
1390706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1391706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
1392706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Create our scatter/gather array - passing NULL gets the space
1393706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * allocation requirement rather than actually flattening the
1394706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * structures.
1395706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
1396706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iov[0].iov_len = strlen(Version) + 1;
1397706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iov[0].iov_base = NULL;
1398706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  niov = 1;
1399706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (datalink2iov(NULL, iov, &niov, SCATTER_SEGMENTS, NULL, NULL) == -1) {
1400706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "Cannot determine space required for link\n");
1401706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1402706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1403706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1404706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Allocate the scatter/gather array for recvmsg() */
1405706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (f = expect = 0; f < niov; f++) {
1406706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if ((iov[f].iov_base = malloc(iov[f].iov_len)) == NULL) {
1407706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Cannot allocate space to receive link\n");
1408706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return;
1409706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1410706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (f)
1411706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      expect += iov[f].iov_len;
1412706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1413706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1414706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Set up our message */
1415706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  cmsg = (struct cmsghdr *)cmsgbuf;
1416706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  cmsg->cmsg_len = sizeof cmsgbuf;
1417706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  cmsg->cmsg_level = SOL_SOCKET;
1418706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  cmsg->cmsg_type = 0;
1419706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1420706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(&msg, '\0', sizeof msg);
1421706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  msg.msg_name = NULL;
1422706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  msg.msg_namelen = 0;
1423706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  msg.msg_iov = iov;
1424706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  msg.msg_iovlen = 1;		/* Only send the version at the first pass */
1425706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  msg.msg_control = cmsgbuf;
1426706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  msg.msg_controllen = sizeof cmsgbuf;
1427706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1428706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogDEBUG, "Expecting %u scatter/gather bytes\n",
1429706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             (unsigned)iov[0].iov_len);
1430706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1431706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((got = recvmsg(s, &msg, MSG_WAITALL)) != (ssize_t)iov[0].iov_len) {
1432706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (got == -1)
1433706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed recvmsg: %s\n", strerror(errno));
1434706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
1435706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed recvmsg: Got %zd, not %u\n",
1436706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 got, (unsigned)iov[0].iov_len);
1437706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (niov--)
1438706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      free(iov[niov].iov_base);
1439706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1440706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1441706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1442706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
1443706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "Recvmsg: no descriptors received !\n");
1444706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (niov--)
1445706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      free(iov[niov].iov_base);
1446706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1447706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1448706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1449706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fd = (int *)CMSG_DATA(cmsg);
1450706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  nfd = ((caddr_t)cmsg + cmsg->cmsg_len - (caddr_t)fd) / sizeof(int);
1451706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1452706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (nfd < 2) {
1453706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "Recvmsg: %d descriptor%s received (too few) !\n",
1454706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               nfd, nfd == 1 ? "" : "s");
1455706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (nfd--)
1456706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[nfd]);
1457706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (niov--)
1458706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      free(iov[niov].iov_base);
1459706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1460706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1461706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1462706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
1463706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * We've successfully received two or more open file descriptors
1464706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * through our socket, plus a version string.  Make sure it's the
1465706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * correct version, and drop the connection if it's not.
1466706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
1467706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (strncmp(Version, iov[0].iov_base, iov[0].iov_len)) {
1468706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "Cannot receive datalink, incorrect version"
1469706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               " (\"%.*s\", not \"%s\")\n", (int)iov[0].iov_len,
1470706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               (char *)iov[0].iov_base, Version);
1471706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (nfd--)
1472706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[nfd]);
1473706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (niov--)
1474706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      free(iov[niov].iov_base);
1475706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1476706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1477706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1478706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
1479706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Everything looks good.  Send the other side our process id so that
1480706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * they can transfer lock ownership, and wait for them to send the
1481706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * actual link data.
1482706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
1483706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  pid = getpid();
1484706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((got = write(fd[1], &pid, sizeof pid)) != sizeof pid) {
1485706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (got == -1)
1486706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed write: %s\n", strerror(errno));
1487706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
1488706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed write: Got %zd, not %d\n", got,
1489706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 (int)(sizeof pid));
1490706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (nfd--)
1491706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[nfd]);
1492706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (niov--)
1493706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      free(iov[niov].iov_base);
1494706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1495706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1496706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1497706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((got = readv(fd[1], iov + 1, niov - 1)) != expect) {
1498706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (got == -1)
1499706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed write: %s\n", strerror(errno));
1500706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
1501706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed write: Got %zd, not %d\n", got, expect);
1502706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (nfd--)
1503706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[nfd]);
1504706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (niov--)
1505706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      free(iov[niov].iov_base);
1506706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1507706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1508706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  close(fd[1]);
1509706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1510706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  onfd = nfd;	/* We've got this many in our array */
1511706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  nfd -= 2;	/* Don't include p->fd and our reply descriptor */
1512706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  niov = 1;	/* Skip the version id */
1513706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  dl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, fd[0],
1514706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    fd + 2, &nfd);
1515706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (dl) {
1516706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1517706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (nfd) {
1518706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "bundle_ReceiveDatalink: Failed to handle %d "
1519706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 "auxiliary file descriptors (%d remain)\n", onfd, nfd);
1520706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      datalink_Destroy(dl);
1521706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      while (nfd--)
1522706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        close(fd[onfd--]);
1523706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[0]);
1524706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else {
1525706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_DatalinkLinkin(bundle, dl);
1526706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      datalink_AuthOk(dl);
1527706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_CalculateBandwidth(dl->bundle);
1528706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1529706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else {
1530706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (nfd--)
1531706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[onfd--]);
1532706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    close(fd[0]);
1533706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    close(fd[1]);
1534706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1535706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1536706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  free(iov[0].iov_base);
1537706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1538706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1539706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1540706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun)
1541706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1542706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char cmsgbuf[CMSG_SPACE(sizeof(int) * SEND_MAXFD)];
1543706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  const char *constlock;
1544706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *lock;
1545706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct cmsghdr *cmsg;
1546706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct msghdr msg;
1547706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct iovec iov[SCATTER_SEGMENTS];
1548706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int niov, f, expect, newsid, fd[SEND_MAXFD], nfd, reply[2];
1549706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ssize_t got;
1550706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  pid_t newpid;
1551706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1552706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogPHASE, "Transmitting datalink %s\n", dl->name);
1553706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1554706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Record the base device name for a lock transfer later */
1555706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  constlock = physical_LockedDevice(dl->physical);
1556706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (constlock) {
1557706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    lock = alloca(strlen(constlock) + 1);
1558706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    strcpy(lock, constlock);
1559706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else
1560706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    lock = NULL;
1561706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1562706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_LinkClosed(dl->bundle, dl);
1563706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_DatalinkLinkout(dl->bundle, dl);
1564706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1565706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Build our scatter/gather array */
1566706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iov[0].iov_len = strlen(Version) + 1;
1567706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  iov[0].iov_base = strdup(Version);
1568706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  niov = 1;
1569706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  nfd = 0;
1570706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1571706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fd[0] = datalink2iov(dl, iov, &niov, SCATTER_SEGMENTS, fd + 2, &nfd);
1572706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1573706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (fd[0] != -1 && socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, reply) != -1) {
1574706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
1575706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * fd[1] is used to get the peer process id back, then to confirm that
1576706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * we've transferred any device locks to that process id.
1577706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
1578706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fd[1] = reply[1];
1579706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1580706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    nfd += 2;			/* Include fd[0] and fd[1] */
1581706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    memset(&msg, '\0', sizeof msg);
1582706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1583706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_name = NULL;
1584706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_namelen = 0;
1585706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
1586706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * Only send the version to start...  We used to send the whole lot, but
1587706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * this caused problems with our RECVBUF size as a single link is about
1588706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * 22k !  This way, we should bump into no limits.
1589706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
1590706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_iovlen = 1;
1591706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_iov = iov;
1592706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_control = cmsgbuf;
1593706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_controllen = CMSG_SPACE(sizeof(int) * nfd);
1594706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    msg.msg_flags = 0;
1595706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1596706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cmsg = (struct cmsghdr *)cmsgbuf;
1597706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cmsg->cmsg_len = msg.msg_controllen;
1598706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cmsg->cmsg_level = SOL_SOCKET;
1599706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cmsg->cmsg_type = SCM_RIGHTS;
1600706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1601706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (f = 0; f < nfd; f++)
1602706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      *((int *)CMSG_DATA(cmsg) + f) = fd[f];
1603706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1604706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (f = 1, expect = 0; f < niov; f++)
1605706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      expect += iov[f].iov_len;
1606706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1607706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (setsockopt(reply[0], SOL_SOCKET, SO_SNDBUF, &expect, sizeof(int)) == -1)
1608706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "setsockopt(SO_RCVBUF, %d): %s\n", expect,
1609706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 strerror(errno));
1610706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (setsockopt(reply[1], SOL_SOCKET, SO_RCVBUF, &expect, sizeof(int)) == -1)
1611706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "setsockopt(SO_RCVBUF, %d): %s\n", expect,
1612706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 strerror(errno));
1613706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1614706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogDEBUG, "Sending %d descriptor%s and %u bytes in scatter"
1615706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               "/gather array\n", nfd, nfd == 1 ? "" : "s",
1616706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               (unsigned)iov[0].iov_len);
1617706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1618706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if ((got = sendmsg(s, &msg, 0)) == -1)
1619706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "Failed sendmsg: %s: %s\n",
1620706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 sun->sun_path, strerror(errno));
1621706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else if (got != (ssize_t)iov[0].iov_len)
1622706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "%s: Failed initial sendmsg: Only sent %zd of %u\n",
1623706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 sun->sun_path, got, (unsigned)iov[0].iov_len);
1624706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else {
1625706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* We must get the ACK before closing the descriptor ! */
1626706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      int res;
1627706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1628706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if ((got = read(reply[0], &newpid, sizeof newpid)) == sizeof newpid) {
1629706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogDEBUG, "Received confirmation from pid %ld\n",
1630706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   (long)newpid);
1631706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (lock && (res = ID0uu_lock_txfr(lock, newpid)) != UU_LOCK_OK)
1632706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            log_Printf(LogERROR, "uu_lock_txfr: %s\n", uu_lockerr(res));
1633706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1634706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogDEBUG, "Transmitting link (%d bytes)\n", expect);
1635706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if ((got = writev(reply[0], iov + 1, niov - 1)) != expect) {
1636706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          if (got == -1)
1637706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            log_Printf(LogERROR, "%s: Failed writev: %s\n",
1638706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       sun->sun_path, strerror(errno));
1639706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          else
1640706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            log_Printf(LogERROR, "%s: Failed writev: Wrote %zd of %d\n",
1641706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       sun->sun_path, got, expect);
1642706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        }
1643706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else if (got == -1)
1644706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogERROR, "%s: Failed socketpair read: %s\n",
1645706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   sun->sun_path, strerror(errno));
1646706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      else
1647706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogERROR, "%s: Failed socketpair read: Got %zd of %d\n",
1648706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   sun->sun_path, got, (int)(sizeof newpid));
1649706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1650706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1651706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    close(reply[0]);
1652706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    close(reply[1]);
1653706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1654706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    newsid = Enabled(dl->bundle, OPT_KEEPSESSION) ||
1655706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             tcgetpgrp(fd[0]) == getpgrp();
1656706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (nfd)
1657706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fd[--nfd]);
1658706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (newsid)
1659706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle_setsid(dl->bundle, got != -1);
1660706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1661706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  close(s);
1662706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1663706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  while (niov--)
1664706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    free(iov[niov].iov_base);
1665706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1666706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1667706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1668706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_RenameDatalink(struct bundle *bundle, struct datalink *ndl,
1669706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      const char *name)
1670706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1671706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1672706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1673706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!strcasecmp(ndl->name, name))
1674706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
1675706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1676706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
1677706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (!strcasecmp(dl->name, name))
1678706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 0;
1679706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1680706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  datalink_Rename(ndl, name);
1681706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 1;
1682706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1683706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1684706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1685706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_SetMode(struct bundle *bundle, struct datalink *dl, int mode)
1686706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1687706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int omode;
1688706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1689706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  omode = dl->physical->type;
1690706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (omode == mode)
1691706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
1692706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1693706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (mode == PHYS_AUTO && !(bundle->phys_type.all & PHYS_AUTO))
1694706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /* First auto link */
1695706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle->ncp.ipcp.peer_ip.s_addr == INADDR_ANY) {
1696706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogWARN, "You must `set ifaddr' or `open' before"
1697706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 " changing mode to %s\n", mode2Nam(mode));
1698706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 0;
1699706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1700706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1701706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!datalink_SetMode(dl, mode))
1702706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
1703706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1704706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (mode == PHYS_AUTO && !(bundle->phys_type.all & PHYS_AUTO) &&
1705706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->phase != PHASE_NETWORK)
1706706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /* First auto link, we need an interface */
1707706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ipcp_InterfaceUp(&bundle->ncp.ipcp);
1708706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1709706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Regenerate phys_type and adjust idle timer */
1710706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle_LinksRemoved(bundle);
1711706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1712706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 1;
1713706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1714706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1715706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1716706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_setsid(struct bundle *bundle, int holdsession)
1717706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1718706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
1719706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Lose the current session.  This means getting rid of our pid
1720706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * too so that the tty device will really go away, and any getty
1721706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * etc will be allowed to restart.
1722706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
1723706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  pid_t pid, orig;
1724706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int fds[2];
1725706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char done;
1726706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1727706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1728706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!holdsession && bundle_IsDead(bundle)) {
1729706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
1730706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * No need to lose our session after all... we're going away anyway
1731706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     *
1732706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * We should really stop the timer and pause if holdsession is set and
1733706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * the bundle's dead, but that leaves other resources lying about :-(
1734706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
1735706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1736706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1737706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1738706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  orig = getpid();
1739706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (pipe(fds) == -1) {
1740706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "pipe: %s\n", strerror(errno));
1741706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
1742706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1743706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  switch ((pid = fork())) {
1744706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case -1:
1745706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogERROR, "fork: %s\n", strerror(errno));
1746706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fds[0]);
1747706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fds[1]);
1748706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return;
1749706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case 0:
1750706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fds[1]);
1751706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      read(fds[0], &done, 1);		/* uu_locks are mine ! */
1752706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fds[0]);
1753706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (pipe(fds) == -1) {
1754706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogERROR, "pipe(2): %s\n", strerror(errno));
1755706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return;
1756706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1757706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      switch ((pid = fork())) {
1758706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        case -1:
1759706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          log_Printf(LogERROR, "fork(2): %s\n", strerror(errno));
1760706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fds[0]);
1761706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fds[1]);
1762706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          return;
1763706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        case 0:
1764706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fds[1]);
1765706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          bundle_LockTun(bundle);	/* update pid */
1766706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          read(fds[0], &done, 1);	/* uu_locks are mine ! */
1767706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fds[0]);
1768706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          setsid();
1769706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          bundle_ChangedPID(bundle);
1770706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          log_Printf(LogDEBUG, "%ld -> %ld: %s session control\n",
1771706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                     (long)orig, (long)getpid(),
1772706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                     holdsession ? "Passed" : "Dropped");
1773706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          timer_InitService(0);		/* Start the Timer Service */
1774706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          break;
1775706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        default:
1776706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fds[0]);
1777706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          /* Give away all our physical locks (to the final process) */
1778706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          for (dl = bundle->links; dl; dl = dl->next)
1779706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            if (dl->state != DATALINK_CLOSED)
1780706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh              physical_ChangedPid(dl->physical, pid);
1781706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          write(fds[1], "!", 1);	/* done */
1782706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fds[1]);
1783706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          _exit(0);
1784706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          break;
1785706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1786706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
1787706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    default:
1788706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fds[0]);
1789706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* Give away all our physical locks (to the intermediate process) */
1790706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      for (dl = bundle->links; dl; dl = dl->next)
1791706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (dl->state != DATALINK_CLOSED)
1792706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          physical_ChangedPid(dl->physical, pid);
1793706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      write(fds[1], "!", 1);	/* done */
1794706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      close(fds[1]);
1795706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (holdsession) {
1796706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        int fd, status;
1797706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1798706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        timer_TermService();
1799706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        signal(SIGPIPE, SIG_DFL);
1800706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        signal(SIGALRM, SIG_DFL);
1801706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        signal(SIGHUP, SIG_DFL);
1802706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        signal(SIGTERM, SIG_DFL);
1803706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        signal(SIGINT, SIG_DFL);
1804706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        signal(SIGQUIT, SIG_DFL);
1805706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        for (fd = getdtablesize(); fd >= 0; fd--)
1806706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          close(fd);
1807706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /*
1808706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * Reap the intermediate process.  As we're not exiting but the
1809706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * intermediate is, we don't want it to become defunct.
1810706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         */
1811706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        waitpid(pid, &status, 0);
1812706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /* Tweak our process arguments.... */
1813706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        SetTitle("session owner");
1814706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NOSUID
1815706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        setuid(ID0realuid());
1816706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
1817706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /*
1818706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * Hang around for a HUP.  This should happen as soon as the
1819706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * ppp that we passed our ctty descriptor to closes it.
1820706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * NOTE: If this process dies, the passed descriptor becomes
1821706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         *       invalid and will give a select() error by setting one
1822706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         *       of the error fds, aborting the other ppp.  We don't
1823706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         *       want that to happen !
1824706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         */
1825706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        pause();
1826706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1827706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      _exit(0);
1828706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
1829706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1830706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1831706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1832706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehunsigned
1833706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_HighestState(struct bundle *bundle)
1834706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1835706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1836706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  unsigned result = DATALINK_CLOSED;
1837706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1838706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
1839706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (result < dl->state)
1840706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      result = dl->state;
1841706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1842706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return result;
1843706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1844706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1845706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1846706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Exception(struct bundle *bundle, int fd)
1847706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1848706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1849706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1850706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
1851706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (dl->physical->fd == fd) {
1852706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      datalink_Down(dl, CLOSE_NORMAL);
1853706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
1854706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1855706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1856706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
1857706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1858706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1859706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1860706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_AdjustFilters(struct bundle *bundle, struct ncpaddr *local,
1861706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                     struct ncpaddr *remote)
1862706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1863706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.in, local, remote, NULL);
1864706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.out, local, remote, NULL);
1865706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.dial, local, remote, NULL);
1866706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.alive, local, remote, NULL);
1867706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1868706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1869706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1870706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_AdjustDNS(struct bundle *bundle)
1871706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1872706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct in_addr *dns = bundle->ncp.ipcp.ns.dns;
1873706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1874706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.in, NULL, NULL, dns);
1875706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.out, NULL, NULL, dns);
1876706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.dial, NULL, NULL, dns);
1877706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  filter_AdjustAddr(&bundle->filter.alive, NULL, NULL, dns);
1878706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1879706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1880706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1881706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_CalculateBandwidth(struct bundle *bundle)
1882706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1883706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1884706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int sp, overhead, maxoverhead;
1885706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1886706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->bandwidth = 0;
1887706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bundle->iface->mtu = 0;
1888706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  maxoverhead = 0;
1889706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1890706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next) {
1891706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    overhead = ccp_MTUOverhead(&dl->physical->link.ccp);
1892706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (maxoverhead < overhead)
1893706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      maxoverhead = overhead;
1894706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (dl->state == DATALINK_OPEN) {
1895706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if ((sp = dl->mp.bandwidth) == 0 &&
1896706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          (sp = physical_GetSpeed(dl->physical)) == 0)
1897706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogDEBUG, "%s: %s: Cannot determine bandwidth\n",
1898706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   dl->name, dl->physical->name.full);
1899706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      else
1900706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->bandwidth += sp;
1901706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (!bundle->ncp.mp.active) {
1902706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle->iface->mtu = dl->physical->link.lcp.his_mru;
1903706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
1904706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1905706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1906706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1907706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1908706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->bandwidth == 0)
1909706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->bandwidth = 115200;		/* Shrug */
1910706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1911706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->ncp.mp.active) {
1912706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->iface->mtu = bundle->ncp.mp.peer_mrru;
1913706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    overhead = ccp_MTUOverhead(&bundle->ncp.mp.link.ccp);
1914706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (maxoverhead < overhead)
1915706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      maxoverhead = overhead;
1916706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (!bundle->iface->mtu)
1917706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->iface->mtu = DEF_MRU;
1918706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1919706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
1920706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->radius.valid && bundle->radius.mtu &&
1921706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bundle->radius.mtu < bundle->iface->mtu) {
1922706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogLCP, "Reducing MTU to radius value %lu\n",
1923706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               bundle->radius.mtu);
1924706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->iface->mtu = bundle->radius.mtu;
1925706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1926706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
1927706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1928706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (maxoverhead) {
1929706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogLCP, "Reducing MTU from %lu to %lu (CCP requirement)\n",
1930706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               bundle->iface->mtu, bundle->iface->mtu - maxoverhead);
1931706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    bundle->iface->mtu -= maxoverhead;
1932706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1933706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1934706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  tun_configure(bundle);
1935706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1936706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  route_UpdateMTU(bundle);
1937706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1938706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1939706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
1940706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_AutoAdjust(struct bundle *bundle, int percent, int what)
1941706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1942706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl, *choice, *otherlinkup;
1943706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1944706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  choice = otherlinkup = NULL;
1945706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (dl = bundle->links; dl; dl = dl->next)
1946706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (dl->physical->type == PHYS_AUTO) {
1947706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (dl->state == DATALINK_OPEN) {
1948706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (what == AUTO_DOWN) {
1949706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          if (choice)
1950706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            otherlinkup = choice;
1951706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          choice = dl;
1952706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        }
1953706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else if (dl->state == DATALINK_CLOSED) {
1954706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (what == AUTO_UP) {
1955706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          choice = dl;
1956706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          break;
1957706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        }
1958706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else {
1959706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /* An auto link in an intermediate state - forget it for the moment */
1960706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        choice = NULL;
1961706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
1962706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1963706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else if (dl->state == DATALINK_OPEN && what == AUTO_DOWN)
1964706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      otherlinkup = dl;
1965706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1966706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (choice) {
1967706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (what == AUTO_UP) {
1968706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogPHASE, "%d%% saturation -> Opening link ``%s''\n",
1969706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 percent, choice->name);
1970706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      datalink_Up(choice, 1, 1);
1971706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      mp_CheckAutoloadTimer(&bundle->ncp.mp);
1972706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else if (otherlinkup) {	/* Only bring the second-last link down */
1973706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogPHASE, "%d%% saturation -> Closing link ``%s''\n",
1974706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 percent, choice->name);
1975706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      datalink_Close(choice, CLOSE_STAYDOWN);
1976706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      mp_CheckAutoloadTimer(&bundle->ncp.mp);
1977706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
1978706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
1979706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
1980706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1981706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
1982706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_WantAutoloadTimer(struct bundle *bundle)
1983706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
1984706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct datalink *dl;
1985706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int autolink, opened;
1986706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
1987706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->phase == PHASE_NETWORK) {
1988706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    for (autolink = opened = 0, dl = bundle->links; dl; dl = dl->next)
1989706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (dl->physical->type == PHYS_AUTO) {
1990706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (++autolink == 2 || (autolink == 1 && opened))
1991706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          /* Two auto links or one auto and one open in NETWORK phase */
1992706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          return 1;
1993706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else if (dl->state == DATALINK_OPEN) {
1994706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        opened++;
1995706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (autolink)
1996706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          /* One auto and one open link in NETWORK phase */
1997706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          return 1;
1998706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
1999706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
2000706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
2001706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
2002706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
2003706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
2004706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
2005706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_ChangedPID(struct bundle *bundle)
2006706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
2007706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef TUNSIFPID
2008706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ioctl(bundle->dev.fd, TUNSIFPID, 0);
2009706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
2010706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
2011706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
2012706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
2013706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehbundle_Uptime(struct bundle *bundle)
2014706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
2015706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->upat)
2016706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return time(NULL) - bundle->upat;
2017706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
2018706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
2019706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
2020