1 /*- 2 * Copyright (c) 1999 Brian Somers <brian (at) Awfulhak.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/usr.sbin/ppp/i4b.c,v 1.16.12.1 2010/12/21 17:10:29 kensmith Exp $ 27 */ 28 29 #include <sys/param.h> 30 31 #include <sys/un.h> 32 #if defined(__OpenBSD__) || defined(__NetBSD__) 33 #include <sys/ioctl.h> 34 #endif 35 #include <sys/stat.h> 36 37 #include <errno.h> 38 #include <fcntl.h> 39 #ifdef __NetBSD__ 40 #include <netisdn/i4b_ioctl.h> 41 #include <netisdn/i4b_rbch_ioctl.h> 42 #else 43 #include <i4b/i4b_ioctl.h> 44 #include <i4b/i4b_rbch_ioctl.h> 45 #endif 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <sysexits.h> 50 #include <sys/uio.h> 51 #include <termios.h> 52 #include <unistd.h> 53 54 #include "layer.h" 55 #include "defs.h" 56 #include "mbuf.h" 57 #include "log.h" 58 #include "timer.h" 59 #include "lqr.h" 60 #include "hdlc.h" 61 #include "throughput.h" 62 #include "fsm.h" 63 #include "lcp.h" 64 #include "ccp.h" 65 #include "link.h" 66 #include "async.h" 67 #include "descriptor.h" 68 #include "physical.h" 69 #include "mp.h" 70 #include "chat.h" 71 #include "auth.h" 72 #include "chap.h" 73 #include "cbcp.h" 74 #include "datalink.h" 75 #include "main.h" 76 #include "i4b.h" 77 78 #define Online(dev) ((dev)->mbits & TIOCM_CD) 79 80 struct i4bdevice { 81 struct device dev; /* What struct physical knows about */ 82 struct pppTimer Timer; /* CD checks */ 83 int mbits; /* Current DCD status */ 84 int carrier_seconds; /* seconds before CD is *required* */ 85 }; 86 87 #define device2i4b(d) ((d)->type == I4B_DEVICE ? (struct i4bdevice *)d : NULL) 88 89 unsigned 90 i4b_DeviceSize(void) 91 { 92 return sizeof(struct i4bdevice); 93 } 94 95 /* 96 * i4b_Timeout() watches the DCD signal and mentions it if it's status 97 * changes. 98 */ 99 static void 100 i4b_Timeout(void *data) 101 { 102 struct physical *p = data; 103 struct i4bdevice *dev = device2i4b(p->handler); 104 int ombits, change; 105 106 timer_Stop(&dev->Timer); 107 dev->Timer.load = SECTICKS; /* Once a second please */ 108 timer_Start(&dev->Timer); 109 ombits = dev->mbits; 110 111 if (p->fd >= 0) { 112 if (ioctl(p->fd, TIOCMGET, &dev->mbits) < 0) { 113 log_Printf(LogPHASE, "%s: ioctl error (%s)!\n", p->link.name, 114 strerror(errno)); 115 datalink_Down(p->dl, CLOSE_NORMAL); 116 timer_Stop(&dev->Timer); 117 return; 118 } 119 } else 120 dev->mbits = 0; 121 122 if (ombits == -1) { 123 /* First time looking for carrier */ 124 if (Online(dev)) 125 log_Printf(LogPHASE, "%s: %s: CD detected\n", p->link.name, p->name.full); 126 else if (++dev->carrier_seconds >= dev->dev.cd.delay) { 127 log_Printf(LogPHASE, "%s: %s: No carrier" 128 " (increase ``set cd'' from %d ?)\n", 129 p->link.name, p->name.full, dev->dev.cd.delay); 130 timer_Stop(&dev->Timer); 131 /* i4b_AwaitCarrier() will notice */ 132 } else { 133 /* Keep waiting */ 134 log_Printf(LogDEBUG, "%s: %s: Still no carrier (%d/%d)\n", 135 p->link.name, p->name.full, dev->carrier_seconds, 136 dev->dev.cd.delay); 137 dev->mbits = -1; 138 } 139 } else { 140 change = ombits ^ dev->mbits; 141 if (change & TIOCM_CD) { 142 if (dev->mbits & TIOCM_CD) 143 log_Printf(LogDEBUG, "%s: offline -> online\n", p->link.name); 144 else { 145 log_Printf(LogDEBUG, "%s: online -> offline\n", p->link.name); 146 log_Printf(LogPHASE, "%s: Carrier lost\n", p->link.name); 147 datalink_Down(p->dl, CLOSE_NORMAL); 148 timer_Stop(&dev->Timer); 149 } 150 } else 151 log_Printf(LogDEBUG, "%s: Still %sline\n", p->link.name, 152 Online(dev) ? "on" : "off"); 153 } 154 } 155 156 static void 157 i4b_StartTimer(struct physical *p) 158 { 159 struct i4bdevice *dev = device2i4b(p->handler); 160 161 timer_Stop(&dev->Timer); 162 dev->Timer.load = SECTICKS; 163 dev->Timer.func = i4b_Timeout; 164 dev->Timer.name = "i4b CD"; 165 dev->Timer.arg = p; 166 log_Printf(LogDEBUG, "%s: Using i4b_Timeout [%p]\n", 167 p->link.name, i4b_Timeout); 168 timer_Start(&dev->Timer); 169 } 170 171 static int 172 i4b_AwaitCarrier(struct physical *p) 173 { 174 struct i4bdevice *dev = device2i4b(p->handler); 175 176 if (dev->mbits == -1) { 177 if (dev->Timer.state == TIMER_STOPPED) { 178 dev->carrier_seconds = 0; 179 i4b_StartTimer(p); 180 } 181 return CARRIER_PENDING; /* Not yet ! */ 182 } 183 184 return Online(dev) ? CARRIER_OK : CARRIER_LOST; 185 } 186 187 static int 188 i4b_Raw(struct physical *p) 189 { 190 int oldflag; 191 192 log_Printf(LogDEBUG, "%s: Entering i4b_Raw\n", p->link.name); 193 194 oldflag = fcntl(p->fd, F_GETFL, 0); 195 if (oldflag < 0) 196 return 0; 197 fcntl(p->fd, F_SETFL, oldflag | O_NONBLOCK); 198 199 return 1; 200 } 201 202 static void 203 i4b_Offline(struct physical *p) 204 { 205 struct i4bdevice *dev = device2i4b(p->handler); 206 207 if (p->fd >= 0) { 208 timer_Stop(&dev->Timer); 209 if (Online(dev)) { 210 int dummy; 211 212 dummy = 1; 213 ioctl(p->fd, TIOCCDTR, &dummy); 214 } 215 } 216 } 217 218 static void 219 i4b_Cooked(struct physical *p) 220 { 221 int oldflag; 222 223 i4b_Offline(p); /* In case of emergency close()s */ 224 225 if ((oldflag = fcntl(p->fd, F_GETFL, 0)) != -1) 226 fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK); 227 } 228 229 static void 230 i4b_StopTimer(struct physical *p) 231 { 232 struct i4bdevice *dev = device2i4b(p->handler); 233 234 timer_Stop(&dev->Timer); 235 } 236 237 static void 238 i4b_Free(struct physical *p) 239 { 240 struct i4bdevice *dev = device2i4b(p->handler); 241 242 i4b_Offline(p); /* In case of emergency close()s */ 243 free(dev); 244 } 245 246 static unsigned 247 i4b_Speed(struct physical *p) 248 { 249 struct termios ios; 250 unsigned ret; 251 252 if (tcgetattr(p->fd, &ios) == -1 || 253 (ret = SpeedToUnsigned(cfgetispeed(&ios))) == 0) 254 ret = 64000; 255 256 return ret; 257 } 258 259 static const char * 260 i4b_OpenInfo(struct physical *p) 261 { 262 struct i4bdevice *dev = device2i4b(p->handler); 263 static char buf[26]; 264 265 if (Online(dev)) 266 snprintf(buf, sizeof buf, "carrier took %ds", dev->carrier_seconds); 267 else 268 *buf = '\0'; 269 270 return buf; 271 } 272 273 static int 274 i4b_Slot(struct physical *p) 275 { 276 struct stat st; 277 278 if (fstat(p->fd, &st) == 0) 279 return minor(st.st_rdev); 280 281 return -1; 282 } 283 284 static void 285 i4b_device2iov(struct device *d, struct iovec *iov, int *niov, 286 int maxiov __unused, int *auxfd __unused, int *nauxfd __unused) 287 { 288 struct i4bdevice *dev = device2i4b(d); 289 int sz = physical_MaxDeviceSize(); 290 291 iov[*niov].iov_base = realloc(d, sz); 292 if (iov[*niov].iov_base == NULL) { 293 log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz); 294 AbortProgram(EX_OSERR); 295 } 296 iov[*niov].iov_len = sz; 297 (*niov)++; 298 299 if (dev->Timer.state != TIMER_STOPPED) { 300 timer_Stop(&dev->Timer); 301 dev->Timer.state = TIMER_RUNNING; 302 } 303 } 304 305 static struct device basei4bdevice = { 306 I4B_DEVICE, 307 "i4b", 308 0, 309 { CD_REQUIRED, DEF_I4BCDDELAY }, 310 i4b_AwaitCarrier, 311 NULL, 312 i4b_Raw, 313 i4b_Offline, 314 i4b_Cooked, 315 NULL, 316 i4b_StopTimer, 317 i4b_Free, 318 NULL, 319 NULL, 320 i4b_device2iov, 321 i4b_Speed, 322 i4b_OpenInfo, 323 i4b_Slot 324 }; 325 326 struct device * 327 i4b_iov2device(int type, struct physical *p, struct iovec *iov, int *niov, 328 int maxiov __unused, int *auxfd __unused, int *nauxfd __unused) 329 { 330 if (type == I4B_DEVICE) { 331 struct i4bdevice *dev = (struct i4bdevice *)iov[(*niov)++].iov_base; 332 333 dev = realloc(dev, sizeof *dev); /* Reduce to the correct size */ 334 if (dev == NULL) { 335 log_Printf(LogALERT, "Failed to allocate memory: %d\n", 336 (int)(sizeof *dev)); 337 AbortProgram(EX_OSERR); 338 } 339 340 /* Refresh function pointers etc */ 341 memcpy(&dev->dev, &basei4bdevice, sizeof dev->dev); 342 343 physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE); 344 if (dev->Timer.state != TIMER_STOPPED) { 345 dev->Timer.state = TIMER_STOPPED; 346 p->handler = &dev->dev; /* For the benefit of StartTimer */ 347 i4b_StartTimer(p); 348 } 349 return &dev->dev; 350 } 351 352 return NULL; 353 } 354 355 struct device * 356 i4b_Create(struct physical *p) 357 { 358 struct i4bdevice *dev; 359 int oldflag, dial; 360 msg_vr_req_t req; 361 telno_t number; 362 363 if (p->fd < 0 || ioctl(p->fd, I4B_RBCH_VR_REQ, &req)) 364 /* Don't want this */ 365 return NULL; 366 367 /* 368 * We don't bother validating the version.... all versions of i4b that 369 * support I4B_RBCH_VR_REQ are fair game :-) 370 */ 371 372 if (*p->name.full == '\0') { 373 physical_SetDevice(p, ttyname(p->fd)); 374 log_Printf(LogDEBUG, "%s: Input is an i4b version %d.%d.%d isdn " 375 "device (%s)\n", p->link.name, req.version, req.release, 376 req.step, p->name.full); 377 dial = 0; 378 } else { 379 log_Printf(LogDEBUG, "%s: Opened %s (i4b version %d.%d.%d)\n", 380 p->link.name, p->name.full, req.version, req.release, req.step); 381 dial = 1; 382 } 383 384 /* We're gonna return an i4bdevice (unless something goes horribly wrong) */ 385 386 if ((dev = malloc(sizeof *dev)) == NULL) { 387 /* Complete failure - parent doesn't continue trying to ``create'' */ 388 close(p->fd); 389 p->fd = -1; 390 return NULL; 391 } 392 393 memcpy(&dev->dev, &basei4bdevice, sizeof dev->dev); 394 memset(&dev->Timer, '\0', sizeof dev->Timer); 395 dev->mbits = -1; 396 397 switch (p->cfg.cd.necessity) { 398 case CD_VARIABLE: 399 dev->dev.cd.delay = p->cfg.cd.delay; 400 break; 401 case CD_REQUIRED: 402 dev->dev.cd = p->cfg.cd; 403 break; 404 case CD_NOTREQUIRED: 405 log_Printf(LogWARN, "%s: Carrier must be set, using ``set cd %d!''\n", 406 p->link.name, dev->dev.cd.delay); 407 case CD_DEFAULT: 408 break; 409 } 410 411 oldflag = fcntl(p->fd, F_GETFL, 0); 412 if (oldflag < 0) { 413 /* Complete failure - parent doesn't continue trying to ``create'' */ 414 415 log_Printf(LogWARN, "%s: Open: Cannot get physical flags: %s\n", 416 p->link.name, strerror(errno)); 417 i4b_Cooked(p); 418 close(p->fd); 419 p->fd = -1; 420 free(dev); 421 return NULL; 422 } else 423 fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK); 424 425 if (dial) { 426 strncpy(number, datalink_ChoosePhoneNumber(p->dl), sizeof number - 1); 427 number[sizeof number - 1] = '\0'; 428 if (number[0] == '\0') 429 dial = 0; 430 } 431 if (dial && ioctl(p->fd, I4B_RBCH_DIALOUT, number) == -1) { 432 /* Complete failure - parent doesn't continue trying to ``create'' */ 433 434 log_Printf(LogWARN, "%s: ioctl(I4B_RBCH_DIALOUT): %s\n", 435 p->link.name, strerror(errno)); 436 i4b_Cooked(p); 437 close(p->fd); 438 p->fd = -1; 439 free(dev); 440 return NULL; 441 } 442 443 physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNC); 444 445 return &dev->dev; 446 } 447