atm.c revision 65862
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 65862 2000-09-14 22:02:54Z 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 */
6265862Sbrian#define PPPOA "PPPoA"
6365862Sbrian#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);
8165862Sbrian  if (ret<0) {
8265862Sbrian    log_Printf(LogDEBUG, "atm_Sendto(%d): %s\n", 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);
9265862Sbrian    if (ret<0) {
9365862Sbrian      log_Printf(LogDEBUG, "atm_Recvfrom(%d): %s\n", 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",
12565862Sbrian  { CD_NOTREQUIRED, 0 },
12665862Sbrian  NULL,
12765862Sbrian  NULL,
12865862Sbrian  NULL,
12965862Sbrian  NULL,
13065862Sbrian  NULL,
13165862Sbrian  NULL,
13265862Sbrian  atm_Free,
13365862Sbrian  atm_Recvfrom,
13465862Sbrian  atm_Sendto,
13565862Sbrian  atm_device2iov,
13665862Sbrian  NULL,
13765862Sbrian  NULL
13865862Sbrian};
13965862Sbrian
14065862Sbrianstruct device *
14165862Sbrianatm_iov2device(int type, struct physical *p, struct iovec *iov, int *niov,
14265862Sbrian               int maxiov, int *auxfd, int *nauxfd)
14365862Sbrian{
14465862Sbrian  if (type == ATM_DEVICE) {
14565862Sbrian    struct atmdevice *dev = (struct atmdevice *)iov[(*niov)++].iov_base;
14665862Sbrian
14765862Sbrian    dev = realloc(dev, sizeof *dev);	/* Reduce to the correct size */
14865862Sbrian    if (dev == NULL) {
14965862Sbrian      log_Printf(LogALERT, "Failed to allocate memory: %d\n",
15065862Sbrian                 (int)(sizeof *dev));
15165862Sbrian      AbortProgram(EX_OSERR);
15265862Sbrian    }
15365862Sbrian
15465862Sbrian    /* Refresh function pointers etc */
15565862Sbrian    memcpy(&dev->dev, &baseatmdevice, sizeof dev->dev);
15665862Sbrian
15765862Sbrian    physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF);
15865862Sbrian    return &dev->dev;
15965862Sbrian  }
16065862Sbrian
16165862Sbrian  return NULL;
16265862Sbrian}
16365862Sbrian
16465862Sbrianstatic struct atmdevice *
16565862Sbrianatm_CreateDevice(struct physical *p, const char *iface, unsigned vpi, unsigned vci)
16665862Sbrian{
16765862Sbrian  struct atmdevice *dev;
16865862Sbrian  struct sockaddr_natm sock;
16965862Sbrian
17065862Sbrian  if ((dev = calloc (1, sizeof *dev)) == NULL) {
17165862Sbrian    log_Printf(LogWARN, "%s: Cannot allocate an atm device: %s\n",
17265862Sbrian               p->link.name, strerror(errno));
17365862Sbrian    return NULL;
17465862Sbrian  }
17565862Sbrian
17665862Sbrian  sock.snatm_len = sizeof sock;
17765862Sbrian  sock.snatm_family = AF_NATM;
17865862Sbrian  strncpy (sock.snatm_if, iface, IFNAMSIZ);
17965862Sbrian  sock.snatm_vpi = vpi;
18065862Sbrian  sock.snatm_vci = vci;
18165862Sbrian
18265862Sbrian  log_Printf(LogPHASE, "%s: Connecting to %s:%u.%u\n", p->link.name,
18365862Sbrian             iface, vpi, vci);
18465862Sbrian
18565862Sbrian  p->fd = socket(PF_NATM, SOCK_DGRAM, PROTO_NATMAAL5);
18665862Sbrian  if (p->fd >= 0) {
18765862Sbrian    log_Printf(LogDEBUG, "%s: Opened atm socket %s\n", p->link.name,
18865862Sbrian               p->name.full);
18965862Sbrian    if (connect(p->fd, (struct sockaddr *)&sock, sizeof sock) == 0)
19065862Sbrian      return dev;
19165862Sbrian    else
19265862Sbrian      log_Printf(LogWARN, "%s: connect: %s\n", p->name.full, strerror(errno));
19365862Sbrian  } else
19465862Sbrian    log_Printf(LogWARN, "%s: socket: %s\n", p->name.full, strerror(errno));
19565862Sbrian
19665862Sbrian  close(p->fd);
19765862Sbrian  p->fd = -1;
19865862Sbrian  free(dev);
19965862Sbrian
20065862Sbrian  return NULL;
20165862Sbrian}
20265862Sbrian
20365862Sbrianstruct device *
20465862Sbrianatm_Create(struct physical *p)
20565862Sbrian{
20665862Sbrian  struct atmdevice *dev;
20765862Sbrian
20865862Sbrian  dev = NULL;
20965862Sbrian  if (p->fd < 0 && !strncasecmp (p->name.full, PPPOA, PPPOA_LEN)
21065862Sbrian      && p->name.full[PPPOA_LEN] == ':') {
21165862Sbrian    char iface[25];
21265862Sbrian    unsigned vci, vpi;
21365862Sbrian
21465862Sbrian    if (sscanf (p->name.full + PPPOA_LEN + 1, "%25[A-Za-z0-9]:%u.%u", iface,
21565862Sbrian		&vpi, &vci) != 3) {
21665862Sbrian      log_Printf (LogWARN, "Malformed ATM device name \'%s\', PPPoA:if:vpi.vci expected\n", p->name.full);
21765862Sbrian      return NULL;
21865862Sbrian    }
21965862Sbrian
22065862Sbrian    dev = atm_CreateDevice(p, iface, vpi, vci);
22165862Sbrian  }
22265862Sbrian
22365862Sbrian  if (dev) {
22465862Sbrian    memcpy(&dev->dev, &baseatmdevice, sizeof dev->dev);
22565862Sbrian    physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF);
22665862Sbrian    if (p->cfg.cd.necessity != CD_DEFAULT)
22765862Sbrian      log_Printf(LogWARN, "Carrier settings ignored\n");
22865862Sbrian    return &dev->dev;
22965862Sbrian  }
23065862Sbrian
23165862Sbrian  return NULL;
23265862Sbrian}
233