Date: Fri, 12 Nov 1999 22:01:58 +0300 (MSK) From: vak@cronyx.ru To: FreeBSD-gnats-submit@freebsd.org Subject: kern/14848: Frame Relay support, corrected Message-ID: <199911121901.WAA00658@crox.cronyx.ru>
index | next in thread | raw e-mail
>Number: 14848
>Category: kern
>Synopsis: Frame Relay support, corrected
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Fri Nov 12 11:00:01 PST 1999
>Closed-Date:
>Last-Modified:
>Originator: Serge V.Vakulenko
>Release: FreeBSD 3.3-RELEASE i386
>Organization:
Cronyx
>Environment:
FreeBSD router with syncronous serial adapters installed.
>Description:
Added support for Frame Relay protocol,
corrected according to style(9).
>How-To-Repeat:
>Fix:
--- if_sppp33.h Fri Nov 12 21:16:21 1999
+++ if_sppp.h Fri Nov 12 21:16:50 1999
@@ -99,6 +99,8 @@
struct sipcp ipcp; /* IPCP params */
struct sauth myauth; /* auth params, i'm peer */
struct sauth hisauth; /* auth params, i'm authenticator */
+ u_short fr_dlci; /* Frame Relay DLCI number, 16..1023 */
+ u_char fr_status; /* PVC status, active/new/delete */
/*
* These functions are filled in by sppp_attach(), and are
* expected to be used by the lower layer (hardware) drivers
@@ -133,7 +135,7 @@
#define PP_KEEPALIVE 0x01 /* use keepalive protocol */
#define PP_CISCO 0x02 /* use Cisco protocol instead of PPP */
- /* 0x04 was PP_TIMO */
+#define PP_FR 0x04 /* use Frame Relay protocol instead of PPP */
#define PP_CALLIN 0x08 /* we are being called */
#define PP_NEEDAUTH 0x10 /* remote requested authentication */
--- if_sppps33.c Fri Nov 12 21:16:02 1999
+++ if_spppsubr.c Fri Nov 12 21:55:14 1999
@@ -1,8 +1,12 @@
/*
- * Synchronous PPP/Cisco link level subroutines.
+ * Synchronous PPP/Cisco/Frame Relay link level subroutines.
* Keepalive protocol implemented in both Cisco and PPP modes.
+ * ANSI T1.617-compaible link management signaling
+ * implemented for Frame Relay mode.
+ * Cisco-type Frame Relay framing added, thanks Alex Tutubalin.
+ * Only one DLCI per channel for now.
*
- * Copyright (C) 1994-1996 Cronyx Engineering Ltd.
+ * Copyright (C) 1994-1999 Cronyx Engineering Ltd.
* Author: Serge Vakulenko, <vak@cronyx.ru>
*
* Heavily revamped to conform to RFC 1661.
@@ -226,6 +230,65 @@
#define CISCO_PACKET_LEN 18
/*
+ * Frame Relay.
+ */
+#define FR_IP 0xCC /* IP protocol identifier */
+#define FR_PADDING 0x00 /* NLPID padding */
+#define FR_SIGNALING 0x08 /* Q.933/T1.617 signaling identifier */
+#define FR_SNAP 0x80 /* NLPID snap */
+
+/*
+ * Header flags.
+ */
+#define FR_DE 0x02 /* discard eligibility */
+#define FR_FECN 0x04 /* forward notification */
+#define FR_BECN 0x08 /* backward notification */
+
+/*
+ * Signaling message types.
+ */
+#define FR_MSG_ENQUIRY 0x75 /* status enquiry */
+#define FR_MSG_STATUS 0x7d /* status */
+
+#define FR_ENQUIRY_SIZE 14
+
+/*
+ * Message field types.
+ */
+#define FR_FLD_RTYPE 0x01 /* report type */
+#define FR_FLD_VERIFY 0x03 /* link verification */
+#define FR_FLD_PVC 0x07 /* PVC status */
+#define FR_FLD_LSHIFT5 0x95 /* locking shift 5 */
+
+/*
+ * Report types.
+ */
+#define FR_RTYPE_FULL 0 /* full status */
+#define FR_RTYPE_SHORT 1 /* link verification only */
+#define FR_RTYPE_SINGLE 2 /* single PVC status */
+
+/*
+ * PVC status field.
+ */
+#define FR_DLCI_DELETE 0x04 /* PVC is deleted */
+#define FR_DLCI_ACTIVE 0x02 /* PVC is operational */
+#define FR_DLCI_NEW 0x08 /* PVC is new */
+
+struct arp_req {
+ unsigned short htype; /* hardware type = ARPHRD_FRELAY */
+ unsigned short ptype; /* protocol type = ETHERTYPE_IP */
+ unsigned char halen; /* hardware address length = 2 */
+ unsigned char palen; /* protocol address length = 4 */
+ unsigned short op; /* ARP/RARP/InARP request/reply */
+ unsigned short hsource; /* hardware source address */
+ unsigned short psource1; /* protocol source */
+ unsigned short psource2;
+ unsigned short htarget; /* hardware target address */
+ unsigned short ptarget1; /* protocol target */
+ unsigned short ptarget2;
+};
+
+/*
* We follow the spelling and capitalization of RFC 1661 here, to make
* it easier comparing with the standard. Please refer to this RFC in
* case you can't make sense out of these abbreviation; it will also
@@ -295,6 +358,12 @@
static void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2);
static void sppp_cisco_input(struct sppp *sp, struct mbuf *m);
+static void sppp_fr_input(struct sppp *sp, struct mbuf *m);
+static struct mbuf *sppp_fr_header(struct sppp *sp, struct mbuf *m, int fam);
+static void sppp_fr_keepalive(struct sppp *sp);
+static void sppp_fr_arp(struct sppp *sp, struct arp_req *req, u_short addr);
+static void sppp_fr_signal(struct sppp *sp, unsigned char *h, int len);
+
static void sppp_cp_input(const struct cp *cp, struct sppp *sp,
struct mbuf *m);
static void sppp_cp_send(struct sppp *sp, u_short proto, u_char type,
@@ -458,6 +527,11 @@
return;
}
+ if (sp->pp_flags & PP_FR) {
+ sppp_fr_input(sp, m);
+ return;
+ }
+
/* Get PPP header. */
h = mtod (m, struct ppp_header*);
m_adj (m, PPP_HEADER_LEN);
@@ -694,12 +768,20 @@
}
#endif
+ if (sp->pp_flags & PP_FR) {
+ /* Add frame relay header. */
+ m = sppp_fr_header(sp, m, dst->sa_family);
+ if (m == NULL)
+ goto nobufs;
+ goto out;
+ }
+
/*
* Prepend general data packet PPP header. For now, IP only.
*/
M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT);
if (! m) {
- if (debug)
+nobufs: if (debug)
log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n",
SPP_ARGS(ifp));
++ifp->if_oerrors;
@@ -771,7 +853,7 @@
* Queue message on interface, and start output if interface
* not yet active.
*/
- if (IF_QFULL (ifq)) {
+out: if (IF_QFULL(ifq)) {
IF_DROP (&ifp->if_snd);
m_freem (m);
++ifp->if_oerrors;
@@ -898,7 +980,8 @@
*/
IF_DEQUEUE(&sp->pp_cpq, m);
if (m == NULL &&
- (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) {
+ (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0 ||
+ (sp->pp_flags & PP_FR) != 0)) {
IF_DEQUEUE(&sp->pp_fastq, m);
if (m == NULL)
IF_DEQUEUE (&sp->pp_if.if_snd, m);
@@ -922,7 +1005,8 @@
m = sp->pp_cpq.ifq_head;
if (m == NULL &&
(sp->pp_phase == PHASE_NETWORK ||
- (sp->pp_flags & PP_CISCO) != 0))
+ (sp->pp_flags & PP_CISCO) != 0 ||
+ (sp->pp_flags & PP_FR) != 0))
if ((m = sp->pp_fastq.ifq_head) == NULL)
m = sp->pp_if.if_snd.ifq_head;
splx (s);
@@ -963,11 +1047,14 @@
}
if (going_up || going_down)
- lcp.Close(sp);
+ if (! (sp->pp_flags & PP_CISCO) &&
+ ! (sp->pp_flags & PP_FR))
+ lcp.Close(sp);
if (going_up && newmode == 0) {
/* neither auto-dial nor passive */
ifp->if_flags |= IFF_RUNNING;
- if (!(sp->pp_flags & PP_CISCO))
+ if (! (sp->pp_flags & PP_CISCO) &&
+ ! (sp->pp_flags & PP_FR))
lcp.Open(sp);
} else if (going_down) {
sppp_flush(ifp);
@@ -3812,6 +3899,11 @@
! (ifp->if_flags & IFF_RUNNING))
continue;
+ if (sp->pp_flags & PP_FR) {
+ sppp_fr_keepalive(sp);
+ continue;
+ }
+
/* No keepalive in PPP mode if LCP not opened yet. */
if (! (sp->pp_flags & PP_CISCO) &&
sp->pp_phase < PHASE_AUTHENTICATE)
@@ -4271,4 +4363,490 @@
sppp_null(struct sppp *unused)
{
/* do just nothing */
+}
+
+/*
+ * Frame Relay link level subroutines.
+ * ANSI T1.617-compatible link management signaling implemented.
+ * Only one DLCI per channel for now.
+ * Copyright (C) 1994-1999 Cronyx Engineering Ltd.
+ * Author: Serge Vakulenko, <vak@cronyx.ru>
+ */
+static void
+sppp_fr_input(struct sppp *sp, struct mbuf *m)
+{
+ STDDCL;
+ u_char *h;
+ struct ifqueue *inq;
+ int dlci, hlen, proto, s;
+
+ /* Get the DLCI number. */
+ if (m->m_pkthdr.len < 10) {
+bad: m_freem(m);
+ return;
+ }
+ h = mtod(m, u_char*);
+ dlci = (h[0] << 2 & 0x3f0) | (h[1] >> 4 & 0x0f);
+
+ /* Process signaling packets. */
+ if (dlci == 0) {
+ sppp_fr_signal(sp, h, m->m_pkthdr.len);
+ m_freem(m);
+ return;
+ }
+
+ if (dlci != sp->fr_dlci) {
+ if (debug)
+ printf("%s%d: Received packet from invalid DLCI %d\n",
+ ifp->if_name, ifp->if_unit, dlci);
+ goto bad;
+ }
+
+ /* Process the packet. */
+ if (ntohs(*(short*) (h+2)) == ETHERTYPE_IP)
+ goto proto_ip; /* cisco framing */
+ if (h[2] != PPP_UI) {
+ if (debug)
+ printf("%s%d: Invalid frame relay header flag 0x%02x\n",
+ ifp->if_name, ifp->if_unit, h[2]);
+ goto bad;
+ }
+ switch (h[3]) {
+ case FR_PADDING:
+ if (h[4] != FR_SNAP) {
+ if (debug)
+ printf("%s%d: Bad NLPID 0x%02x\n",
+ ifp->if_name, ifp->if_unit, h[4]);
+ goto bad;
+ }
+ if (h[5] || h[6] || h[7]) {
+ if (debug)
+ printf("%s%d: Bad OID 0x%02x-0x%02x-0x%02x\n",
+ ifp->if_name, ifp->if_unit,
+ h[5], h[6], h[7]);
+ goto bad;
+ }
+ proto = ntohs(*(short*) (h+8));
+ if (proto == ETHERTYPE_ARP) {
+ /* Process the ARP request. */
+ if (m->m_pkthdr.len != 10 + sizeof (struct arp_req)) {
+ if (debug)
+ printf("%s%d: Bad ARP request size = %d bytes\n",
+ ifp->if_name, ifp->if_unit,
+ m->m_pkthdr.len);
+ goto bad;
+ }
+ sppp_fr_arp(sp, (struct arp_req*) (h + 10),
+ h[0] << 8 | h[1]);
+ m_freem(m);
+ return;
+ }
+ hlen = 10;
+ break;
+
+ case FR_IP:
+proto_ip: proto = ETHERTYPE_IP;
+ hlen = 4;
+ break;
+
+ default:
+ if (debug)
+ printf("%s%d: Unsupported NLPID 0x%02x\n",
+ ifp->if_name, ifp->if_unit, h[3]);
+ goto bad;
+ }
+
+ /* Remove frame relay header. */
+ m_adj(m, hlen);
+
+ switch (proto) {
+#ifdef INET
+ case ETHERTYPE_IP:
+ schednetisr(NETISR_IP);
+ inq = &ipintrq;
+ break;
+#endif
+#ifdef IPX
+ case ETHERTYPE_IPX:
+ schednetisr(NETISR_IPX);
+ inq = &ipxintrq;
+ break;
+#endif
+#ifdef NS
+ case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
+ schednetisr(NETISR_NS);
+ inq = &nsintrq;
+ break;
+#endif
+#ifdef NETATALK
+ case ETHERTYPE_AT:
+ schednetisr(NETISR_ATALK);
+ inq = &atintrq1;
+ break;
+#endif
+ default:
+ ++ifp->if_noproto;
+drop: ++ifp->if_ierrors;
+ ++ifp->if_iqdrops;
+ m_freem(m);
+ return;
+ }
+
+ if (! (ifp->if_flags & IFF_UP))
+ goto drop;
+
+ /* Check queue. */
+ s = splimp();
+ if (IF_QFULL(inq)) {
+ /* Queue overflow. */
+ IF_DROP(inq);
+ splx(s);
+ if (debug)
+ log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n",
+ SPP_ARGS(ifp));
+ goto drop;
+ }
+ IF_ENQUEUE(inq, m);
+ splx(s);
+}
+
+/*
+ * Add the frame relay header to the packet.
+ * For IP the header length is 4 bytes,
+ * for all other protocols - 10 bytes (RFC 1490).
+ */
+static struct mbuf *
+sppp_fr_header(struct sppp *sp, struct mbuf *m, int family)
+{
+ STDDCL;
+ u_char *h;
+ int type, hlen;
+
+ /* Prepend the space for Frame Relay header. */
+ hlen = (family == AF_INET) ? 4 : 10;
+ M_PREPEND(m, hlen, M_DONTWAIT);
+ if (m == NULL)
+ return 0;
+ h = mtod(m, u_char*);
+
+ /* Fill the header. */
+ h[0] = sp->fr_dlci >> 2 & 0xfc;
+ h[1] = sp->fr_dlci << 4 | 1;
+ h[2] = PPP_UI;
+
+ switch (family) {
+#ifdef INET
+ case AF_INET:
+ h[3] = FR_IP;
+ return m;
+#endif
+#ifdef IPX
+ case AF_IPX:
+ type = ETHERTYPE_IPX;
+ break;
+#endif
+#ifdef NS
+ case AF_NS:
+ type = 0x8137;
+ break;
+#endif
+#ifdef NETATALK
+ case AF_APPLETALK:
+ type = ETHERTYPE_AT;
+ break;
+#endif
+ default:
+ if (debug)
+ printf("%s%d: cannot handle address family %d\n",
+ ifp->if_name, ifp->if_unit, family);
+ m_freem(m);
+ return 0;
+ }
+ h[3] = FR_PADDING;
+ h[4] = FR_SNAP;
+ h[5] = 0;
+ h[6] = 0;
+ h[7] = 0;
+ *(short*) (h+8) = htons(type);
+ return m;
+}
+
+/*
+ * Send periodical frame relay link verification messages via DLCI 0.
+ * Called every 10 seconds (default value of T391 timer is 10 sec).
+ * Every 6-th message is a full status request
+ * (default value of N391 counter is 6).
+ */
+static void
+sppp_fr_keepalive(struct sppp *sp)
+{
+ STDDCL;
+ unsigned char *h, *p;
+ struct mbuf *m;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return;
+ m->m_pkthdr.rcvif = 0;
+
+ h = mtod(m, u_char*);
+ p = h;
+ *p++ = 0; /* DLCI = 0 */
+ *p++ = 1;
+ *p++ = PPP_UI;
+ *p++ = FR_SIGNALING; /* NLPID = UNI call control */
+
+ *p++ = 0; /* call reference length = 0 */
+ *p++ = FR_MSG_ENQUIRY; /* message type = status enquiry */
+
+ *p++ = FR_FLD_LSHIFT5; /* locking shift 5 */
+
+ *p++ = FR_FLD_RTYPE; /* report type field */
+ *p++ = 1; /* report type length = 1 */
+ if (sp->pp_seq % 6)
+ *p++ = FR_RTYPE_SHORT; /* link verification only */
+ else
+ *p++ = FR_RTYPE_FULL; /* full status needed */
+
+ if (sp->pp_seq >= 255)
+ sp->pp_seq = 0;
+ *p++ = FR_FLD_VERIFY; /* link verification type field */
+ *p++ = 2; /* link verification field length = 2 */
+ *p++ = ++sp->pp_seq; /* our sequence number */
+ *p++ = sp->pp_rseq; /* last received sequence number */
+
+ m->m_pkthdr.len = m->m_len = p - h;
+ if (debug)
+ printf("%s%d: send lmi packet, seq=%d, rseq=%d\n",
+ ifp->if_name, ifp->if_unit, (u_char) sp->pp_seq,
+ (u_char) sp->pp_rseq);
+
+ if (IF_QFULL(&sp->pp_fastq)) {
+ IF_DROP(&ifp->if_snd);
+ m_freem(m);
+ } else
+ IF_ENQUEUE(&sp->pp_fastq, m);
+ if (! (ifp->if_flags & IFF_OACTIVE))
+ (*ifp->if_start)(ifp);
+ ifp->if_obytes += m->m_pkthdr.len + 3;
+}
+
+/*
+ * Process the frame relay Inverse ARP request.
+ */
+static void
+sppp_fr_arp(struct sppp *sp, struct arp_req *req, u_short his_hardware_address)
+{
+ STDDCL;
+ struct mbuf *m;
+ struct arp_req *reply;
+ u_char *h;
+ u_short my_hardware_address;
+ u_long his_ip_address, my_ip_address;
+
+ if ((ntohs(req->htype) != ARPHRD_FRELAY ||
+ ntohs(req->htype) != 16) || /* for BayNetworks routers */
+ ntohs(req->ptype) != ETHERTYPE_IP) {
+ if (debug)
+ printf("%s%d: Invalid ARP hardware/protocol type = 0x%x/0x%x\n",
+ ifp->if_name, ifp->if_unit,
+ ntohs(req->htype), ntohs(req->ptype));
+ return;
+ }
+ if (req->halen != 2 || req->palen != 4) {
+ if (debug)
+ printf("%s%d: Invalid ARP hardware/protocol address length = %d/%d\n",
+ ifp->if_name, ifp->if_unit,
+ req->halen, req->palen);
+ return;
+ }
+ switch (ntohs(req->op)) {
+ case ARPOP_INVREPLY:
+ /* Ignore. */
+ return;
+
+ case ARPOP_INVREQUEST:
+ my_hardware_address = ntohs(req->htarget);
+ his_ip_address = ntohs(req->psource1) << 16 |
+ ntohs(req->psource2);
+ my_ip_address = ntohs(req->ptarget1) << 16 |
+ ntohs(req->ptarget2);
+ break;
+
+ default:
+ if (debug)
+ printf("%s%d: Invalid ARP op = 0x%x\n",
+ ifp->if_name, ifp->if_unit, ntohs(req->op));
+ return;
+ }
+ if (debug)
+ printf("%s%d: got ARP request, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n",
+ ifp->if_name, ifp->if_unit, ntohs(req->hsource),
+ (unsigned char) (his_ip_address >> 24),
+ (unsigned char) (his_ip_address >> 16),
+ (unsigned char) (his_ip_address >> 8),
+ (unsigned char) his_ip_address,
+ my_hardware_address,
+ (unsigned char) (my_ip_address >> 24),
+ (unsigned char) (my_ip_address >> 16),
+ (unsigned char) (my_ip_address >> 8),
+ (unsigned char) my_ip_address);
+
+ sppp_get_ip_addrs(sp, &my_ip_address, 0, 0);
+ if (my_ip_address == 0)
+ return; /* nothing to reply */
+
+ if (debug)
+ printf("%s%d: send ARP reply, source=0x%04x/%d.%d.%d.%d, target=0x%04x/%d.%d.%d.%d\n",
+ ifp->if_name, ifp->if_unit, my_hardware_address,
+ (unsigned char) (my_ip_address >> 24),
+ (unsigned char) (my_ip_address >> 16),
+ (unsigned char) (my_ip_address >> 8),
+ (unsigned char) my_ip_address,
+ his_hardware_address,
+ (unsigned char) (his_ip_address >> 24),
+ (unsigned char) (his_ip_address >> 16),
+ (unsigned char) (his_ip_address >> 8),
+ (unsigned char) his_ip_address);
+
+ /* Send the Inverse ARP reply. */
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return;
+ m->m_pkthdr.len = m->m_len = 10 + sizeof(*reply);
+ m->m_pkthdr.rcvif = 0;
+
+ h = mtod(m, u_char*);
+ reply = (struct arp_req*) (h + 10);
+
+ h[0] = his_hardware_address >> 8;
+ h[1] = his_hardware_address;
+ h[2] = PPP_UI;
+ h[3] = FR_PADDING;
+ h[4] = FR_SNAP;
+ h[5] = 0;
+ h[6] = 0;
+ h[7] = 0;
+ *(short*) (h+8) = htons(ETHERTYPE_ARP);
+
+ reply->htype = htons(ARPHRD_FRELAY);
+ reply->ptype = htons(ETHERTYPE_IP);
+ reply->halen = 2;
+ reply->palen = 4;
+ reply->op = htons(ARPOP_INVREPLY);
+ reply->hsource = htons(my_hardware_address);
+ reply->psource1 = htonl(my_ip_address);
+ reply->psource2 = htonl(my_ip_address) >> 16;
+ reply->htarget = htons(his_hardware_address);
+ reply->ptarget1 = htonl(his_ip_address);
+ reply->ptarget2 = htonl(his_ip_address) >> 16;
+
+ if (IF_QFULL(&sp->pp_fastq)) {
+ IF_DROP(&ifp->if_snd);
+ m_freem(m);
+ } else
+ IF_ENQUEUE(&sp->pp_fastq, m);
+ if (! (ifp->if_flags & IFF_OACTIVE))
+ (*ifp->if_start)(ifp);
+ ifp->if_obytes += m->m_pkthdr.len + 3;
+}
+
+/*
+ * Process the input signaling packet (DLCI 0).
+ * The implemented protocol is ANSI T1.617 Annex D.
+ */
+static void
+sppp_fr_signal(struct sppp *sp, unsigned char *h, int len)
+{
+ STDDCL;
+ u_char *p;
+ int dlci;
+
+ if (h[2] != PPP_UI || h[3] != FR_SIGNALING || h[4] != 0) {
+ if (debug)
+ printf("%s%d: Invalid signaling header\n",
+ ifp->if_name, ifp->if_unit);
+bad: if (debug) {
+ printf("%02x", *h++);
+ while (--len > 0)
+ printf("-%02x", *h++);
+ printf("\n");
+ }
+ return;
+ }
+ if (h[5] == FR_MSG_ENQUIRY) {
+ if (len == FR_ENQUIRY_SIZE &&
+ h[12] == (u_char) sp->pp_seq) {
+ sp->pp_seq = random();
+ printf("%s%d: loopback detected\n",
+ ifp->if_name, ifp->if_unit);
+ }
+ return;
+ }
+ if (h[5] != FR_MSG_STATUS) {
+ if (debug)
+ printf("%s%d: Unknown signaling message: 0x%02x\n",
+ ifp->if_name, ifp->if_unit, h[5]);
+ goto bad;
+ }
+
+ /* Parse message fields. */
+ for (p=h+6; p<h+len; ) {
+ switch (*p) {
+ case FR_FLD_LSHIFT5:
+ case FR_FLD_RTYPE:
+ /* Ignore. */
+ break;
+ case FR_FLD_VERIFY:
+ if (p[1] != 2) {
+ if (debug)
+ printf("%s%d: Invalid signaling verify field length %d\n",
+ ifp->if_name, ifp->if_unit, p[1]);
+ break;
+ }
+ sp->pp_rseq = p[2];
+ if (debug) {
+ printf("%s%d: got lmi reply rseq=%d, seq=%d",
+ ifp->if_name, ifp->if_unit, p[2], p[3]);
+ if (p[3] != (u_char) sp->pp_seq)
+ printf(" (really %d)",
+ (u_char) sp->pp_seq);
+ printf("\n");
+ }
+ break;
+ case FR_FLD_PVC:
+ if (p[1] < 3) {
+ if (debug)
+ printf("%s%d: Invalid PVC status length %d\n",
+ ifp->if_name, ifp->if_unit, p[1]);
+ break;
+ }
+ dlci = (p[2] << 4 & 0x3f0) | (p[3] >> 3 & 0x0f);
+ if (sp->fr_dlci == 0)
+ sp->fr_dlci = dlci;
+ if (sp->fr_status != p[4])
+ printf("%s%d: DLCI %d %s%s\n",
+ ifp->if_name, ifp->if_unit, dlci,
+ p[4] & FR_DLCI_DELETE ? "deleted" :
+ p[4] & FR_DLCI_ACTIVE ? "active" : "passive",
+ p[4] & FR_DLCI_NEW ? ", new" : "");
+ sp->fr_status = p[4];
+ break;
+ default:
+ if (debug)
+ printf("%s%d: Unknown signaling field 0x%x\n",
+ ifp->if_name, ifp->if_unit, *p);
+ break;
+ }
+ if (*p & 0x80)
+ ++p;
+ else if (p < h+len+1 && p[1])
+ p += 2 + p[1];
+ else {
+ if (debug)
+ printf("%s%d: Invalid signaling field 0x%x\n",
+ ifp->if_name, ifp->if_unit, *p);
+ goto bad;
+ }
+ }
}
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199911121901.WAA00658>
