146686Sbrian/*-
246686Sbrian * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
346686Sbrian * All rights reserved.
446686Sbrian *
546686Sbrian * Redistribution and use in source and binary forms, with or without
646686Sbrian * modification, are permitted provided that the following conditions
746686Sbrian * are met:
846686Sbrian * 1. Redistributions of source code must retain the above copyright
946686Sbrian *    notice, this list of conditions and the following disclaimer.
1046686Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1146686Sbrian *    notice, this list of conditions and the following disclaimer in the
1246686Sbrian *    documentation and/or other materials provided with the distribution.
1346686Sbrian *
1446686Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1546686Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1646686Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1746686Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1846686Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1946686Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2046686Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2146686Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2246686Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2346686Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2446686Sbrian * SUCH DAMAGE.
2546686Sbrian *
2650479Speter * $FreeBSD$
2746686Sbrian */
2846686Sbrian
2946686Sbrian#include <sys/types.h>
3046686Sbrian
3146686Sbrian#include <stdio.h>
3246686Sbrian#include <termios.h>
3346686Sbrian
3446686Sbrian#include "defs.h"
3546686Sbrian#include "layer.h"
3646686Sbrian#include "timer.h"
3746686Sbrian#include "fsm.h"
3846686Sbrian#include "log.h"
3946686Sbrian#include "mbuf.h"
4046686Sbrian#include "acf.h"
4146686Sbrian#include "proto.h"
4246686Sbrian#include "throughput.h"
4346686Sbrian#include "lqr.h"
4446686Sbrian#include "hdlc.h"
4563484Sbrian#include "lcp.h"
4646686Sbrian#include "ccp.h"
4746686Sbrian#include "link.h"
4846686Sbrian#include "descriptor.h"
4946686Sbrian#include "async.h"
5046686Sbrian#include "physical.h"
5146686Sbrian
5246686Sbrianint
5346686Sbrianacf_WrapperOctets(struct lcp *lcp, u_short proto)
5446686Sbrian{
5546686Sbrian  return (proto == PROTO_LCP || lcp->his_acfcomp == 0) ? 2 : 0;
5646686Sbrian}
5746686Sbrian
5846686Sbrianstatic struct mbuf *
59134789Sbrianacf_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp,
60134789Sbrian              int pri __unused, u_short *proto)
6146686Sbrian{
6246686Sbrian  const u_char cp[2] = { HDLC_ADDR, HDLC_UI };
6346686Sbrian
6447695Sbrian  if (*proto == PROTO_LCP || l->lcp.his_acfcomp == 0) {
6554912Sbrian    bp = m_prepend(bp, cp, 2, 0);
6654912Sbrian    m_settype(bp, MB_ACFOUT);
6747695Sbrian  }
6846686Sbrian
6946686Sbrian  return bp;
7046686Sbrian}
7146686Sbrian
7246686Sbrianstatic struct mbuf *
73134789Sbrianacf_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp,
74134789Sbrian	      u_short *proto __unused)
7546686Sbrian{
7646686Sbrian  struct physical *p = link2physical(l);
7746686Sbrian  u_char cp[2];
7846686Sbrian
7946686Sbrian  if (!p) {
8046686Sbrian    log_Printf(LogERROR, "Can't Pull an acf packet from a logical link\n");
8146686Sbrian    return bp;
8246686Sbrian  }
8346686Sbrian
8446686Sbrian  if (mbuf_View(bp, cp, 2) == 2) {
8546686Sbrian    if (!p->link.lcp.want_acfcomp) {
8646686Sbrian      /* We expect the packet not to be compressed */
8746686Sbrian      bp = mbuf_Read(bp, cp, 2);
8846686Sbrian      if (cp[0] != HDLC_ADDR) {
89131327Sbrian        p->hdlc.lqm.ifInErrors++;
9046686Sbrian        p->hdlc.stats.badaddr++;
9146686Sbrian        log_Printf(LogDEBUG, "acf_LayerPull: addr 0x%02x\n", cp[0]);
9254912Sbrian        m_freem(bp);
9346686Sbrian        return NULL;
9446686Sbrian      }
9546686Sbrian      if (cp[1] != HDLC_UI) {
96131327Sbrian        p->hdlc.lqm.ifInErrors++;
9746686Sbrian        p->hdlc.stats.badcommand++;
9846686Sbrian        log_Printf(LogDEBUG, "acf_LayerPull: control 0x%02x\n", cp[1]);
9954912Sbrian        m_freem(bp);
10046686Sbrian        return NULL;
10146686Sbrian      }
10254912Sbrian      m_settype(bp, MB_ACFIN);
10346686Sbrian    } else if (cp[0] == HDLC_ADDR && cp[1] == HDLC_UI) {
10446686Sbrian      /*
10546686Sbrian       * We can receive compressed packets, but the peer still sends
10646686Sbrian       * uncompressed packets (or maybe this is a PROTO_LCP packet) !
10746686Sbrian       */
10846686Sbrian      bp = mbuf_Read(bp, cp, 2);
10954912Sbrian      m_settype(bp, MB_ACFIN);
11046686Sbrian    }
11146686Sbrian  }
11246686Sbrian
11346686Sbrian  return bp;
11446686Sbrian}
11546686Sbrian
11646686Sbrianstruct layer acflayer = { LAYER_ACF, "acf", acf_LayerPush, acf_LayerPull };
117