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