| Summary: | Added support of Frame Relay protocol | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | vak <vak> | ||||
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | ||||||
| Priority: | Normal | ||||||
| Version: | 3.3-RELEASE | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
I am not offering a code review below, just a style review. If you hate people who nitpick your style, you might not want to read on. However, if you want to contribute code to FreeBSD, we typically follow KNF as detailed in style(9). On with the show.. On Fri, 12 Nov 1999 vak@cronyx.ru wrote: > @@ -663,7 +735,7 @@ > * become invalid. So we > * - don't let packets with src ip addr 0 thru > * - we flag TCP packets with src ip 0 as an error > - */ > + */ > > if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ > { > @@ -674,7 +746,7 @@ > else > return(0); > } > - > + Whitespace changes, avoid. > @@ -1117,7 +1202,7 @@ > #if defined(__FreeBSD__) && __FreeBSD__ >= 3 > getmicrouptime(&tv); > #endif > - > + > MGETHDR (m, M_DONTWAIT, MT_DATA); > if (! m) > return; Ditto. > @@ -1738,7 +1823,7 @@ > case STATE_STOPPING: > sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, > 0, 0); > - TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, > + TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, > sp->ch[cp->protoidx]); Ditto. > @@ -1779,7 +1864,7 @@ > case STATE_REQ_SENT: > case STATE_ACK_RCVD: > case STATE_ACK_SENT: > - TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, > + TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, Ditto. > @@ -2322,7 +2407,7 @@ > /* notify low-level driver of state change */ > if (sp->pp_chg) > sp->pp_chg(sp, (int)sp->pp_phase); > - > + Ditto. :> > @@ -2641,7 +2726,7 @@ > (hisaddr == 1 && desiredaddr != 0)) { > /* > * Peer's address is same as our value, > - * or we have set it to 0.0.0.1 to > + * or we have set it to 0.0.0.1 to > * indicate that we do not really care, > * this is agreeable. Gonna conf-ack > * it. > @@ -3026,7 +3111,7 @@ > } > break; > } > - > + > if (debug) { > log(LOG_DEBUG, > SPP_FMT "chap input <%s id=0x%x len=%d name=", > @@ -3136,7 +3221,7 @@ > sppp_print_string(sp->hisauth.name, > sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); > addlog("\n"); > - } > + } > if (debug) { And all of the above. > @@ -3958,7 +4048,7 @@ > si->sin_addr.s_addr = htonl(src); > > /* add new route */ > - error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); > + error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); Here too. > @@ -3966,7 +4056,7 @@ > } > #endif > } > -} > +} And here. > > static int > sppp_params(struct sppp *sp, u_long cmd, void *data) > @@ -4098,7 +4188,7 @@ > /* if no NCP is starting, all this was in vain, close down */ > sppp_lcp_check_and_close(sp); > } > - > + > > static const char * > sppp_cp_type_name(u_char type) Here too > @@ -4271,4 +4361,500 @@ > 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) static void sppp_fr_input (struct sppp *sp, struct mbuf *m) { ... This allows for "grep -e '^functionname' foo.c". > +{ > + STDDCL; > + u_char *h = mtod (m, u_char*); Please initialilize and declare on differnt lines. > + > +/* > + * 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) Same as above. > + if (! m) > + return 0; I didn't mention this before because that was changing an old file, but in this file you'll want if (m == '\0') or at least if (!m) > + 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) { > + default: > + if (debug) > + printf ("%s%d: cannot handle address family %d\n", > + ifp->if_name, ifp->if_unit, family); > + m_freem (m); > + return 0; Default belongs as the bottom. > +/* > + * 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) Same as above. > + MGETHDR (m, M_DONTWAIT, MT_DATA); > + if (! m) > + return; Same as above. > +/* > + * Process the frame relay Inverse ARP request. > + */ > +static void sppp_fr_arp (struct sppp *sp, struct arp_req *req, > + u_short his_hardware_address) Same as above.` > + switch (ntohs (req->op)) { > + default: > + if (debug) > + printf ("%s%d: Invalid ARP op = 0x%x\n", > + ifp->if_name, ifp->if_unit, ntohs (req->op)); > + return; Default belongs at the bottom. > + case ARPOP_INVREQUEST: > + sppp_get_ip_addrs (sp, &my_ip_address, 0, 0); > + if (! my_ip_address) > + return; /* nothing to reply */ if (my_ip_address != '\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; All of those spaces between functionname(and_the, variables) needs to be dropped. Spaces only come after the keywords if, while, for, return and switch Everything else uses functionname(variables) Some of the same style snafus are made throughout the file, so I tried not to point out every single one of them when they were repeated. Please read style(9) for the source for most of these comments. -- - bill fumerola - billf@chc-chimes.com - BF1560 - computer horizons corp - - ph:(800) 252-2421 - bfumerol@computerhorizons.com - billf@FreeBSD.org - >I am not offering a code review below, just a style review. If you >hate people who nitpick your style, you might not want to read on. >However, if you want to contribute code to FreeBSD, we typically follow >KNF as detailed in style(9). > >On with the show.. >... Oh, it seems I am somewhat behind the times... I will prepare and submit the correct patch. Thanks, Serge State Changed From-To: open->closed Superseded by PR 14848 |
The in-kernel implementation of point-to-point protocols supported only PPP and Cisco/HDLC protocols. This patch adds Frame Relay support, with ANSI T1.617 signaling. Fix: #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 */ /* + * 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 +356,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 +525,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); @@ -663,7 +735,7 @@ * become invalid. So we * - don't let packets with src ip addr 0 thru * - we flag TCP packets with src ip 0 as an error - */ + */ if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ { @@ -674,7 +746,7 @@ else return(0); } - + /* * Put low delay, telnet, rlogin and ftp control packets * in front of the queue. @@ -694,12 +766,20 @@ } #endif + if (sp->pp_flags & PP_FR) { + /* Add frame relay header. */ + m = sppp_fr_header (sp, m, dst->sa_family); + if (! m) + 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 +851,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 +978,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 +1003,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 +1045,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); @@ -1117,7 +1202,7 @@ #if defined(__FreeBSD__) && __FreeBSD__ >= 3 getmicrouptime(&tv); #endif - + MGETHDR (m, M_DONTWAIT, MT_DATA); if (! m) return; @@ -1738,7 +1823,7 @@ case STATE_STOPPING: sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); - TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, + TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, sp->ch[cp->protoidx]); break; case STATE_REQ_SENT: @@ -1779,7 +1864,7 @@ case STATE_REQ_SENT: case STATE_ACK_RCVD: case STATE_ACK_SENT: - TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, + TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, sp->ch[cp->protoidx]); break; } @@ -2322,7 +2407,7 @@ /* notify low-level driver of state change */ if (sp->pp_chg) sp->pp_chg(sp, (int)sp->pp_phase); - + if (sp->pp_phase == PHASE_NETWORK) /* if no NCP is starting, close down */ sppp_lcp_check_and_close(sp); @@ -2641,7 +2726,7 @@ (hisaddr == 1 && desiredaddr != 0)) { /* * Peer's address is same as our value, - * or we have set it to 0.0.0.1 to + * or we have set it to 0.0.0.1 to * indicate that we do not really care, * this is agreeable. Gonna conf-ack * it. @@ -3026,7 +3111,7 @@ } break; } - + if (debug) { log(LOG_DEBUG, SPP_FMT "chap input <%s id=0x%x len=%d name=", @@ -3136,7 +3221,7 @@ sppp_print_string(sp->hisauth.name, sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); addlog("\n"); - } + } if (debug) { log(LOG_DEBUG, SPP_FMT "chap input(%s) " "<%s id=0x%x len=%d name=", @@ -3812,6 +3897,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) @@ -3958,7 +4048,7 @@ si->sin_addr.s_addr = htonl(src); /* add new route */ - error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); + error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); if (debug && error) { log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", @@ -3966,7 +4056,7 @@ } #endif } -} +} static int sppp_params(struct sppp *sp, u_long cmd, void *data) @@ -4098,7 +4188,7 @@ /* if no NCP is starting, all this was in vain, close down */ sppp_lcp_check_and_close(sp); } - + static const char * sppp_cp_type_name(u_char type) @@ -4271,4 +4361,500 @@ 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 = mtod (m, u_char*); + struct ifqueue *inq; + int dlci, hlen, proto, s; + + /* Get the DLCI number. */ + if (m->m_pkthdr.len < 10) { +bad: m_freem (m); + return; + } + 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]) { + default: + if (debug) + printf ("%s%d: Unsupported NLPID 0x%02x\n", + ifp->if_name, ifp->if_unit, h[3]); + goto bad; + + 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; + } + + /* Remove frame relay header. */ + m_adj (m, hlen); + + switch (proto) { + default: + ++ifp->if_noproto; +drop: ++ifp->if_ierrors; + ++ifp->if_iqdrops; + m_freem (m); + return; +#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 + } + + 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) + 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) { + default: + if (debug) + printf ("%s%d: cannot handle address family %d\n", + ifp->if_name, ifp->if_unit, family); + m_freem (m); + return 0; +#ifdef INET + case AF_INET: +#if 0 /* Crashes on fragmented packets */ + /* + * Set the discard eligibility bit, if: + * 1) no fragmentation + * 2) length > 400 bytes + * 3a) the protocol is UDP or + * 3b) TCP data (no control bits) + */ + { + struct ip *ip = (struct ip*) (h + hlen); + struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); + + if (! (ip->ip_off & ~IP_DF) && ip->ip_len > 400 && + (ip->ip_p == IPPROTO_UDP || + ip->ip_p == IPPROTO_TCP && ! tcp->th_flags)) + h[1] |= FR_DE; + } +#endif + 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 + } + 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) + 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 */ + + *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)) { + default: + if (debug) + printf ("%s%d: Invalid ARP op = 0x%x\n", + ifp->if_name, ifp->if_unit, ntohs (req->op)); + return; + + case ARPOP_INVREPLY: + /* Ignore. */ + return; + + case ARPOP_INVREQUEST: + sppp_get_ip_addrs (sp, &my_ip_address, 0, 0); + if (! my_ip_address) + return; /* nothing to reply */ + 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; + } + 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); + 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) + 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) { + default: + if (debug) + printf ("%s%d: Unknown signaling field 0x%x\n", + ifp->if_name, ifp->if_unit, *p); + break; + 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) + 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; + } + 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; + } + } }--0aMu9MklQHisK76W34xucsL6n0oxx5CS1781uC29mFY3UzwF Content-Type: text/plain; name="file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="file.diff" --- if_sppp33.h Fri Nov 12 17:09:39 1999 +++ if_sppp.h Fri Nov 12 17:10:20 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 @@