1/*-
2 * Synchronous Frame Relay link level subroutines.
3 * ANSI T1.617-compaible link management signaling
4 * implemented for Frame Relay mode.
5 * Cisco-type Frame Relay framing added, thanks Alex Tutubalin.
6 * Only one DLCI per channel for now.
7 *
8 * Copyright (C) 1994-2000 Cronyx Engineering.
9 * Author: Serge Vakulenko, <vak@cronyx.ru>
10 *
11 * Copyright (C) 1999-2004 Cronyx Engineering.
12 * Author: Kurakin Roman, <rik@cronyx.ru>
13 *
14 * This software is distributed with NO WARRANTIES, not even the implied
15 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * Authors grant any other persons or organisations a permission to use,
18 * modify and redistribute this software in source and binary forms,
19 * as long as this message is kept with the software, all derivative
20 * works or modified versions.
21 *
22 * $Cronyx Id: if_spppfr.c,v 1.1.2.10 2004/06/29 09:02:30 rik Exp $
23 * $FreeBSD$
24 */
25
26#include <sys/param.h>
27
28#if defined(__FreeBSD__)
29#include "opt_inet.h"
30#include "opt_inet6.h"
31#endif
32
33#ifdef NetBSD1_3
34#  if NetBSD1_3 > 6
35#      include "opt_inet.h"
36#      include "opt_inet6.h"
37#      include "opt_iso.h"
38#  endif
39#endif
40
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/module.h>
44#include <sys/sockio.h>
45#include <sys/socket.h>
46#include <sys/syslog.h>
47#if defined(__FreeBSD__)
48#include <sys/random.h>
49#endif
50#include <sys/malloc.h>
51#include <sys/mbuf.h>
52
53#if defined (__OpenBSD__)
54#include <sys/md5k.h>
55#else
56#include <sys/md5.h>
57#endif
58
59#include <net/if.h>
60#include <net/if_var.h>
61#include <net/netisr.h>
62#include <net/if_types.h>
63#include <net/route.h>
64#include <netinet/in.h>
65#include <netinet/in_systm.h>
66#include <netinet/ip.h>
67#include <net/slcompress.h>
68
69#if defined (__NetBSD__) || defined (__OpenBSD__)
70#include <machine/cpu.h> /* XXX for softnet */
71#endif
72
73#include <machine/stdarg.h>
74
75#include <netinet/in_var.h>
76#ifdef INET
77#include <netinet/ip.h>
78#include <netinet/tcp.h>
79#endif
80
81#if defined (__FreeBSD__) || defined (__OpenBSD__)
82#  include <netinet/if_ether.h>
83#else
84#  include <net/ethertypes.h>
85#endif
86
87#include <net/if_sppp.h>
88
89/*
90 * Frame Relay.
91 */
92#define FR_UI		0x03	/* Unnumbered Information */
93#define FR_IP           0xCC    /* IP protocol identifier */
94#define FR_PADDING      0x00    /* NLPID padding */
95#define FR_SIGNALING    0x08    /* Q.933/T1.617 signaling identifier */
96#define FR_SNAP         0x80    /* NLPID snap */
97
98/*
99 * Header flags.
100 */
101#define FR_DE           0x02    /* discard eligibility */
102#define FR_FECN         0x04    /* forward notification */
103#define FR_BECN         0x08    /* backward notification */
104
105/*
106 * Signaling message types.
107 */
108#define FR_MSG_ENQUIRY  0x75    /* status enquiry */
109#define FR_MSG_STATUS   0x7d    /* status */
110
111#define FR_ENQUIRY_SIZE	14
112
113/*
114 * Message field types.
115 */
116#define FR_FLD_RTYPE    0x01    /* report type */
117#define FR_FLD_VERIFY   0x03    /* link verification */
118#define FR_FLD_PVC      0x07    /* PVC status */
119#define FR_FLD_LSHIFT5  0x95    /* locking shift 5 */
120
121/*
122 * Report types.
123 */
124#define FR_RTYPE_FULL   0       /* full status */
125#define FR_RTYPE_SHORT  1       /* link verification only */
126#define FR_RTYPE_SINGLE 2       /* single PVC status */
127
128/* PVC status field. */
129#define FR_DLCI_DELETE  0x04    /* PVC is deleted */
130#define FR_DLCI_ACTIVE  0x02    /* PVC is operational */
131#define FR_DLCI_NEW     0x08    /* PVC is new */
132
133struct arp_req {
134	unsigned short  htype;          /* hardware type = ARPHRD_FRELAY */
135	unsigned short  ptype;          /* protocol type = ETHERTYPE_IP */
136	unsigned char   halen;          /* hardware address length = 2 */
137	unsigned char   palen;          /* protocol address length = 4 */
138	unsigned short  op;             /* ARP/RARP/InARP request/reply */
139	unsigned short  hsource;        /* hardware source address */
140	unsigned short  psource1;       /* protocol source */
141	unsigned short  psource2;
142	unsigned short  htarget;        /* hardware target address */
143	unsigned short  ptarget1;       /* protocol target */
144	unsigned short  ptarget2;
145} __packed;
146
147#if defined(__FreeBSD__) && __FreeBSD_version < 501113
148#define	SPP_FMT		"%s%d: "
149#define	SPP_ARGS(ifp)	(ifp)->if_name, (ifp)->if_unit
150#else
151#define	SPP_FMT		"%s: "
152#define	SPP_ARGS(ifp)	(ifp)->if_xname
153#endif
154
155/* almost every function needs these */
156#define STDDCL							\
157	struct ifnet *ifp = SP2IFP(sp);				\
158	int debug = ifp->if_flags & IFF_DEBUG
159
160static void sppp_fr_arp (struct sppp *sp, struct arp_req *req, u_short addr);
161static void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len);
162
163void sppp_fr_input (struct sppp *sp, struct mbuf *m)
164{
165	STDDCL;
166	u_char *h = mtod (m, u_char*);
167	int isr = -1;
168	int dlci, hlen, proto;
169
170	/* Get the DLCI number. */
171	if (m->m_pkthdr.len < 10) {
172bad:            m_freem (m);
173		return;
174	}
175	dlci = (h[0] << 2 & 0x3f0) | (h[1] >> 4 & 0x0f);
176
177	/* Process signaling packets. */
178	if (dlci == 0) {
179		sppp_fr_signal (sp, h, m->m_pkthdr.len);
180		m_freem (m);
181		return;
182	}
183
184	if (dlci != sp->fr_dlci) {
185		if (debug)
186			printf (SPP_FMT "Received packet from invalid DLCI %d\n",
187				SPP_ARGS(ifp), dlci);
188		goto bad;
189	}
190
191	/* Process the packet. */
192	if (ntohs (*(short*) (h+2)) == ETHERTYPE_IP) {
193                /* Prehistoric IP framing? */
194		h[2] = FR_UI;
195		h[3] = FR_IP;
196	}
197	if (h[2] != FR_UI) {
198		if (debug)
199			printf (SPP_FMT "Invalid frame relay header flag 0x%02x\n",
200				SPP_ARGS(ifp), h[2]);
201		goto bad;
202	}
203	switch (h[3]) {
204	default:
205		if (debug)
206			printf (SPP_FMT "Unsupported NLPID 0x%02x\n",
207				SPP_ARGS(ifp), h[3]);
208		goto bad;
209
210	case FR_PADDING:
211		if (h[4] != FR_SNAP) {
212			if (debug)
213				printf (SPP_FMT "Bad NLPID 0x%02x\n",
214					SPP_ARGS(ifp), h[4]);
215			goto bad;
216		}
217		if (h[5] || h[6] || h[7]) {
218			if (debug)
219				printf (SPP_FMT "Bad OID 0x%02x-0x%02x-0x%02x\n",
220					SPP_ARGS(ifp),
221					h[5], h[6], h[7]);
222			goto bad;
223		}
224		proto = ntohs (*(short*) (h+8));
225		if (proto == ETHERTYPE_ARP) {
226			/* Process the ARP request. */
227			if (m->m_pkthdr.len != 10 + sizeof (struct arp_req)) {
228				if (debug)
229					printf (SPP_FMT "Bad ARP request size = %d bytes\n",
230						SPP_ARGS(ifp),
231						m->m_pkthdr.len);
232				goto bad;
233			}
234			sppp_fr_arp (sp, (struct arp_req*) (h + 10),
235				h[0] << 8 | h[1]);
236			m_freem (m);
237			return;
238		}
239		hlen = 10;
240		break;
241
242	case FR_IP:
243		proto = ETHERTYPE_IP;
244		hlen = 4;
245		break;
246	}
247
248	/* Remove frame relay header. */
249	m_adj (m, hlen);
250
251	switch (proto) {
252	default:
253		if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
254drop:		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
255		if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
256		m_freem (m);
257		return;
258#ifdef INET
259	case ETHERTYPE_IP:
260		isr = NETISR_IP;
261		break;
262#endif
263	}
264
265	if (! (ifp->if_flags & IFF_UP))
266		goto drop;
267
268	M_SETFIB(m, ifp->if_fib);
269
270	/* Check queue. */
271	if (netisr_queue(isr, m)) {	/* (0) on success. */
272		if (debug)
273			log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n",
274				SPP_ARGS(ifp));
275	}
276}
277
278/*
279 * Add the frame relay header to the packet.
280 * For IP the header length is 4 bytes,
281 * for all other protocols - 10 bytes (RFC 1490).
282 */
283struct mbuf *sppp_fr_header (struct sppp *sp, struct mbuf *m,
284	int family)
285{
286	STDDCL;
287	u_char *h;
288	int type, hlen;
289
290	/* Prepend the space for Frame Relay header. */
291	hlen = (family == AF_INET) ? 4 : 10;
292	M_PREPEND (m, hlen, M_NOWAIT);
293	if (! m)
294		return 0;
295	h = mtod (m, u_char*);
296
297	/* Fill the header. */
298	h[0] = sp->fr_dlci >> 2 & 0xfc;
299	h[1] = sp->fr_dlci << 4 | 1;
300	h[2] = FR_UI;
301
302	switch (family) {
303	default:
304		if (debug)
305			printf (SPP_FMT "Cannot handle address family %d\n",
306				SPP_ARGS(ifp), family);
307		m_freem (m);
308		return 0;
309#ifdef INET
310	case AF_INET:
311#if 0 /* Crashes on fragmented packets */
312		/*
313		 * Set the discard eligibility bit, if:
314		 * 1) no fragmentation
315		 * 2) length > 400 bytes
316		 * 3a) the protocol is UDP or
317		 * 3b) TCP data (no control bits)
318		 */
319		{
320		struct ip *ip = (struct ip*) (h + hlen);
321		struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);
322
323		if (! (ip->ip_off & ~IP_DF) && ip->ip_len > 400 &&
324		    (ip->ip_p == IPPROTO_UDP ||
325		    ip->ip_p == IPPROTO_TCP && ! tcp->th_flags))
326			h[1] |= FR_DE;
327		}
328#endif
329		h[3] = FR_IP;
330		return m;
331#endif
332#ifdef NS
333	case AF_NS:
334		type = 0x8137;
335		break;
336#endif
337	}
338	h[3] = FR_PADDING;
339	h[4] = FR_SNAP;
340	h[5] = 0;
341	h[6] = 0;
342	h[7] = 0;
343	*(short*) (h+8) = htons(type);
344	return m;
345}
346
347/*
348 * Send periodical frame relay link verification messages via DLCI 0.
349 * Called every 10 seconds (default value of T391 timer is 10 sec).
350 * Every 6-th message is a full status request
351 * (default value of N391 counter is 6).
352 */
353void sppp_fr_keepalive (struct sppp *sp)
354{
355	STDDCL;
356	unsigned char *h, *p;
357	struct mbuf *m;
358
359	MGETHDR (m, M_NOWAIT, MT_DATA);
360	if (! m)
361		return;
362	m->m_pkthdr.rcvif = 0;
363
364	h = mtod (m, u_char*);
365	p = h;
366	*p++ = 0;                       /* DLCI = 0 */
367	*p++ = 1;
368	*p++ = FR_UI;
369	*p++ = FR_SIGNALING;            /* NLPID = UNI call control */
370
371	*p++ = 0;                       /* call reference length = 0 */
372	*p++ = FR_MSG_ENQUIRY;          /* message type = status enquiry */
373
374	*p++ = FR_FLD_LSHIFT5;          /* locking shift 5 */
375
376	*p++ = FR_FLD_RTYPE;            /* report type field */
377	*p++ = 1;                       /* report type length = 1 */
378	if (sp->pp_seq[IDX_LCP] % 6)
379		*p++ = FR_RTYPE_SHORT;  /* link verification only */
380	else
381		*p++ = FR_RTYPE_FULL;   /* full status needed */
382
383	if (sp->pp_seq[IDX_LCP] >= 255)
384		sp->pp_seq[IDX_LCP] = 0;
385	*p++ = FR_FLD_VERIFY;           /* link verification type field */
386	*p++ = 2;                       /* link verification field length = 2 */
387	*p++ = ++sp->pp_seq[IDX_LCP];   /* our sequence number */
388	*p++ = sp->pp_rseq[IDX_LCP];    /* last received sequence number */
389
390	m->m_pkthdr.len = m->m_len = p - h;
391	if (debug)
392		printf (SPP_FMT "send lmi packet, seq=%d, rseq=%d\n",
393			SPP_ARGS(ifp), (u_char) sp->pp_seq[IDX_LCP],
394			(u_char) sp->pp_rseq[IDX_LCP]);
395
396	if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
397		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
398}
399
400/*
401 * Process the frame relay Inverse ARP request.
402 */
403static void sppp_fr_arp (struct sppp *sp, struct arp_req *req,
404	u_short his_hardware_address)
405{
406	STDDCL;
407	struct mbuf *m;
408	struct arp_req *reply;
409	u_char *h;
410	u_short my_hardware_address;
411	u_long his_ip_address, my_ip_address;
412
413	if ((ntohs (req->htype) != ARPHRD_FRELAY ||
414	    ntohs (req->htype) != 16) || /* for BayNetworks routers */
415	    ntohs (req->ptype) != ETHERTYPE_IP) {
416		if (debug)
417			printf (SPP_FMT "Invalid ARP hardware/protocol type = 0x%x/0x%x\n",
418				SPP_ARGS(ifp),
419				ntohs (req->htype), ntohs (req->ptype));
420		return;
421	}
422	if (req->halen != 2 || req->palen != 4) {
423		if (debug)
424			printf (SPP_FMT "Invalid ARP hardware/protocol address length = %d/%d\n",
425				SPP_ARGS(ifp),
426				req->halen, req->palen);
427		return;
428	}
429	switch (ntohs (req->op)) {
430	default:
431		if (debug)
432			printf (SPP_FMT "Invalid ARP op = 0x%x\n",
433				SPP_ARGS(ifp), ntohs (req->op));
434		return;
435
436	case ARPOP_INVREPLY:
437		/* Ignore. */
438		return;
439
440	case ARPOP_INVREQUEST:
441		my_hardware_address = ntohs (req->htarget);
442		his_ip_address = ntohs (req->psource1) << 16 |
443			ntohs (req->psource2);
444		my_ip_address = ntohs (req->ptarget1) << 16 |
445			ntohs (req->ptarget2);
446		break;
447	}
448	if (debug)
449		printf (SPP_FMT "got ARP request, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n",
450			SPP_ARGS(ifp), ntohs (req->hsource),
451			(unsigned char) (his_ip_address >> 24),
452			(unsigned char) (his_ip_address >> 16),
453			(unsigned char) (his_ip_address >> 8),
454			(unsigned char) his_ip_address,
455			my_hardware_address,
456			(unsigned char) (my_ip_address >> 24),
457			(unsigned char) (my_ip_address >> 16),
458			(unsigned char) (my_ip_address >> 8),
459			(unsigned char) my_ip_address);
460
461	sppp_get_ip_addrs (sp, &my_ip_address, 0, 0);
462	if (! my_ip_address)
463		return;         /* nothing to reply */
464
465	if (debug)
466		printf (SPP_FMT "send ARP reply, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n",
467			SPP_ARGS(ifp), my_hardware_address,
468			(unsigned char) (my_ip_address >> 24),
469			(unsigned char) (my_ip_address >> 16),
470			(unsigned char) (my_ip_address >> 8),
471			(unsigned char) my_ip_address,
472			his_hardware_address,
473			(unsigned char) (his_ip_address >> 24),
474			(unsigned char) (his_ip_address >> 16),
475			(unsigned char) (his_ip_address >> 8),
476			(unsigned char) his_ip_address);
477
478	/* Send the Inverse ARP reply. */
479	MGETHDR (m, M_NOWAIT, MT_DATA);
480	if (! m)
481		return;
482	m->m_pkthdr.len = m->m_len = 10 + sizeof (*reply);
483	m->m_pkthdr.rcvif = 0;
484
485	h = mtod (m, u_char*);
486	reply = (struct arp_req*) (h + 10);
487
488	h[0] = his_hardware_address >> 8;
489	h[1] = his_hardware_address;
490	h[2] = FR_UI;
491	h[3] = FR_PADDING;
492	h[4] = FR_SNAP;
493	h[5] = 0;
494	h[6] = 0;
495	h[7] = 0;
496	*(short*) (h+8) = htons (ETHERTYPE_ARP);
497
498	reply->htype    = htons (ARPHRD_FRELAY);
499	reply->ptype    = htons (ETHERTYPE_IP);
500	reply->halen    = 2;
501	reply->palen    = 4;
502	reply->op       = htons (ARPOP_INVREPLY);
503	reply->hsource  = htons (my_hardware_address);
504	reply->psource1 = htonl (my_ip_address);
505	reply->psource2 = htonl (my_ip_address) >> 16;
506	reply->htarget  = htons (his_hardware_address);
507	reply->ptarget1 = htonl (his_ip_address);
508	reply->ptarget2 = htonl (his_ip_address) >> 16;
509
510	if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
511		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
512}
513
514/*
515 * Process the input signaling packet (DLCI 0).
516 * The implemented protocol is ANSI T1.617 Annex D.
517 */
518static void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len)
519{
520	STDDCL;
521	u_char *p;
522	int dlci;
523
524	if (h[2] != FR_UI || h[3] != FR_SIGNALING || h[4] != 0) {
525		if (debug)
526			printf (SPP_FMT "Invalid signaling header\n",
527				SPP_ARGS(ifp));
528bad:            if (debug) {
529			printf ("%02x", *h++);
530			while (--len > 0)
531				printf ("-%02x", *h++);
532			printf ("\n");
533		}
534		return;
535	}
536	if (h[5] == FR_MSG_ENQUIRY) {
537		if (len == FR_ENQUIRY_SIZE &&
538		    h[12] == (u_char) sp->pp_seq[IDX_LCP]) {
539			sp->pp_seq[IDX_LCP] = random();
540			printf (SPP_FMT "loopback detected\n",
541				SPP_ARGS(ifp));
542		}
543		return;
544	}
545	if (h[5] != FR_MSG_STATUS) {
546		if (debug)
547			printf (SPP_FMT "Unknown signaling message: 0x%02x\n",
548				SPP_ARGS(ifp), h[5]);
549		goto bad;
550	}
551
552	/* Parse message fields. */
553	for (p=h+6; p<h+len; ) {
554		switch (*p) {
555		default:
556			if (debug)
557				printf (SPP_FMT "Unknown signaling field 0x%x\n",
558					SPP_ARGS(ifp), *p);
559			break;
560		case FR_FLD_LSHIFT5:
561		case FR_FLD_RTYPE:
562			/* Ignore. */
563			break;
564		case FR_FLD_VERIFY:
565			if (p[1] != 2) {
566				if (debug)
567					printf (SPP_FMT "Invalid signaling verify field length %d\n",
568						SPP_ARGS(ifp), p[1]);
569				break;
570			}
571			sp->pp_rseq[IDX_LCP] = p[2];
572			if (debug) {
573				printf (SPP_FMT "got lmi reply rseq=%d, seq=%d",
574					SPP_ARGS(ifp), p[2], p[3]);
575				if (p[3] != (u_char) sp->pp_seq[IDX_LCP])
576					printf (" (really %d)",
577						(u_char) sp->pp_seq[IDX_LCP]);
578				printf ("\n");
579			}
580			break;
581		case FR_FLD_PVC:
582			if (p[1] < 3) {
583				if (debug)
584					printf (SPP_FMT "Invalid PVC status length %d\n",
585						SPP_ARGS(ifp), p[1]);
586				break;
587			}
588			dlci = (p[2] << 4 & 0x3f0) | (p[3] >> 3 & 0x0f);
589			if (! sp->fr_dlci)
590				sp->fr_dlci = dlci;
591			if (sp->fr_status != p[4])
592				printf (SPP_FMT "DLCI %d %s%s\n",
593					SPP_ARGS(ifp), dlci,
594					p[4] & FR_DLCI_DELETE ? "deleted" :
595					p[4] & FR_DLCI_ACTIVE ? "active" : "passive",
596					p[4] & FR_DLCI_NEW ? ", new" : "");
597			sp->fr_status = p[4];
598			break;
599		}
600		if (*p & 0x80)
601			++p;
602		else if (p < h+len+1 && p[1])
603			p += 2 + p[1];
604		else {
605			if (debug)
606				printf (SPP_FMT "Invalid signaling field 0x%x\n",
607					SPP_ARGS(ifp), *p);
608			goto bad;
609		}
610	}
611}
612