The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

Cache object: f1e7b79e8434fa03f25c0351d5d0bac5


[ 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.