if_spppfr.c revision 139823
1139823Simp/*- 2139365Srik * Synchronous Frame Relay link level subroutines. 3139365Srik * ANSI T1.617-compaible link management signaling 4139365Srik * implemented for Frame Relay mode. 5139365Srik * Cisco-type Frame Relay framing added, thanks Alex Tutubalin. 6139365Srik * Only one DLCI per channel for now. 7139365Srik * 8139365Srik * Copyright (C) 1994-2000 Cronyx Engineering. 9139365Srik * Author: Serge Vakulenko, <vak@cronyx.ru> 10139365Srik * 11139365Srik * Copyright (C) 1999-2004 Cronyx Engineering. 12139365Srik * Author: Kurakin Roman, <rik@cronyx.ru> 13139365Srik * 14139365Srik * This software is distributed with NO WARRANTIES, not even the implied 15139365Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16139365Srik * 17139365Srik * Authors grant any other persons or organisations a permission to use, 18139365Srik * modify and redistribute this software in source and binary forms, 19139365Srik * as long as this message is kept with the software, all derivative 20139365Srik * works or modified versions. 21139365Srik * 22139365Srik * $Cronyx Id: if_spppfr.c,v 1.1.2.10 2004/06/29 09:02:30 rik Exp $ 23139365Srik * $FreeBSD: head/sys/net/if_spppfr.c 139823 2005-01-07 01:45:51Z imp $ 24139365Srik */ 25139365Srik 26139365Srik#include <sys/param.h> 27139365Srik 28139365Srik#if defined(__FreeBSD__) && __FreeBSD__ >= 3 29139365Srik#include "opt_inet.h" 30139365Srik#include "opt_inet6.h" 31139365Srik#include "opt_ipx.h" 32139365Srik#endif 33139365Srik 34139365Srik#ifdef NetBSD1_3 35139365Srik# if NetBSD1_3 > 6 36139365Srik# include "opt_inet.h" 37139365Srik# include "opt_inet6.h" 38139365Srik# include "opt_iso.h" 39139365Srik# endif 40139365Srik#endif 41139365Srik 42139365Srik#include <sys/systm.h> 43139365Srik#include <sys/kernel.h> 44139365Srik#include <sys/module.h> 45139365Srik#include <sys/sockio.h> 46139365Srik#include <sys/socket.h> 47139365Srik#include <sys/syslog.h> 48139365Srik#if defined(__FreeBSD__) && __FreeBSD__ >= 3 49139365Srik#include <sys/random.h> 50139365Srik#endif 51139365Srik#include <sys/malloc.h> 52139365Srik#include <sys/mbuf.h> 53139365Srik 54139365Srik#if defined (__OpenBSD__) 55139365Srik#include <sys/md5k.h> 56139365Srik#else 57139365Srik#include <sys/md5.h> 58139365Srik#endif 59139365Srik 60139365Srik#include <net/if.h> 61139365Srik#include <net/netisr.h> 62139365Srik#include <net/if_types.h> 63139365Srik#include <net/route.h> 64139365Srik#include <netinet/in.h> 65139365Srik#include <netinet/in_systm.h> 66139365Srik#include <netinet/ip.h> 67139365Srik#include <net/slcompress.h> 68139365Srik 69139365Srik#if defined (__NetBSD__) || defined (__OpenBSD__) 70139365Srik#include <machine/cpu.h> /* XXX for softnet */ 71139365Srik#endif 72139365Srik 73139365Srik#include <machine/stdarg.h> 74139365Srik 75139365Srik#include <netinet/in_var.h> 76139365Srik#ifdef INET 77139365Srik#include <netinet/ip.h> 78139365Srik#include <netinet/tcp.h> 79139365Srik#endif 80139365Srik 81139365Srik#if defined (__FreeBSD__) || defined (__OpenBSD__) 82139365Srik# include <netinet/if_ether.h> 83139365Srik#else 84139365Srik# include <net/ethertypes.h> 85139365Srik#endif 86139365Srik 87139365Srik#ifdef IPX 88139365Srik#include <netipx/ipx.h> 89139365Srik#include <netipx/ipx_if.h> 90139365Srik#endif 91139365Srik 92139365Srik#include <net/if_sppp.h> 93139365Srik 94139365Srik/* 95139365Srik * Frame Relay. 96139365Srik */ 97139365Srik#define FR_UI 0x03 /* Unnumbered Information */ 98139365Srik#define FR_IP 0xCC /* IP protocol identifier */ 99139365Srik#define FR_PADDING 0x00 /* NLPID padding */ 100139365Srik#define FR_SIGNALING 0x08 /* Q.933/T1.617 signaling identifier */ 101139365Srik#define FR_SNAP 0x80 /* NLPID snap */ 102139365Srik 103139365Srik/* 104139365Srik * Header flags. 105139365Srik */ 106139365Srik#define FR_DE 0x02 /* discard eligibility */ 107139365Srik#define FR_FECN 0x04 /* forward notification */ 108139365Srik#define FR_BECN 0x08 /* backward notification */ 109139365Srik 110139365Srik/* 111139365Srik * Signaling message types. 112139365Srik */ 113139365Srik#define FR_MSG_ENQUIRY 0x75 /* status enquiry */ 114139365Srik#define FR_MSG_STATUS 0x7d /* status */ 115139365Srik 116139365Srik#define FR_ENQUIRY_SIZE 14 117139365Srik 118139365Srik/* 119139365Srik * Message field types. 120139365Srik */ 121139365Srik#define FR_FLD_RTYPE 0x01 /* report type */ 122139365Srik#define FR_FLD_VERIFY 0x03 /* link verification */ 123139365Srik#define FR_FLD_PVC 0x07 /* PVC status */ 124139365Srik#define FR_FLD_LSHIFT5 0x95 /* locking shift 5 */ 125139365Srik 126139365Srik/* 127139365Srik * Report types. 128139365Srik */ 129139365Srik#define FR_RTYPE_FULL 0 /* full status */ 130139365Srik#define FR_RTYPE_SHORT 1 /* link verification only */ 131139365Srik#define FR_RTYPE_SINGLE 2 /* single PVC status */ 132139365Srik 133139365Srik/* PVC status field. */ 134139365Srik#define FR_DLCI_DELETE 0x04 /* PVC is deleted */ 135139365Srik#define FR_DLCI_ACTIVE 0x02 /* PVC is operational */ 136139365Srik#define FR_DLCI_NEW 0x08 /* PVC is new */ 137139365Srik 138139365Srikstruct arp_req { 139139365Srik unsigned short htype; /* hardware type = ARPHRD_FRELAY */ 140139365Srik unsigned short ptype; /* protocol type = ETHERTYPE_IP */ 141139365Srik unsigned char halen; /* hardware address length = 2 */ 142139365Srik unsigned char palen; /* protocol address length = 4 */ 143139365Srik unsigned short op; /* ARP/RARP/InARP request/reply */ 144139365Srik unsigned short hsource; /* hardware source address */ 145139365Srik unsigned short psource1; /* protocol source */ 146139365Srik unsigned short psource2; 147139365Srik unsigned short htarget; /* hardware target address */ 148139365Srik unsigned short ptarget1; /* protocol target */ 149139365Srik unsigned short ptarget2; 150139365Srik} __packed; 151139365Srik 152139365Srik#if defined(__FreeBSD__) && __FreeBSD__ >= 3 && __FreeBSD_version < 501113 153139365Srik#define SPP_FMT "%s%d: " 154139365Srik#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 155139365Srik#else 156139365Srik#define SPP_FMT "%s: " 157139365Srik#define SPP_ARGS(ifp) (ifp)->if_xname 158139365Srik#endif 159139365Srik 160139365Srik/* almost every function needs these */ 161139365Srik#define STDDCL \ 162139365Srik struct ifnet *ifp = &sp->pp_if; \ 163139365Srik int debug = ifp->if_flags & IFF_DEBUG 164139365Srik 165139365Srikstatic void sppp_fr_arp (struct sppp *sp, struct arp_req *req, u_short addr); 166139365Srikstatic void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len); 167139365Srik 168139365Srikvoid sppp_fr_input (struct sppp *sp, struct mbuf *m) 169139365Srik{ 170139365Srik STDDCL; 171139365Srik u_char *h = mtod (m, u_char*); 172139365Srik int isr = -1; 173139365Srik int dlci, hlen, proto; 174139365Srik 175139365Srik /* Get the DLCI number. */ 176139365Srik if (m->m_pkthdr.len < 10) { 177139365Srikbad: m_freem (m); 178139365Srik return; 179139365Srik } 180139365Srik dlci = (h[0] << 2 & 0x3f0) | (h[1] >> 4 & 0x0f); 181139365Srik 182139365Srik /* Process signaling packets. */ 183139365Srik if (dlci == 0) { 184139365Srik sppp_fr_signal (sp, h, m->m_pkthdr.len); 185139365Srik m_freem (m); 186139365Srik return; 187139365Srik } 188139365Srik 189139365Srik if (dlci != sp->fr_dlci) { 190139365Srik if (debug) 191139365Srik printf (SPP_FMT "Received packet from invalid DLCI %d\n", 192139365Srik SPP_ARGS(ifp), dlci); 193139365Srik goto bad; 194139365Srik } 195139365Srik 196139365Srik /* Process the packet. */ 197139365Srik if (ntohs (*(short*) (h+2)) == ETHERTYPE_IP) { 198139365Srik /* Prehistoric IP framing? */ 199139365Srik h[2] = FR_UI; 200139365Srik h[3] = FR_IP; 201139365Srik } 202139365Srik if (h[2] != FR_UI) { 203139365Srik if (debug) 204139365Srik printf (SPP_FMT "Invalid frame relay header flag 0x%02x\n", 205139365Srik SPP_ARGS(ifp), h[2]); 206139365Srik goto bad; 207139365Srik } 208139365Srik switch (h[3]) { 209139365Srik default: 210139365Srik if (debug) 211139365Srik printf (SPP_FMT "Unsupported NLPID 0x%02x\n", 212139365Srik SPP_ARGS(ifp), h[3]); 213139365Srik goto bad; 214139365Srik 215139365Srik case FR_PADDING: 216139365Srik if (h[4] != FR_SNAP) { 217139365Srik if (debug) 218139365Srik printf (SPP_FMT "Bad NLPID 0x%02x\n", 219139365Srik SPP_ARGS(ifp), h[4]); 220139365Srik goto bad; 221139365Srik } 222139365Srik if (h[5] || h[6] || h[7]) { 223139365Srik if (debug) 224139365Srik printf (SPP_FMT "Bad OID 0x%02x-0x%02x-0x%02x\n", 225139365Srik SPP_ARGS(ifp), 226139365Srik h[5], h[6], h[7]); 227139365Srik goto bad; 228139365Srik } 229139365Srik proto = ntohs (*(short*) (h+8)); 230139365Srik if (proto == ETHERTYPE_ARP) { 231139365Srik /* Process the ARP request. */ 232139365Srik if (m->m_pkthdr.len != 10 + sizeof (struct arp_req)) { 233139365Srik if (debug) 234139365Srik printf (SPP_FMT "Bad ARP request size = %d bytes\n", 235139365Srik SPP_ARGS(ifp), 236139365Srik m->m_pkthdr.len); 237139365Srik goto bad; 238139365Srik } 239139365Srik sppp_fr_arp (sp, (struct arp_req*) (h + 10), 240139365Srik h[0] << 8 | h[1]); 241139365Srik m_freem (m); 242139365Srik return; 243139365Srik } 244139365Srik hlen = 10; 245139365Srik break; 246139365Srik 247139365Srik case FR_IP: 248139365Srik proto = ETHERTYPE_IP; 249139365Srik hlen = 4; 250139365Srik break; 251139365Srik } 252139365Srik 253139365Srik /* Remove frame relay header. */ 254139365Srik m_adj (m, hlen); 255139365Srik 256139365Srik switch (proto) { 257139365Srik default: 258139365Srik ++ifp->if_noproto; 259139365Srikdrop: ++ifp->if_ierrors; 260139365Srik ++ifp->if_iqdrops; 261139365Srik m_freem (m); 262139365Srik return; 263139365Srik#ifdef INET 264139365Srik case ETHERTYPE_IP: 265139365Srik isr = NETISR_IP; 266139365Srik break; 267139365Srik#endif 268139365Srik#ifdef IPX 269139365Srik case ETHERTYPE_IPX: 270139365Srik isr = NETISR_IPX; 271139365Srik break; 272139365Srik#endif 273139365Srik#ifdef NETATALK 274139365Srik case ETHERTYPE_AT: 275139365Srik isr = NETISR_ATALK; 276139365Srik break; 277139365Srik#endif 278139365Srik } 279139365Srik 280139365Srik if (! (ifp->if_flags & IFF_UP)) 281139365Srik goto drop; 282139365Srik 283139365Srik /* Check queue. */ 284139365Srik if (netisr_queue(isr, m)) { /* (0) on success. */ 285139365Srik if (debug) 286139365Srik log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 287139365Srik SPP_ARGS(ifp)); 288139365Srik } 289139365Srik} 290139365Srik 291139365Srik/* 292139365Srik * Add the frame relay header to the packet. 293139365Srik * For IP the header length is 4 bytes, 294139365Srik * for all other protocols - 10 bytes (RFC 1490). 295139365Srik */ 296139365Srikstruct mbuf *sppp_fr_header (struct sppp *sp, struct mbuf *m, 297139365Srik int family) 298139365Srik{ 299139365Srik STDDCL; 300139365Srik u_char *h; 301139365Srik int type, hlen; 302139365Srik 303139365Srik /* Prepend the space for Frame Relay header. */ 304139365Srik hlen = (family == AF_INET) ? 4 : 10; 305139365Srik M_PREPEND (m, hlen, M_DONTWAIT); 306139365Srik if (! m) 307139365Srik return 0; 308139365Srik h = mtod (m, u_char*); 309139365Srik 310139365Srik /* Fill the header. */ 311139365Srik h[0] = sp->fr_dlci >> 2 & 0xfc; 312139365Srik h[1] = sp->fr_dlci << 4 | 1; 313139365Srik h[2] = FR_UI; 314139365Srik 315139365Srik switch (family) { 316139365Srik default: 317139365Srik if (debug) 318139365Srik printf (SPP_FMT "Cannot handle address family %d\n", 319139365Srik SPP_ARGS(ifp), family); 320139365Srik m_freem (m); 321139365Srik return 0; 322139365Srik#ifdef INET 323139365Srik case AF_INET: 324139365Srik#if 0 /* Crashes on fragmented packets */ 325139365Srik /* 326139365Srik * Set the discard eligibility bit, if: 327139365Srik * 1) no fragmentation 328139365Srik * 2) length > 400 bytes 329139365Srik * 3a) the protocol is UDP or 330139365Srik * 3b) TCP data (no control bits) 331139365Srik */ 332139365Srik { 333139365Srik struct ip *ip = (struct ip*) (h + hlen); 334139365Srik struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 335139365Srik 336139365Srik if (! (ip->ip_off & ~IP_DF) && ip->ip_len > 400 && 337139365Srik (ip->ip_p == IPPROTO_UDP || 338139365Srik ip->ip_p == IPPROTO_TCP && ! tcp->th_flags)) 339139365Srik h[1] |= FR_DE; 340139365Srik } 341139365Srik#endif 342139365Srik h[3] = FR_IP; 343139365Srik return m; 344139365Srik#endif 345139365Srik#ifdef IPX 346139365Srik case AF_IPX: 347139365Srik type = ETHERTYPE_IPX; 348139365Srik break; 349139365Srik#endif 350139365Srik#ifdef NS 351139365Srik case AF_NS: 352139365Srik type = 0x8137; 353139365Srik break; 354139365Srik#endif 355139365Srik#ifdef NETATALK 356139365Srik case AF_APPLETALK: 357139365Srik type = ETHERTYPE_AT; 358139365Srik break; 359139365Srik#endif 360139365Srik } 361139365Srik h[3] = FR_PADDING; 362139365Srik h[4] = FR_SNAP; 363139365Srik h[5] = 0; 364139365Srik h[6] = 0; 365139365Srik h[7] = 0; 366139365Srik *(short*) (h+8) = htons(type); 367139365Srik return m; 368139365Srik} 369139365Srik 370139365Srik/* 371139365Srik * Send periodical frame relay link verification messages via DLCI 0. 372139365Srik * Called every 10 seconds (default value of T391 timer is 10 sec). 373139365Srik * Every 6-th message is a full status request 374139365Srik * (default value of N391 counter is 6). 375139365Srik */ 376139365Srikvoid sppp_fr_keepalive (struct sppp *sp) 377139365Srik{ 378139365Srik STDDCL; 379139365Srik unsigned char *h, *p; 380139365Srik struct mbuf *m; 381139365Srik 382139365Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 383139365Srik if (! m) 384139365Srik return; 385139365Srik m->m_pkthdr.rcvif = 0; 386139365Srik 387139365Srik h = mtod (m, u_char*); 388139365Srik p = h; 389139365Srik *p++ = 0; /* DLCI = 0 */ 390139365Srik *p++ = 1; 391139365Srik *p++ = FR_UI; 392139365Srik *p++ = FR_SIGNALING; /* NLPID = UNI call control */ 393139365Srik 394139365Srik *p++ = 0; /* call reference length = 0 */ 395139365Srik *p++ = FR_MSG_ENQUIRY; /* message type = status enquiry */ 396139365Srik 397139365Srik *p++ = FR_FLD_LSHIFT5; /* locking shift 5 */ 398139365Srik 399139365Srik *p++ = FR_FLD_RTYPE; /* report type field */ 400139365Srik *p++ = 1; /* report type length = 1 */ 401139365Srik if (sp->pp_seq[IDX_LCP] % 6) 402139365Srik *p++ = FR_RTYPE_SHORT; /* link verification only */ 403139365Srik else 404139365Srik *p++ = FR_RTYPE_FULL; /* full status needed */ 405139365Srik 406139365Srik if (sp->pp_seq[IDX_LCP] >= 255) 407139365Srik sp->pp_seq[IDX_LCP] = 0; 408139365Srik *p++ = FR_FLD_VERIFY; /* link verification type field */ 409139365Srik *p++ = 2; /* link verification field length = 2 */ 410139365Srik *p++ = ++sp->pp_seq[IDX_LCP]; /* our sequence number */ 411139365Srik *p++ = sp->pp_rseq[IDX_LCP]; /* last received sequence number */ 412139365Srik 413139365Srik m->m_pkthdr.len = m->m_len = p - h; 414139365Srik if (debug) 415139365Srik printf (SPP_FMT "send lmi packet, seq=%d, rseq=%d\n", 416139365Srik SPP_ARGS(ifp), (u_char) sp->pp_seq[IDX_LCP], 417139365Srik (u_char) sp->pp_rseq[IDX_LCP]); 418139365Srik 419139365Srik if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 420139365Srik ++ifp->if_oerrors; 421139365Srik} 422139365Srik 423139365Srik/* 424139365Srik * Process the frame relay Inverse ARP request. 425139365Srik */ 426139365Srikstatic void sppp_fr_arp (struct sppp *sp, struct arp_req *req, 427139365Srik u_short his_hardware_address) 428139365Srik{ 429139365Srik STDDCL; 430139365Srik struct mbuf *m; 431139365Srik struct arp_req *reply; 432139365Srik u_char *h; 433139365Srik u_short my_hardware_address; 434139365Srik u_long his_ip_address, my_ip_address; 435139365Srik 436139365Srik if ((ntohs (req->htype) != ARPHRD_FRELAY || 437139365Srik ntohs (req->htype) != 16) || /* for BayNetworks routers */ 438139365Srik ntohs (req->ptype) != ETHERTYPE_IP) { 439139365Srik if (debug) 440139365Srik printf (SPP_FMT "Invalid ARP hardware/protocol type = 0x%x/0x%x\n", 441139365Srik SPP_ARGS(ifp), 442139365Srik ntohs (req->htype), ntohs (req->ptype)); 443139365Srik return; 444139365Srik } 445139365Srik if (req->halen != 2 || req->palen != 4) { 446139365Srik if (debug) 447139365Srik printf (SPP_FMT "Invalid ARP hardware/protocol address length = %d/%d\n", 448139365Srik SPP_ARGS(ifp), 449139365Srik req->halen, req->palen); 450139365Srik return; 451139365Srik } 452139365Srik switch (ntohs (req->op)) { 453139365Srik default: 454139365Srik if (debug) 455139365Srik printf (SPP_FMT "Invalid ARP op = 0x%x\n", 456139365Srik SPP_ARGS(ifp), ntohs (req->op)); 457139365Srik return; 458139365Srik 459139365Srik case ARPOP_INVREPLY: 460139365Srik /* Ignore. */ 461139365Srik return; 462139365Srik 463139365Srik case ARPOP_INVREQUEST: 464139365Srik my_hardware_address = ntohs (req->htarget); 465139365Srik his_ip_address = ntohs (req->psource1) << 16 | 466139365Srik ntohs (req->psource2); 467139365Srik my_ip_address = ntohs (req->ptarget1) << 16 | 468139365Srik ntohs (req->ptarget2); 469139365Srik break; 470139365Srik } 471139365Srik if (debug) 472139365Srik printf (SPP_FMT "got ARP request, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n", 473139365Srik SPP_ARGS(ifp), ntohs (req->hsource), 474139365Srik (unsigned char) (his_ip_address >> 24), 475139365Srik (unsigned char) (his_ip_address >> 16), 476139365Srik (unsigned char) (his_ip_address >> 8), 477139365Srik (unsigned char) his_ip_address, 478139365Srik my_hardware_address, 479139365Srik (unsigned char) (my_ip_address >> 24), 480139365Srik (unsigned char) (my_ip_address >> 16), 481139365Srik (unsigned char) (my_ip_address >> 8), 482139365Srik (unsigned char) my_ip_address); 483139365Srik 484139365Srik sppp_get_ip_addrs (sp, &my_ip_address, 0, 0); 485139365Srik if (! my_ip_address) 486139365Srik return; /* nothing to reply */ 487139365Srik 488139365Srik if (debug) 489139365Srik printf (SPP_FMT "send ARP reply, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n", 490139365Srik SPP_ARGS(ifp), my_hardware_address, 491139365Srik (unsigned char) (my_ip_address >> 24), 492139365Srik (unsigned char) (my_ip_address >> 16), 493139365Srik (unsigned char) (my_ip_address >> 8), 494139365Srik (unsigned char) my_ip_address, 495139365Srik his_hardware_address, 496139365Srik (unsigned char) (his_ip_address >> 24), 497139365Srik (unsigned char) (his_ip_address >> 16), 498139365Srik (unsigned char) (his_ip_address >> 8), 499139365Srik (unsigned char) his_ip_address); 500139365Srik 501139365Srik /* Send the Inverse ARP reply. */ 502139365Srik MGETHDR (m, M_DONTWAIT, MT_DATA); 503139365Srik if (! m) 504139365Srik return; 505139365Srik m->m_pkthdr.len = m->m_len = 10 + sizeof (*reply); 506139365Srik m->m_pkthdr.rcvif = 0; 507139365Srik 508139365Srik h = mtod (m, u_char*); 509139365Srik reply = (struct arp_req*) (h + 10); 510139365Srik 511139365Srik h[0] = his_hardware_address >> 8; 512139365Srik h[1] = his_hardware_address; 513139365Srik h[2] = FR_UI; 514139365Srik h[3] = FR_PADDING; 515139365Srik h[4] = FR_SNAP; 516139365Srik h[5] = 0; 517139365Srik h[6] = 0; 518139365Srik h[7] = 0; 519139365Srik *(short*) (h+8) = htons (ETHERTYPE_ARP); 520139365Srik 521139365Srik reply->htype = htons (ARPHRD_FRELAY); 522139365Srik reply->ptype = htons (ETHERTYPE_IP); 523139365Srik reply->halen = 2; 524139365Srik reply->palen = 4; 525139365Srik reply->op = htons (ARPOP_INVREPLY); 526139365Srik reply->hsource = htons (my_hardware_address); 527139365Srik reply->psource1 = htonl (my_ip_address); 528139365Srik reply->psource2 = htonl (my_ip_address) >> 16; 529139365Srik reply->htarget = htons (his_hardware_address); 530139365Srik reply->ptarget1 = htonl (his_ip_address); 531139365Srik reply->ptarget2 = htonl (his_ip_address) >> 16; 532139365Srik 533139365Srik if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 534139365Srik ++ifp->if_oerrors; 535139365Srik} 536139365Srik 537139365Srik/* 538139365Srik * Process the input signaling packet (DLCI 0). 539139365Srik * The implemented protocol is ANSI T1.617 Annex D. 540139365Srik */ 541139365Srikstatic void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len) 542139365Srik{ 543139365Srik STDDCL; 544139365Srik u_char *p; 545139365Srik int dlci; 546139365Srik 547139365Srik if (h[2] != FR_UI || h[3] != FR_SIGNALING || h[4] != 0) { 548139365Srik if (debug) 549139365Srik printf (SPP_FMT "Invalid signaling header\n", 550139365Srik SPP_ARGS(ifp)); 551139365Srikbad: if (debug) { 552139365Srik printf ("%02x", *h++); 553139365Srik while (--len > 0) 554139365Srik printf ("-%02x", *h++); 555139365Srik printf ("\n"); 556139365Srik } 557139365Srik return; 558139365Srik } 559139365Srik if (h[5] == FR_MSG_ENQUIRY) { 560139365Srik if (len == FR_ENQUIRY_SIZE && 561139365Srik h[12] == (u_char) sp->pp_seq[IDX_LCP]) { 562139365Srik sp->pp_seq[IDX_LCP] = random(); 563139365Srik printf (SPP_FMT "loopback detected\n", 564139365Srik SPP_ARGS(ifp)); 565139365Srik } 566139365Srik return; 567139365Srik } 568139365Srik if (h[5] != FR_MSG_STATUS) { 569139365Srik if (debug) 570139365Srik printf (SPP_FMT "Unknown signaling message: 0x%02x\n", 571139365Srik SPP_ARGS(ifp), h[5]); 572139365Srik goto bad; 573139365Srik } 574139365Srik 575139365Srik /* Parse message fields. */ 576139365Srik for (p=h+6; p<h+len; ) { 577139365Srik switch (*p) { 578139365Srik default: 579139365Srik if (debug) 580139365Srik printf (SPP_FMT "Unknown signaling field 0x%x\n", 581139365Srik SPP_ARGS(ifp), *p); 582139365Srik break; 583139365Srik case FR_FLD_LSHIFT5: 584139365Srik case FR_FLD_RTYPE: 585139365Srik /* Ignore. */ 586139365Srik break; 587139365Srik case FR_FLD_VERIFY: 588139365Srik if (p[1] != 2) { 589139365Srik if (debug) 590139365Srik printf (SPP_FMT "Invalid signaling verify field length %d\n", 591139365Srik SPP_ARGS(ifp), p[1]); 592139365Srik break; 593139365Srik } 594139365Srik sp->pp_rseq[IDX_LCP] = p[2]; 595139365Srik if (debug) { 596139365Srik printf (SPP_FMT "got lmi reply rseq=%d, seq=%d", 597139365Srik SPP_ARGS(ifp), p[2], p[3]); 598139365Srik if (p[3] != (u_char) sp->pp_seq[IDX_LCP]) 599139365Srik printf (" (really %d)", 600139365Srik (u_char) sp->pp_seq[IDX_LCP]); 601139365Srik printf ("\n"); 602139365Srik } 603139365Srik break; 604139365Srik case FR_FLD_PVC: 605139365Srik if (p[1] < 3) { 606139365Srik if (debug) 607139365Srik printf (SPP_FMT "Invalid PVC status length %d\n", 608139365Srik SPP_ARGS(ifp), p[1]); 609139365Srik break; 610139365Srik } 611139365Srik dlci = (p[2] << 4 & 0x3f0) | (p[3] >> 3 & 0x0f); 612139365Srik if (! sp->fr_dlci) 613139365Srik sp->fr_dlci = dlci; 614139365Srik if (sp->fr_status != p[4]) 615139365Srik printf (SPP_FMT "DLCI %d %s%s\n", 616139365Srik SPP_ARGS(ifp), dlci, 617139365Srik p[4] & FR_DLCI_DELETE ? "deleted" : 618139365Srik p[4] & FR_DLCI_ACTIVE ? "active" : "passive", 619139365Srik p[4] & FR_DLCI_NEW ? ", new" : ""); 620139365Srik sp->fr_status = p[4]; 621139365Srik break; 622139365Srik } 623139365Srik if (*p & 0x80) 624139365Srik ++p; 625139365Srik else if (p < h+len+1 && p[1]) 626139365Srik p += 2 + p[1]; 627139365Srik else { 628139365Srik if (debug) 629139365Srik printf (SPP_FMT "Invalid signaling field 0x%x\n", 630139365Srik SPP_ARGS(ifp), *p); 631139365Srik goto bad; 632139365Srik } 633139365Srik } 634139365Srik} 635