cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdlc_ppp.c (19353B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Generic HDLC support routines for Linux
      4 * Point-to-point protocol support
      5 *
      6 * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl>
      7 */
      8
      9#include <linux/errno.h>
     10#include <linux/hdlc.h>
     11#include <linux/if_arp.h>
     12#include <linux/inetdevice.h>
     13#include <linux/init.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/pkt_sched.h>
     17#include <linux/poll.h>
     18#include <linux/skbuff.h>
     19#include <linux/slab.h>
     20#include <linux/spinlock.h>
     21
     22#define DEBUG_CP		0 /* also bytes# to dump */
     23#define DEBUG_STATE		0
     24#define DEBUG_HARD_HEADER	0
     25
     26#define HDLC_ADDR_ALLSTATIONS	0xFF
     27#define HDLC_CTRL_UI		0x03
     28
     29#define PID_LCP			0xC021
     30#define PID_IP			0x0021
     31#define PID_IPCP		0x8021
     32#define PID_IPV6		0x0057
     33#define PID_IPV6CP		0x8057
     34
     35enum {IDX_LCP = 0, IDX_IPCP, IDX_IPV6CP, IDX_COUNT};
     36enum {CP_CONF_REQ = 1, CP_CONF_ACK, CP_CONF_NAK, CP_CONF_REJ, CP_TERM_REQ,
     37      CP_TERM_ACK, CP_CODE_REJ, LCP_PROTO_REJ, LCP_ECHO_REQ, LCP_ECHO_REPLY,
     38      LCP_DISC_REQ, CP_CODES};
     39#if DEBUG_CP
     40static const char *const code_names[CP_CODES] = {
     41	"0", "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq",
     42	"TermAck", "CodeRej", "ProtoRej", "EchoReq", "EchoReply", "Discard"
     43};
     44
     45static char debug_buffer[64 + 3 * DEBUG_CP];
     46#endif
     47
     48enum {LCP_OPTION_MRU = 1, LCP_OPTION_ACCM, LCP_OPTION_MAGIC = 5};
     49
     50struct hdlc_header {
     51	u8 address;
     52	u8 control;
     53	__be16 protocol;
     54};
     55
     56struct cp_header {
     57	u8 code;
     58	u8 id;
     59	__be16 len;
     60};
     61
     62struct proto {
     63	struct net_device *dev;
     64	struct timer_list timer;
     65	unsigned long timeout;
     66	u16 pid;		/* protocol ID */
     67	u8 state;
     68	u8 cr_id;		/* ID of last Configuration-Request */
     69	u8 restart_counter;
     70};
     71
     72struct ppp {
     73	struct proto protos[IDX_COUNT];
     74	spinlock_t lock;
     75	unsigned long last_pong;
     76	unsigned int req_timeout, cr_retries, term_retries;
     77	unsigned int keepalive_interval, keepalive_timeout;
     78	u8 seq;			/* local sequence number for requests */
     79	u8 echo_id;		/* ID of last Echo-Request (LCP) */
     80};
     81
     82enum {CLOSED = 0, STOPPED, STOPPING, REQ_SENT, ACK_RECV, ACK_SENT, OPENED,
     83      STATES, STATE_MASK = 0xF};
     84enum {START = 0, STOP, TO_GOOD, TO_BAD, RCR_GOOD, RCR_BAD, RCA, RCN, RTR, RTA,
     85      RUC, RXJ_GOOD, RXJ_BAD, EVENTS};
     86enum {INV = 0x10, IRC = 0x20, ZRC = 0x40, SCR = 0x80, SCA = 0x100,
     87      SCN = 0x200, STR = 0x400, STA = 0x800, SCJ = 0x1000};
     88
     89#if DEBUG_STATE
     90static const char *const state_names[STATES] = {
     91	"Closed", "Stopped", "Stopping", "ReqSent", "AckRecv", "AckSent",
     92	"Opened"
     93};
     94
     95static const char *const event_names[EVENTS] = {
     96	"Start", "Stop", "TO+", "TO-", "RCR+", "RCR-", "RCA", "RCN",
     97	"RTR", "RTA", "RUC", "RXJ+", "RXJ-"
     98};
     99#endif
    100
    101static struct sk_buff_head tx_queue; /* used when holding the spin lock */
    102
    103static int ppp_ioctl(struct net_device *dev, struct if_settings *ifs);
    104
    105static inline struct ppp *get_ppp(struct net_device *dev)
    106{
    107	return (struct ppp *)dev_to_hdlc(dev)->state;
    108}
    109
    110static inline struct proto *get_proto(struct net_device *dev, u16 pid)
    111{
    112	struct ppp *ppp = get_ppp(dev);
    113
    114	switch (pid) {
    115	case PID_LCP:
    116		return &ppp->protos[IDX_LCP];
    117	case PID_IPCP:
    118		return &ppp->protos[IDX_IPCP];
    119	case PID_IPV6CP:
    120		return &ppp->protos[IDX_IPV6CP];
    121	default:
    122		return NULL;
    123	}
    124}
    125
    126static inline const char *proto_name(u16 pid)
    127{
    128	switch (pid) {
    129	case PID_LCP:
    130		return "LCP";
    131	case PID_IPCP:
    132		return "IPCP";
    133	case PID_IPV6CP:
    134		return "IPV6CP";
    135	default:
    136		return NULL;
    137	}
    138}
    139
    140static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
    141{
    142	struct hdlc_header *data = (struct hdlc_header *)skb->data;
    143
    144	if (skb->len < sizeof(struct hdlc_header))
    145		return htons(ETH_P_HDLC);
    146	if (data->address != HDLC_ADDR_ALLSTATIONS ||
    147	    data->control != HDLC_CTRL_UI)
    148		return htons(ETH_P_HDLC);
    149
    150	switch (data->protocol) {
    151	case cpu_to_be16(PID_IP):
    152		skb_pull(skb, sizeof(struct hdlc_header));
    153		return htons(ETH_P_IP);
    154
    155	case cpu_to_be16(PID_IPV6):
    156		skb_pull(skb, sizeof(struct hdlc_header));
    157		return htons(ETH_P_IPV6);
    158
    159	default:
    160		return htons(ETH_P_HDLC);
    161	}
    162}
    163
    164static int ppp_hard_header(struct sk_buff *skb, struct net_device *dev,
    165			   u16 type, const void *daddr, const void *saddr,
    166			   unsigned int len)
    167{
    168	struct hdlc_header *data;
    169#if DEBUG_HARD_HEADER
    170	printk(KERN_DEBUG "%s: ppp_hard_header() called\n", dev->name);
    171#endif
    172
    173	skb_push(skb, sizeof(struct hdlc_header));
    174	data = (struct hdlc_header *)skb->data;
    175
    176	data->address = HDLC_ADDR_ALLSTATIONS;
    177	data->control = HDLC_CTRL_UI;
    178	switch (type) {
    179	case ETH_P_IP:
    180		data->protocol = htons(PID_IP);
    181		break;
    182	case ETH_P_IPV6:
    183		data->protocol = htons(PID_IPV6);
    184		break;
    185	case PID_LCP:
    186	case PID_IPCP:
    187	case PID_IPV6CP:
    188		data->protocol = htons(type);
    189		break;
    190	default:		/* unknown protocol */
    191		data->protocol = 0;
    192	}
    193	return sizeof(struct hdlc_header);
    194}
    195
    196static void ppp_tx_flush(void)
    197{
    198	struct sk_buff *skb;
    199
    200	while ((skb = skb_dequeue(&tx_queue)) != NULL)
    201		dev_queue_xmit(skb);
    202}
    203
    204static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code,
    205		      u8 id, unsigned int len, const void *data)
    206{
    207	struct sk_buff *skb;
    208	struct cp_header *cp;
    209	unsigned int magic_len = 0;
    210	static u32 magic;
    211
    212#if DEBUG_CP
    213	int i;
    214	char *ptr;
    215#endif
    216
    217	if (pid == PID_LCP && (code == LCP_ECHO_REQ || code == LCP_ECHO_REPLY))
    218		magic_len = sizeof(magic);
    219
    220	skb = dev_alloc_skb(sizeof(struct hdlc_header) +
    221			    sizeof(struct cp_header) + magic_len + len);
    222	if (!skb)
    223		return;
    224
    225	skb_reserve(skb, sizeof(struct hdlc_header));
    226
    227	cp = skb_put(skb, sizeof(struct cp_header));
    228	cp->code = code;
    229	cp->id = id;
    230	cp->len = htons(sizeof(struct cp_header) + magic_len + len);
    231
    232	if (magic_len)
    233		skb_put_data(skb, &magic, magic_len);
    234	if (len)
    235		skb_put_data(skb, data, len);
    236
    237#if DEBUG_CP
    238	BUG_ON(code >= CP_CODES);
    239	ptr = debug_buffer;
    240	*ptr = '\x0';
    241	for (i = 0; i < min_t(unsigned int, magic_len + len, DEBUG_CP); i++) {
    242		sprintf(ptr, " %02X", skb->data[sizeof(struct cp_header) + i]);
    243		ptr += strlen(ptr);
    244	}
    245	printk(KERN_DEBUG "%s: TX %s [%s id 0x%X]%s\n", dev->name,
    246	       proto_name(pid), code_names[code], id, debug_buffer);
    247#endif
    248
    249	ppp_hard_header(skb, dev, pid, NULL, NULL, 0);
    250
    251	skb->priority = TC_PRIO_CONTROL;
    252	skb->dev = dev;
    253	skb->protocol = htons(ETH_P_HDLC);
    254	skb_reset_network_header(skb);
    255	skb_queue_tail(&tx_queue, skb);
    256}
    257
    258/* State transition table (compare STD-51)
    259   Events                                   Actions
    260   TO+  = Timeout with counter > 0          irc = Initialize-Restart-Count
    261   TO-  = Timeout with counter expired      zrc = Zero-Restart-Count
    262
    263   RCR+ = Receive-Configure-Request (Good)  scr = Send-Configure-Request
    264   RCR- = Receive-Configure-Request (Bad)
    265   RCA  = Receive-Configure-Ack             sca = Send-Configure-Ack
    266   RCN  = Receive-Configure-Nak/Rej         scn = Send-Configure-Nak/Rej
    267
    268   RTR  = Receive-Terminate-Request         str = Send-Terminate-Request
    269   RTA  = Receive-Terminate-Ack             sta = Send-Terminate-Ack
    270
    271   RUC  = Receive-Unknown-Code              scj = Send-Code-Reject
    272   RXJ+ = Receive-Code-Reject (permitted)
    273       or Receive-Protocol-Reject
    274   RXJ- = Receive-Code-Reject (catastrophic)
    275       or Receive-Protocol-Reject
    276*/
    277static int cp_table[EVENTS][STATES] = {
    278	/* CLOSED     STOPPED STOPPING REQ_SENT ACK_RECV ACK_SENT OPENED
    279	     0           1         2       3       4      5          6    */
    280	{IRC|SCR|3,     INV     , INV ,   INV   , INV ,  INV    ,   INV   }, /* START */
    281	{   INV   ,      0      ,  0  ,    0    ,  0  ,   0     ,    0    }, /* STOP */
    282	{   INV   ,     INV     ,STR|2,  SCR|3  ,SCR|3,  SCR|5  ,   INV   }, /* TO+ */
    283	{   INV   ,     INV     ,  1  ,    1    ,  1  ,    1    ,   INV   }, /* TO- */
    284	{  STA|0  ,IRC|SCR|SCA|5,  2  ,  SCA|5  ,SCA|6,  SCA|5  ,SCR|SCA|5}, /* RCR+ */
    285	{  STA|0  ,IRC|SCR|SCN|3,  2  ,  SCN|3  ,SCN|4,  SCN|3  ,SCR|SCN|3}, /* RCR- */
    286	{  STA|0  ,    STA|1    ,  2  ,  IRC|4  ,SCR|3,    6    , SCR|3   }, /* RCA */
    287	{  STA|0  ,    STA|1    ,  2  ,IRC|SCR|3,SCR|3,IRC|SCR|5, SCR|3   }, /* RCN */
    288	{  STA|0  ,    STA|1    ,STA|2,  STA|3  ,STA|3,  STA|3  ,ZRC|STA|2}, /* RTR */
    289	{    0    ,      1      ,  1  ,    3    ,  3  ,    5    ,  SCR|3  }, /* RTA */
    290	{  SCJ|0  ,    SCJ|1    ,SCJ|2,  SCJ|3  ,SCJ|4,  SCJ|5  ,  SCJ|6  }, /* RUC */
    291	{    0    ,      1      ,  2  ,    3    ,  3  ,    5    ,    6    }, /* RXJ+ */
    292	{    0    ,      1      ,  1  ,    1    ,  1  ,    1    ,IRC|STR|2}, /* RXJ- */
    293};
    294
    295/* SCA: RCR+ must supply id, len and data
    296   SCN: RCR- must supply code, id, len and data
    297   STA: RTR must supply id
    298   SCJ: RUC must supply CP packet len and data */
    299static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
    300			 u8 id, unsigned int len, const void *data)
    301{
    302	int old_state, action;
    303	struct ppp *ppp = get_ppp(dev);
    304	struct proto *proto = get_proto(dev, pid);
    305
    306	old_state = proto->state;
    307	BUG_ON(old_state >= STATES);
    308	BUG_ON(event >= EVENTS);
    309
    310#if DEBUG_STATE
    311	printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) %s ...\n", dev->name,
    312	       proto_name(pid), event_names[event], state_names[proto->state]);
    313#endif
    314
    315	action = cp_table[event][old_state];
    316
    317	proto->state = action & STATE_MASK;
    318	if (action & (SCR | STR)) /* set Configure-Req/Terminate-Req timer */
    319		mod_timer(&proto->timer, proto->timeout =
    320			  jiffies + ppp->req_timeout * HZ);
    321	if (action & ZRC)
    322		proto->restart_counter = 0;
    323	if (action & IRC)
    324		proto->restart_counter = (proto->state == STOPPING) ?
    325			ppp->term_retries : ppp->cr_retries;
    326
    327	if (action & SCR)	/* send Configure-Request */
    328		ppp_tx_cp(dev, pid, CP_CONF_REQ, proto->cr_id = ++ppp->seq,
    329			  0, NULL);
    330	if (action & SCA)	/* send Configure-Ack */
    331		ppp_tx_cp(dev, pid, CP_CONF_ACK, id, len, data);
    332	if (action & SCN)	/* send Configure-Nak/Reject */
    333		ppp_tx_cp(dev, pid, code, id, len, data);
    334	if (action & STR)	/* send Terminate-Request */
    335		ppp_tx_cp(dev, pid, CP_TERM_REQ, ++ppp->seq, 0, NULL);
    336	if (action & STA)	/* send Terminate-Ack */
    337		ppp_tx_cp(dev, pid, CP_TERM_ACK, id, 0, NULL);
    338	if (action & SCJ)	/* send Code-Reject */
    339		ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data);
    340
    341	if (old_state != OPENED && proto->state == OPENED) {
    342		netdev_info(dev, "%s up\n", proto_name(pid));
    343		if (pid == PID_LCP) {
    344			netif_dormant_off(dev);
    345			ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL);
    346			ppp_cp_event(dev, PID_IPV6CP, START, 0, 0, 0, NULL);
    347			ppp->last_pong = jiffies;
    348			mod_timer(&proto->timer, proto->timeout =
    349				  jiffies + ppp->keepalive_interval * HZ);
    350		}
    351	}
    352	if (old_state == OPENED && proto->state != OPENED) {
    353		netdev_info(dev, "%s down\n", proto_name(pid));
    354		if (pid == PID_LCP) {
    355			netif_dormant_on(dev);
    356			ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL);
    357			ppp_cp_event(dev, PID_IPV6CP, STOP, 0, 0, 0, NULL);
    358		}
    359	}
    360	if (old_state != CLOSED && proto->state == CLOSED)
    361		del_timer(&proto->timer);
    362
    363#if DEBUG_STATE
    364	printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) ... %s\n", dev->name,
    365	       proto_name(pid), event_names[event], state_names[proto->state]);
    366#endif
    367}
    368
    369static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id,
    370			    unsigned int req_len, const u8 *data)
    371{
    372	static u8 const valid_accm[6] = { LCP_OPTION_ACCM, 6, 0, 0, 0, 0 };
    373	const u8 *opt;
    374	u8 *out;
    375	unsigned int len = req_len, nak_len = 0, rej_len = 0;
    376
    377	out = kmalloc(len, GFP_ATOMIC);
    378	if (!out) {
    379		dev->stats.rx_dropped++;
    380		return;	/* out of memory, ignore CR packet */
    381	}
    382
    383	for (opt = data; len; len -= opt[1], opt += opt[1]) {
    384		if (len < 2 || opt[1] < 2 || len < opt[1])
    385			goto err_out;
    386
    387		if (pid == PID_LCP)
    388			switch (opt[0]) {
    389			case LCP_OPTION_MRU:
    390				continue; /* MRU always OK and > 1500 bytes? */
    391
    392			case LCP_OPTION_ACCM: /* async control character map */
    393				if (opt[1] < sizeof(valid_accm))
    394					goto err_out;
    395				if (!memcmp(opt, valid_accm,
    396					    sizeof(valid_accm)))
    397					continue;
    398				if (!rej_len) { /* NAK it */
    399					memcpy(out + nak_len, valid_accm,
    400					       sizeof(valid_accm));
    401					nak_len += sizeof(valid_accm);
    402					continue;
    403				}
    404				break;
    405			case LCP_OPTION_MAGIC:
    406				if (len < 6)
    407					goto err_out;
    408				if (opt[1] != 6 || (!opt[2] && !opt[3] &&
    409						    !opt[4] && !opt[5]))
    410					break; /* reject invalid magic number */
    411				continue;
    412			}
    413		/* reject this option */
    414		memcpy(out + rej_len, opt, opt[1]);
    415		rej_len += opt[1];
    416	}
    417
    418	if (rej_len)
    419		ppp_cp_event(dev, pid, RCR_BAD, CP_CONF_REJ, id, rej_len, out);
    420	else if (nak_len)
    421		ppp_cp_event(dev, pid, RCR_BAD, CP_CONF_NAK, id, nak_len, out);
    422	else
    423		ppp_cp_event(dev, pid, RCR_GOOD, CP_CONF_ACK, id, req_len, data);
    424
    425	kfree(out);
    426	return;
    427
    428err_out:
    429	dev->stats.rx_errors++;
    430	kfree(out);
    431}
    432
    433static int ppp_rx(struct sk_buff *skb)
    434{
    435	struct hdlc_header *hdr = (struct hdlc_header *)skb->data;
    436	struct net_device *dev = skb->dev;
    437	struct ppp *ppp = get_ppp(dev);
    438	struct proto *proto;
    439	struct cp_header *cp;
    440	unsigned long flags;
    441	unsigned int len;
    442	u16 pid;
    443#if DEBUG_CP
    444	int i;
    445	char *ptr;
    446#endif
    447
    448	spin_lock_irqsave(&ppp->lock, flags);
    449	/* Check HDLC header */
    450	if (skb->len < sizeof(struct hdlc_header))
    451		goto rx_error;
    452	cp = skb_pull(skb, sizeof(struct hdlc_header));
    453	if (hdr->address != HDLC_ADDR_ALLSTATIONS ||
    454	    hdr->control != HDLC_CTRL_UI)
    455		goto rx_error;
    456
    457	pid = ntohs(hdr->protocol);
    458	proto = get_proto(dev, pid);
    459	if (!proto) {
    460		if (ppp->protos[IDX_LCP].state == OPENED)
    461			ppp_tx_cp(dev, PID_LCP, LCP_PROTO_REJ,
    462				  ++ppp->seq, skb->len + 2, &hdr->protocol);
    463		goto rx_error;
    464	}
    465
    466	len = ntohs(cp->len);
    467	if (len < sizeof(struct cp_header) /* no complete CP header? */ ||
    468	    skb->len < len /* truncated packet? */)
    469		goto rx_error;
    470	skb_pull(skb, sizeof(struct cp_header));
    471	len -= sizeof(struct cp_header);
    472
    473	/* HDLC and CP headers stripped from skb */
    474#if DEBUG_CP
    475	if (cp->code < CP_CODES)
    476		sprintf(debug_buffer, "[%s id 0x%X]", code_names[cp->code],
    477			cp->id);
    478	else
    479		sprintf(debug_buffer, "[code %u id 0x%X]", cp->code, cp->id);
    480	ptr = debug_buffer + strlen(debug_buffer);
    481	for (i = 0; i < min_t(unsigned int, len, DEBUG_CP); i++) {
    482		sprintf(ptr, " %02X", skb->data[i]);
    483		ptr += strlen(ptr);
    484	}
    485	printk(KERN_DEBUG "%s: RX %s %s\n", dev->name, proto_name(pid),
    486	       debug_buffer);
    487#endif
    488
    489	/* LCP only */
    490	if (pid == PID_LCP)
    491		switch (cp->code) {
    492		case LCP_PROTO_REJ:
    493			pid = ntohs(*(__be16 *)skb->data);
    494			if (pid == PID_LCP || pid == PID_IPCP ||
    495			    pid == PID_IPV6CP)
    496				ppp_cp_event(dev, pid, RXJ_BAD, 0, 0,
    497					     0, NULL);
    498			goto out;
    499
    500		case LCP_ECHO_REQ: /* send Echo-Reply */
    501			if (len >= 4 && proto->state == OPENED)
    502				ppp_tx_cp(dev, PID_LCP, LCP_ECHO_REPLY,
    503					  cp->id, len - 4, skb->data + 4);
    504			goto out;
    505
    506		case LCP_ECHO_REPLY:
    507			if (cp->id == ppp->echo_id)
    508				ppp->last_pong = jiffies;
    509			goto out;
    510
    511		case LCP_DISC_REQ: /* discard */
    512			goto out;
    513		}
    514
    515	/* LCP, IPCP and IPV6CP */
    516	switch (cp->code) {
    517	case CP_CONF_REQ:
    518		ppp_cp_parse_cr(dev, pid, cp->id, len, skb->data);
    519		break;
    520
    521	case CP_CONF_ACK:
    522		if (cp->id == proto->cr_id)
    523			ppp_cp_event(dev, pid, RCA, 0, 0, 0, NULL);
    524		break;
    525
    526	case CP_CONF_REJ:
    527	case CP_CONF_NAK:
    528		if (cp->id == proto->cr_id)
    529			ppp_cp_event(dev, pid, RCN, 0, 0, 0, NULL);
    530		break;
    531
    532	case CP_TERM_REQ:
    533		ppp_cp_event(dev, pid, RTR, 0, cp->id, 0, NULL);
    534		break;
    535
    536	case CP_TERM_ACK:
    537		ppp_cp_event(dev, pid, RTA, 0, 0, 0, NULL);
    538		break;
    539
    540	case CP_CODE_REJ:
    541		ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, 0, NULL);
    542		break;
    543
    544	default:
    545		len += sizeof(struct cp_header);
    546		if (len > dev->mtu)
    547			len = dev->mtu;
    548		ppp_cp_event(dev, pid, RUC, 0, 0, len, cp);
    549		break;
    550	}
    551	goto out;
    552
    553rx_error:
    554	dev->stats.rx_errors++;
    555out:
    556	spin_unlock_irqrestore(&ppp->lock, flags);
    557	dev_kfree_skb_any(skb);
    558	ppp_tx_flush();
    559	return NET_RX_DROP;
    560}
    561
    562static void ppp_timer(struct timer_list *t)
    563{
    564	struct proto *proto = from_timer(proto, t, timer);
    565	struct ppp *ppp = get_ppp(proto->dev);
    566	unsigned long flags;
    567
    568	spin_lock_irqsave(&ppp->lock, flags);
    569	/* mod_timer could be called after we entered this function but
    570	 * before we got the lock.
    571	 */
    572	if (timer_pending(&proto->timer)) {
    573		spin_unlock_irqrestore(&ppp->lock, flags);
    574		return;
    575	}
    576	switch (proto->state) {
    577	case STOPPING:
    578	case REQ_SENT:
    579	case ACK_RECV:
    580	case ACK_SENT:
    581		if (proto->restart_counter) {
    582			ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0,
    583				     0, NULL);
    584			proto->restart_counter--;
    585		} else if (netif_carrier_ok(proto->dev))
    586			ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0,
    587				     0, NULL);
    588		else
    589			ppp_cp_event(proto->dev, proto->pid, TO_BAD, 0, 0,
    590				     0, NULL);
    591		break;
    592
    593	case OPENED:
    594		if (proto->pid != PID_LCP)
    595			break;
    596		if (time_after(jiffies, ppp->last_pong +
    597			       ppp->keepalive_timeout * HZ)) {
    598			netdev_info(proto->dev, "Link down\n");
    599			ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL);
    600			ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL);
    601		} else {	/* send keep-alive packet */
    602			ppp->echo_id = ++ppp->seq;
    603			ppp_tx_cp(proto->dev, PID_LCP, LCP_ECHO_REQ,
    604				  ppp->echo_id, 0, NULL);
    605			proto->timer.expires = jiffies +
    606				ppp->keepalive_interval * HZ;
    607			add_timer(&proto->timer);
    608		}
    609		break;
    610	}
    611	spin_unlock_irqrestore(&ppp->lock, flags);
    612	ppp_tx_flush();
    613}
    614
    615static void ppp_start(struct net_device *dev)
    616{
    617	struct ppp *ppp = get_ppp(dev);
    618	int i;
    619
    620	for (i = 0; i < IDX_COUNT; i++) {
    621		struct proto *proto = &ppp->protos[i];
    622
    623		proto->dev = dev;
    624		timer_setup(&proto->timer, ppp_timer, 0);
    625		proto->state = CLOSED;
    626	}
    627	ppp->protos[IDX_LCP].pid = PID_LCP;
    628	ppp->protos[IDX_IPCP].pid = PID_IPCP;
    629	ppp->protos[IDX_IPV6CP].pid = PID_IPV6CP;
    630
    631	ppp_cp_event(dev, PID_LCP, START, 0, 0, 0, NULL);
    632}
    633
    634static void ppp_stop(struct net_device *dev)
    635{
    636	ppp_cp_event(dev, PID_LCP, STOP, 0, 0, 0, NULL);
    637}
    638
    639static void ppp_close(struct net_device *dev)
    640{
    641	ppp_tx_flush();
    642}
    643
    644static struct hdlc_proto proto = {
    645	.start		= ppp_start,
    646	.stop		= ppp_stop,
    647	.close		= ppp_close,
    648	.type_trans	= ppp_type_trans,
    649	.ioctl		= ppp_ioctl,
    650	.netif_rx	= ppp_rx,
    651	.module		= THIS_MODULE,
    652};
    653
    654static const struct header_ops ppp_header_ops = {
    655	.create = ppp_hard_header,
    656};
    657
    658static int ppp_ioctl(struct net_device *dev, struct if_settings *ifs)
    659{
    660	hdlc_device *hdlc = dev_to_hdlc(dev);
    661	struct ppp *ppp;
    662	int result;
    663
    664	switch (ifs->type) {
    665	case IF_GET_PROTO:
    666		if (dev_to_hdlc(dev)->proto != &proto)
    667			return -EINVAL;
    668		ifs->type = IF_PROTO_PPP;
    669		return 0; /* return protocol only, no settable parameters */
    670
    671	case IF_PROTO_PPP:
    672		if (!capable(CAP_NET_ADMIN))
    673			return -EPERM;
    674
    675		if (dev->flags & IFF_UP)
    676			return -EBUSY;
    677
    678		/* no settable parameters */
    679
    680		result = hdlc->attach(dev, ENCODING_NRZ,
    681				      PARITY_CRC16_PR1_CCITT);
    682		if (result)
    683			return result;
    684
    685		result = attach_hdlc_protocol(dev, &proto, sizeof(struct ppp));
    686		if (result)
    687			return result;
    688
    689		ppp = get_ppp(dev);
    690		spin_lock_init(&ppp->lock);
    691		ppp->req_timeout = 2;
    692		ppp->cr_retries = 10;
    693		ppp->term_retries = 2;
    694		ppp->keepalive_interval = 10;
    695		ppp->keepalive_timeout = 60;
    696
    697		dev->hard_header_len = sizeof(struct hdlc_header);
    698		dev->header_ops = &ppp_header_ops;
    699		dev->type = ARPHRD_PPP;
    700		call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
    701		netif_dormant_on(dev);
    702		return 0;
    703	}
    704
    705	return -EINVAL;
    706}
    707
    708static int __init hdlc_ppp_init(void)
    709{
    710	skb_queue_head_init(&tx_queue);
    711	register_hdlc_protocol(&proto);
    712	return 0;
    713}
    714
    715static void __exit hdlc_ppp_exit(void)
    716{
    717	unregister_hdlc_protocol(&proto);
    718}
    719
    720module_init(hdlc_ppp_init);
    721module_exit(hdlc_ppp_exit);
    722
    723MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
    724MODULE_DESCRIPTION("PPP protocol support for generic HDLC");
    725MODULE_LICENSE("GPL v2");