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