[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_spppfr.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

    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: src/sys/net/if_spppfr.c,v 1.2.2.1 2005/01/25 15:24:45 rik Exp $
   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 
  138 struct 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;                         \
  163         int debug = ifp->if_flags & IFF_DEBUG
  164 
  165 static void sppp_fr_arp (struct sppp *sp, struct arp_req *req, u_short addr);
  166 static void sppp_fr_signal (struct sppp *sp, unsigned char *h, int len);
  167 
  168 void 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) {
  177 bad:            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;
  259 drop:           ++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  */
  296 struct 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  */
  376 void 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  */
  426 static 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  */
  541 static 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));
  551 bad:            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 }

Cache object: fe42e8150cf660537c187a821ef0186e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.