atm.c revision 89422
165862Sbrian/*- 265862Sbrian * Copyright (c) 2000 Jakob Stoklund Olesen <stoklund@taxidriver.dk> 365862Sbrian * All rights reserved. 465862Sbrian * 565862Sbrian * Redistribution and use in source and binary forms, with or without 665862Sbrian * modification, are permitted provided that the following conditions 765862Sbrian * are met: 865862Sbrian * 1. Redistributions of source code must retain the above copyright 965862Sbrian * notice, this list of conditions and the following disclaimer. 1065862Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1165862Sbrian * notice, this list of conditions and the following disclaimer in the 1265862Sbrian * documentation and/or other materials provided with the distribution. 1365862Sbrian * 1465862Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1565862Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1665862Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1765862Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1865862Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1965862Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2065862Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2165862Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2265862Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2365862Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2465862Sbrian * SUCH DAMAGE. 2565862Sbrian * 2665862Sbrian * $FreeBSD: head/usr.sbin/ppp/atm.c 89422 2002-01-16 14:03:52Z brian $ 2765862Sbrian */ 2865862Sbrian 2965862Sbrian#include <sys/types.h> 3065862Sbrian#include <sys/socket.h> 3165862Sbrian#include <net/if.h> 3265862Sbrian#include <netnatm/natm.h> 3365862Sbrian 3465862Sbrian#include <errno.h> 3565862Sbrian#include <stdio.h> 3665862Sbrian#include <stdlib.h> 3765862Sbrian#include <string.h> 3865862Sbrian#include <sysexits.h> 3965862Sbrian#include <sys/uio.h> 4065862Sbrian#include <termios.h> 4165862Sbrian#include <unistd.h> 4265862Sbrian 4365862Sbrian#include "layer.h" 4465862Sbrian#include "defs.h" 4565862Sbrian#include "mbuf.h" 4665862Sbrian#include "log.h" 4765862Sbrian#include "timer.h" 4865862Sbrian#include "lqr.h" 4965862Sbrian#include "hdlc.h" 5065862Sbrian#include "throughput.h" 5165862Sbrian#include "fsm.h" 5265862Sbrian#include "lcp.h" 5365862Sbrian#include "ccp.h" 5465862Sbrian#include "link.h" 5565862Sbrian#include "async.h" 5665862Sbrian#include "descriptor.h" 5765862Sbrian#include "physical.h" 5865862Sbrian#include "main.h" 5965862Sbrian#include "atm.h" 6065862Sbrian 6165862Sbrian/* String identifying PPPoA */ 6265863Sbrian#define PPPOA "PPPoA" 6365863Sbrian#define PPPOA_LEN (sizeof(PPPOA) - 1) 6465862Sbrian 6565862Sbrianstruct atmdevice { 6665862Sbrian struct device dev; /* What struct physical knows about */ 6765862Sbrian}; 6865862Sbrian 6965862Sbrian#define device2atm(d) ((d)->type == ATM_DEVICE ? (struct atmdevice *)d : NULL) 7065862Sbrian 7165862Sbrianint 7265862Sbrianatm_DeviceSize(void) 7365862Sbrian{ 7465862Sbrian return sizeof(struct atmdevice); 7565862Sbrian} 7665862Sbrian 7765862Sbrianstatic ssize_t 7865862Sbrianatm_Sendto(struct physical *p, const void *v, size_t n) 7965862Sbrian{ 8065862Sbrian ssize_t ret = write(p->fd, v, n); 8165863Sbrian if (ret < 0) { 8271781Sbrian log_Printf(LogDEBUG, "atm_Sendto(%ld): %s\n", (long)n, strerror(errno)); 8365862Sbrian return ret; 8465862Sbrian } 8565862Sbrian return ret; 8665862Sbrian} 8765862Sbrian 8865862Sbrianstatic ssize_t 8965862Sbrianatm_Recvfrom(struct physical *p, void *v, size_t n) 9065862Sbrian{ 9165862Sbrian ssize_t ret = read(p->fd, (char*)v, n); 9265863Sbrian if (ret < 0) { 9371781Sbrian log_Printf(LogDEBUG, "atm_Recvfrom(%ld): %s\n", (long)n, strerror(errno)); 9465862Sbrian return ret; 9565862Sbrian } 9665862Sbrian return ret; 9765862Sbrian} 9865862Sbrian 9965862Sbrianstatic void 10065862Sbrianatm_Free(struct physical *p) 10165862Sbrian{ 10265862Sbrian struct atmdevice *dev = device2atm(p->handler); 10365862Sbrian 10465862Sbrian free(dev); 10565862Sbrian} 10665862Sbrian 10765862Sbrianstatic void 10865862Sbrianatm_device2iov(struct device *d, struct iovec *iov, int *niov, 10965862Sbrian int maxiov, int *auxfd, int *nauxfd) 11065862Sbrian{ 11165862Sbrian int sz = physical_MaxDeviceSize(); 11265862Sbrian 11365862Sbrian iov[*niov].iov_base = realloc(d, sz); 11465862Sbrian if (iov[*niov].iov_base == NULL) { 11565862Sbrian log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz); 11665862Sbrian AbortProgram(EX_OSERR); 11765862Sbrian } 11865862Sbrian iov[*niov].iov_len = sz; 11965862Sbrian (*niov)++; 12065862Sbrian} 12165862Sbrian 12265862Sbrianstatic const struct device baseatmdevice = { 12365862Sbrian ATM_DEVICE, 12465862Sbrian "atm", 12578410Sbrian 0, 12665862Sbrian { CD_NOTREQUIRED, 0 }, 12765862Sbrian NULL, 12865862Sbrian NULL, 12965862Sbrian NULL, 13065862Sbrian NULL, 13165862Sbrian NULL, 13265862Sbrian NULL, 13365862Sbrian atm_Free, 13465862Sbrian atm_Recvfrom, 13565862Sbrian atm_Sendto, 13665862Sbrian atm_device2iov, 13765862Sbrian NULL, 13865862Sbrian NULL 13965862Sbrian}; 14065862Sbrian 14165862Sbrianstruct device * 14265862Sbrianatm_iov2device(int type, struct physical *p, struct iovec *iov, int *niov, 14365862Sbrian int maxiov, int *auxfd, int *nauxfd) 14465862Sbrian{ 14565862Sbrian if (type == ATM_DEVICE) { 14665862Sbrian struct atmdevice *dev = (struct atmdevice *)iov[(*niov)++].iov_base; 14765862Sbrian 14865862Sbrian dev = realloc(dev, sizeof *dev); /* Reduce to the correct size */ 14965862Sbrian if (dev == NULL) { 15065862Sbrian log_Printf(LogALERT, "Failed to allocate memory: %d\n", 15165862Sbrian (int)(sizeof *dev)); 15265862Sbrian AbortProgram(EX_OSERR); 15365862Sbrian } 15465862Sbrian 15565862Sbrian /* Refresh function pointers etc */ 15665862Sbrian memcpy(&dev->dev, &baseatmdevice, sizeof dev->dev); 15765862Sbrian 15865862Sbrian physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); 15965862Sbrian return &dev->dev; 16065862Sbrian } 16165862Sbrian 16265862Sbrian return NULL; 16365862Sbrian} 16465862Sbrian 16565862Sbrianstatic struct atmdevice * 16665863Sbrianatm_CreateDevice(struct physical *p, const char *iface, unsigned vpi, 16765863Sbrian unsigned vci) 16865862Sbrian{ 16965862Sbrian struct atmdevice *dev; 17065862Sbrian struct sockaddr_natm sock; 17165862Sbrian 17265863Sbrian if ((dev = calloc(1, sizeof *dev)) == NULL) { 17365862Sbrian log_Printf(LogWARN, "%s: Cannot allocate an atm device: %s\n", 17465862Sbrian p->link.name, strerror(errno)); 17565862Sbrian return NULL; 17665862Sbrian } 17765862Sbrian 17865862Sbrian sock.snatm_len = sizeof sock; 17965862Sbrian sock.snatm_family = AF_NATM; 18065863Sbrian strncpy(sock.snatm_if, iface, IFNAMSIZ); 18165862Sbrian sock.snatm_vpi = vpi; 18265862Sbrian sock.snatm_vci = vci; 18365862Sbrian 18465862Sbrian log_Printf(LogPHASE, "%s: Connecting to %s:%u.%u\n", p->link.name, 18565862Sbrian iface, vpi, vci); 18665862Sbrian 18789422Sbrian p->fd = socket(PF_NATM, SOCK_DGRAM, PROTO_NATMAAL5); 18865862Sbrian if (p->fd >= 0) { 18965862Sbrian log_Printf(LogDEBUG, "%s: Opened atm socket %s\n", p->link.name, 19065862Sbrian p->name.full); 19165862Sbrian if (connect(p->fd, (struct sockaddr *)&sock, sizeof sock) == 0) 19265862Sbrian return dev; 19365862Sbrian else 19465862Sbrian log_Printf(LogWARN, "%s: connect: %s\n", p->name.full, strerror(errno)); 19565862Sbrian } else 19665862Sbrian log_Printf(LogWARN, "%s: socket: %s\n", p->name.full, strerror(errno)); 19765862Sbrian 19865862Sbrian close(p->fd); 19965862Sbrian p->fd = -1; 20065862Sbrian free(dev); 20165862Sbrian 20265862Sbrian return NULL; 20365862Sbrian} 20465862Sbrian 20565862Sbrianstruct device * 20665862Sbrianatm_Create(struct physical *p) 20765862Sbrian{ 20865862Sbrian struct atmdevice *dev; 20965862Sbrian 21065862Sbrian dev = NULL; 21165863Sbrian if (p->fd < 0 && !strncasecmp(p->name.full, PPPOA, PPPOA_LEN) 21265862Sbrian && p->name.full[PPPOA_LEN] == ':') { 21365862Sbrian char iface[25]; 21465862Sbrian unsigned vci, vpi; 21565862Sbrian 21665863Sbrian if (sscanf(p->name.full + PPPOA_LEN + 1, "%25[A-Za-z0-9]:%u.%u", iface, 21765863Sbrian &vpi, &vci) != 3) { 21865863Sbrian log_Printf(LogWARN, "Malformed ATM device name \'%s\', " 21965863Sbrian "PPPoA:if:vpi.vci expected\n", p->name.full); 22065862Sbrian return NULL; 22165862Sbrian } 22265862Sbrian 22365862Sbrian dev = atm_CreateDevice(p, iface, vpi, vci); 22465862Sbrian } 22565862Sbrian 22665862Sbrian if (dev) { 22765862Sbrian memcpy(&dev->dev, &baseatmdevice, sizeof dev->dev); 22865862Sbrian physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); 22965862Sbrian if (p->cfg.cd.necessity != CD_DEFAULT) 23065862Sbrian log_Printf(LogWARN, "Carrier settings ignored\n"); 23165862Sbrian return &dev->dev; 23265862Sbrian } 23365862Sbrian 23465862Sbrian return NULL; 23565862Sbrian} 236