136285Sbrian/*- 236285Sbrian * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org> 336285Sbrian * All rights reserved. 436285Sbrian * 536285Sbrian * Redistribution and use in source and binary forms, with or without 636285Sbrian * modification, are permitted provided that the following conditions 736285Sbrian * are met: 836285Sbrian * 1. Redistributions of source code must retain the above copyright 936285Sbrian * notice, this list of conditions and the following disclaimer. 1036285Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1136285Sbrian * notice, this list of conditions and the following disclaimer in the 1236285Sbrian * documentation and/or other materials provided with the distribution. 1336285Sbrian * 1436285Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1536285Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1636285Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1736285Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1836285Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1936285Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2036285Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2136285Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2236285Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2336285Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2436285Sbrian * SUCH DAMAGE. 2536285Sbrian * 2650479Speter * $FreeBSD$ 2736285Sbrian * 2836285Sbrian */ 2936285Sbrian 3036285Sbrian#include <sys/types.h> 3146686Sbrian#include <netinet/in_systm.h> 3281634Sbrian#include <sys/socket.h> 3346686Sbrian#include <sys/un.h> 3446686Sbrian#include <netinet/in.h> 3546686Sbrian#include <netinet/ip.h> 3636285Sbrian 37102500Sbrian#include <stdarg.h> 3836285Sbrian#include <stdio.h> 3945193Sbrian#include <string.h> 4036285Sbrian#include <termios.h> 4136285Sbrian 4238174Sbrian#include "defs.h" 4346686Sbrian#include "layer.h" 4436285Sbrian#include "mbuf.h" 4536285Sbrian#include "log.h" 4636285Sbrian#include "timer.h" 4736285Sbrian#include "lqr.h" 4836285Sbrian#include "hdlc.h" 4936285Sbrian#include "throughput.h" 5046686Sbrian#include "proto.h" 5136285Sbrian#include "fsm.h" 5236285Sbrian#include "descriptor.h" 5336285Sbrian#include "lcp.h" 5436285Sbrian#include "ccp.h" 5536285Sbrian#include "link.h" 5636285Sbrian#include "prompt.h" 5746686Sbrian#include "async.h" 5846686Sbrian#include "physical.h" 5946686Sbrian#include "mp.h" 6046686Sbrian#include "iplist.h" 6146686Sbrian#include "slcompress.h" 6281634Sbrian#include "ncpaddr.h" 6381634Sbrian#include "ip.h" 6446686Sbrian#include "ipcp.h" 6581634Sbrian#include "ipv6cp.h" 6646686Sbrian#include "auth.h" 6746686Sbrian#include "pap.h" 6846686Sbrian#include "chap.h" 6946686Sbrian#include "cbcp.h" 7047211Sbrian#include "command.h" 7136285Sbrian 7246686Sbrianstatic void Despatch(struct bundle *, struct link *, struct mbuf *, u_short); 7346686Sbrian 7464652Sbrianstatic inline void 7536285Sbrianlink_AddInOctets(struct link *l, int n) 7636285Sbrian{ 7764652Sbrian if (l->stats.gather) { 7864652Sbrian throughput_addin(&l->stats.total, n); 7964652Sbrian if (l->stats.parent) 8064652Sbrian throughput_addin(l->stats.parent, n); 8164652Sbrian } 8236285Sbrian} 8336285Sbrian 8464652Sbrianstatic inline void 8536285Sbrianlink_AddOutOctets(struct link *l, int n) 8636285Sbrian{ 8764652Sbrian if (l->stats.gather) { 8864652Sbrian throughput_addout(&l->stats.total, n); 8964652Sbrian if (l->stats.parent) 9064652Sbrian throughput_addout(l->stats.parent, n); 9164652Sbrian } 9236285Sbrian} 9336285Sbrian 9436285Sbrianvoid 9536285Sbrianlink_SequenceQueue(struct link *l) 9636285Sbrian{ 9750867Sbrian struct mqueue *queue, *highest; 9850867Sbrian 9936285Sbrian log_Printf(LogDEBUG, "link_SequenceQueue\n"); 10050867Sbrian 10150867Sbrian highest = LINK_HIGHQ(l); 10250867Sbrian for (queue = l->Queue; queue < highest; queue++) 10354912Sbrian while (queue->len) 10454912Sbrian m_enqueue(highest, m_dequeue(queue)); 10536285Sbrian} 10636285Sbrian 10738544Sbrianvoid 10838544Sbrianlink_DeleteQueue(struct link *l) 10938544Sbrian{ 11050867Sbrian struct mqueue *queue, *highest; 11138544Sbrian 11250867Sbrian highest = LINK_HIGHQ(l); 11350867Sbrian for (queue = l->Queue; queue <= highest; queue++) 11438544Sbrian while (queue->top) 11554912Sbrian m_freem(m_dequeue(queue)); 11638544Sbrian} 11738544Sbrian 11854912Sbriansize_t 11936285Sbrianlink_QueueLen(struct link *l) 12036285Sbrian{ 121134789Sbrian unsigned i; 12254912Sbrian size_t len; 12336285Sbrian 12450867Sbrian for (i = 0, len = 0; i < LINK_QUEUES(l); i++) 12554912Sbrian len += l->Queue[i].len; 12636285Sbrian 12736285Sbrian return len; 12836285Sbrian} 12936285Sbrian 13054912Sbriansize_t 13136285Sbrianlink_QueueBytes(struct link *l) 13236285Sbrian{ 133134789Sbrian unsigned i; 13454912Sbrian size_t len, bytes; 13536285Sbrian struct mbuf *m; 13636285Sbrian 13736285Sbrian bytes = 0; 13850867Sbrian for (i = 0, len = 0; i < LINK_QUEUES(l); i++) { 13954912Sbrian len = l->Queue[i].len; 14036285Sbrian m = l->Queue[i].top; 14136285Sbrian while (len--) { 14254912Sbrian bytes += m_length(m); 14354912Sbrian m = m->m_nextpkt; 14436285Sbrian } 14536285Sbrian } 14636285Sbrian 14736285Sbrian return bytes; 14836285Sbrian} 14936285Sbrian 150131327Sbrianvoid 151131327Sbrianlink_PendingLowPriorityData(struct link *l, size_t *pkts, size_t *octets) 152131327Sbrian{ 153131327Sbrian struct mqueue *queue, *highest; 154131327Sbrian struct mbuf *m; 155131327Sbrian size_t len; 156131327Sbrian 157131327Sbrian /* 158131327Sbrian * This is all rfc1989 stuff... because our LQR packet is going to bypass 159131327Sbrian * everything that's not in the highest priority queue, we must be able to 160131327Sbrian * subtract that data from our outgoing packet/octet counts. However, 161131327Sbrian * we've already async-encoded our data at this point, but the async 162131327Sbrian * encodings MUSTn't be a part of the LQR-reported payload :( So, we have 163131327Sbrian * the async layer record how much it's padded the packet in the mbuf's 164131327Sbrian * priv field, and when we calculate our outgoing LQR values we subtract 165131327Sbrian * this value for each packet from the octet count sent. 166131327Sbrian */ 167131327Sbrian 168131327Sbrian highest = LINK_HIGHQ(l); 169131327Sbrian *pkts = *octets = 0; 170131327Sbrian for (queue = l->Queue; queue < highest; queue++) { 171131327Sbrian len = queue->len; 172131327Sbrian *pkts += len; 173131327Sbrian for (m = queue->top; len--; m = m->m_nextpkt) 174131327Sbrian *octets += m_length(m) - m->priv; 175131327Sbrian } 176131327Sbrian} 177131327Sbrian 17836285Sbrianstruct mbuf * 17936285Sbrianlink_Dequeue(struct link *l) 18036285Sbrian{ 18136285Sbrian int pri; 18236285Sbrian struct mbuf *bp; 18336285Sbrian 18450867Sbrian for (bp = NULL, pri = LINK_QUEUES(l) - 1; pri >= 0; pri--) 18554912Sbrian if (l->Queue[pri].len) { 18654912Sbrian bp = m_dequeue(l->Queue + pri); 18736285Sbrian log_Printf(LogDEBUG, "link_Dequeue: Dequeued from queue %d," 18854912Sbrian " containing %lu more packets\n", pri, 18954912Sbrian (u_long)l->Queue[pri].len); 19036285Sbrian break; 19136285Sbrian } 19236285Sbrian 19336285Sbrian return bp; 19436285Sbrian} 19536285Sbrian 19636285Sbrianstatic struct protostatheader { 19736285Sbrian u_short number; 19836285Sbrian const char *name; 19936285Sbrian} ProtocolStat[NPROTOSTAT] = { 20036285Sbrian { PROTO_IP, "IP" }, 20136285Sbrian { PROTO_VJUNCOMP, "VJ_UNCOMP" }, 20236285Sbrian { PROTO_VJCOMP, "VJ_COMP" }, 20336285Sbrian { PROTO_COMPD, "COMPD" }, 20436285Sbrian { PROTO_ICOMPD, "ICOMPD" }, 20536285Sbrian { PROTO_LCP, "LCP" }, 20636285Sbrian { PROTO_IPCP, "IPCP" }, 20736285Sbrian { PROTO_CCP, "CCP" }, 20836285Sbrian { PROTO_PAP, "PAP" }, 20936285Sbrian { PROTO_LQR, "LQR" }, 21036285Sbrian { PROTO_CHAP, "CHAP" }, 21136285Sbrian { PROTO_MP, "MULTILINK" }, 21236285Sbrian { 0, "Others" } 21336285Sbrian}; 21436285Sbrian 21536285Sbrianvoid 21636285Sbrianlink_ProtocolRecord(struct link *l, u_short proto, int type) 21736285Sbrian{ 21836285Sbrian int i; 21936285Sbrian 22036285Sbrian for (i = 0; i < NPROTOSTAT; i++) 22136285Sbrian if (ProtocolStat[i].number == proto) 22236285Sbrian break; 22336285Sbrian 22436285Sbrian if (type == PROTO_IN) 22536285Sbrian l->proto_in[i]++; 22636285Sbrian else 22736285Sbrian l->proto_out[i]++; 22836285Sbrian} 22936285Sbrian 23036285Sbrianvoid 23136285Sbrianlink_ReportProtocolStatus(struct link *l, struct prompt *prompt) 23236285Sbrian{ 23336285Sbrian int i; 23436285Sbrian 23536285Sbrian prompt_Printf(prompt, " Protocol in out " 23636285Sbrian "Protocol in out\n"); 23736285Sbrian for (i = 0; i < NPROTOSTAT; i++) { 23836285Sbrian prompt_Printf(prompt, " %-9s: %8lu, %8lu", 23936285Sbrian ProtocolStat[i].name, l->proto_in[i], l->proto_out[i]); 24036285Sbrian if ((i % 2) == 0) 24136285Sbrian prompt_Printf(prompt, "\n"); 24236285Sbrian } 24336285Sbrian if (!(i % 2)) 24436285Sbrian prompt_Printf(prompt, "\n"); 24536285Sbrian} 24646686Sbrian 24746686Sbrianvoid 24846686Sbrianlink_PushPacket(struct link *l, struct mbuf *bp, struct bundle *b, int pri, 24946686Sbrian u_short proto) 25046686Sbrian{ 25146686Sbrian int layer; 25246686Sbrian 25346686Sbrian /* 25446686Sbrian * When we ``push'' a packet into the link, it gets processed by the 25546686Sbrian * ``push'' function in each layer starting at the top. 25646686Sbrian * We never expect the result of a ``push'' to be more than one 25746686Sbrian * packet (as we do with ``pull''s). 25846686Sbrian */ 25946686Sbrian 260134789Sbrian if(pri < 0 || (unsigned)pri >= LINK_QUEUES(l)) 26146686Sbrian pri = 0; 26246686Sbrian 263131327Sbrian bp->priv = 0; /* Adjusted by the async layer ! */ 26446686Sbrian for (layer = l->nlayers; layer && bp; layer--) 26546686Sbrian if (l->layer[layer - 1]->push != NULL) 26646686Sbrian bp = (*l->layer[layer - 1]->push)(b, l, bp, pri, &proto); 26746686Sbrian 26846686Sbrian if (bp) { 26954912Sbrian link_AddOutOctets(l, m_length(bp)); 27047061Sbrian log_Printf(LogDEBUG, "link_PushPacket: Transmit proto 0x%04x\n", proto); 27154912Sbrian m_enqueue(l->Queue + pri, m_pullup(bp)); 27246686Sbrian } 27346686Sbrian} 27446686Sbrian 27546686Sbrianvoid 27646686Sbrianlink_PullPacket(struct link *l, char *buf, size_t len, struct bundle *b) 27746686Sbrian{ 27846686Sbrian struct mbuf *bp, *lbp[LAYER_MAX], *next; 27946686Sbrian u_short lproto[LAYER_MAX], proto; 28046686Sbrian int layer; 28146686Sbrian 28246686Sbrian /* 28346686Sbrian * When we ``pull'' a packet from the link, it gets processed by the 28446686Sbrian * ``pull'' function in each layer starting at the bottom. 28546686Sbrian * Each ``pull'' may produce multiple packets, chained together using 28654912Sbrian * bp->m_nextpkt. 28746686Sbrian * Each packet that results from each pull has to be pulled through 28846686Sbrian * all of the higher layers before the next resulting packet is pulled 28946686Sbrian * through anything; this ensures that packets that depend on the 29046686Sbrian * fsm state resulting from the receipt of the previous packet aren't 29146686Sbrian * surprised. 29246686Sbrian */ 29346686Sbrian 29446686Sbrian link_AddInOctets(l, len); 29546686Sbrian 29646686Sbrian memset(lbp, '\0', sizeof lbp); 29754912Sbrian lbp[0] = m_get(len, MB_UNKNOWN); 29846686Sbrian memcpy(MBUF_CTOP(lbp[0]), buf, len); 29946686Sbrian lproto[0] = 0; 30046686Sbrian layer = 0; 30146686Sbrian 30246686Sbrian while (layer || lbp[layer]) { 30346686Sbrian if (lbp[layer] == NULL) { 30446686Sbrian layer--; 30546686Sbrian continue; 30646686Sbrian } 30746686Sbrian bp = lbp[layer]; 30854912Sbrian lbp[layer] = bp->m_nextpkt; 30954912Sbrian bp->m_nextpkt = NULL; 31046686Sbrian proto = lproto[layer]; 31146686Sbrian 31246686Sbrian if (l->layer[layer]->pull != NULL) 31346686Sbrian bp = (*l->layer[layer]->pull)(b, l, bp, &proto); 31446686Sbrian 31546686Sbrian if (layer == l->nlayers - 1) { 31646686Sbrian /* We've just done the top layer, despatch the packet(s) */ 31746686Sbrian while (bp) { 31854912Sbrian next = bp->m_nextpkt; 31954912Sbrian bp->m_nextpkt = NULL; 32047061Sbrian log_Printf(LogDEBUG, "link_PullPacket: Despatch proto 0x%04x\n", proto); 32146686Sbrian Despatch(b, l, bp, proto); 32246686Sbrian bp = next; 32346686Sbrian } 32446686Sbrian } else { 32546686Sbrian lbp[++layer] = bp; 32646686Sbrian lproto[layer] = proto; 32746686Sbrian } 32846686Sbrian } 32946686Sbrian} 33046686Sbrian 33146686Sbrianint 33246686Sbrianlink_Stack(struct link *l, struct layer *layer) 33346686Sbrian{ 33446686Sbrian if (l->nlayers == sizeof l->layer / sizeof l->layer[0]) { 33546686Sbrian log_Printf(LogERROR, "%s: Oops, cannot stack a %s layer...\n", 33646686Sbrian l->name, layer->name); 33746686Sbrian return 0; 33846686Sbrian } 33946686Sbrian l->layer[l->nlayers++] = layer; 34046686Sbrian return 1; 34146686Sbrian} 34246686Sbrian 34346686Sbrianvoid 34446686Sbrianlink_EmptyStack(struct link *l) 34546686Sbrian{ 34646686Sbrian l->nlayers = 0; 34746686Sbrian} 34846686Sbrian 34946686Sbrianstatic const struct { 35046686Sbrian u_short proto; 35146686Sbrian struct mbuf *(*fn)(struct bundle *, struct link *, struct mbuf *); 35246686Sbrian} despatcher[] = { 35381634Sbrian { PROTO_IP, ipv4_Input }, 35481634Sbrian#ifndef NOINET6 35581634Sbrian { PROTO_IPV6, ipv6_Input }, 35681634Sbrian#endif 35746686Sbrian { PROTO_MP, mp_Input }, 35846686Sbrian { PROTO_LCP, lcp_Input }, 35946686Sbrian { PROTO_IPCP, ipcp_Input }, 36081634Sbrian#ifndef NOINET6 36181634Sbrian { PROTO_IPV6CP, ipv6cp_Input }, 36281634Sbrian#endif 36346686Sbrian { PROTO_PAP, pap_Input }, 36446686Sbrian { PROTO_CHAP, chap_Input }, 36546686Sbrian { PROTO_CCP, ccp_Input }, 36646686Sbrian { PROTO_LQR, lqr_Input }, 36746686Sbrian { PROTO_CBCP, cbcp_Input } 36846686Sbrian}; 36946686Sbrian 37046686Sbrian#define DSIZE (sizeof despatcher / sizeof despatcher[0]) 37146686Sbrian 37246686Sbrianstatic void 37346686SbrianDespatch(struct bundle *bundle, struct link *l, struct mbuf *bp, u_short proto) 37446686Sbrian{ 375134789Sbrian unsigned f; 37646686Sbrian 37746686Sbrian for (f = 0; f < DSIZE; f++) 37846686Sbrian if (despatcher[f].proto == proto) { 37946686Sbrian bp = (*despatcher[f].fn)(bundle, l, bp); 38046686Sbrian break; 38146686Sbrian } 38246686Sbrian 38346686Sbrian if (bp) { 38446686Sbrian struct physical *p = link2physical(l); 38546686Sbrian 38646686Sbrian log_Printf(LogPHASE, "%s protocol 0x%04x (%s)\n", 38746686Sbrian f == DSIZE ? "Unknown" : "Unexpected", proto, 38846686Sbrian hdlc_Protocol2Nam(proto)); 38954912Sbrian bp = m_pullup(proto_Prepend(bp, proto, 0, 0)); 39054912Sbrian lcp_SendProtoRej(&l->lcp, MBUF_CTOP(bp), bp->m_len); 39146686Sbrian if (p) { 392131327Sbrian p->hdlc.lqm.ifInDiscards++; 39346686Sbrian p->hdlc.stats.unknownproto++; 39446686Sbrian } 39554912Sbrian m_freem(bp); 39646686Sbrian } 39746686Sbrian} 39847211Sbrian 39947211Sbrianint 40047211Sbrianlink_ShowLayers(struct cmdargs const *arg) 40147211Sbrian{ 40247211Sbrian struct link *l = command_ChooseLink(arg); 40347211Sbrian int layer; 40447211Sbrian 40547211Sbrian for (layer = l->nlayers; layer; layer--) 40647211Sbrian prompt_Printf(arg->prompt, "%s%s", layer == l->nlayers ? "" : ", ", 40747211Sbrian l->layer[layer - 1]->name); 40847211Sbrian if (l->nlayers) 40947211Sbrian prompt_Printf(arg->prompt, "\n"); 41047211Sbrian 41147211Sbrian return 0; 41247211Sbrian} 413