/* * Calculate a new FCS given the current FCS and the new data. */ u_short pppfcs(u_short fcs, u_char *cp, int len) { while (len--) fcs = PPP_FCS(fcs, *cp++); return (fcs); }
/* * loop_chars - process characters received from the loopback. * Calls loop_frame when a complete frame has been accumulated. * Return value is 1 if we need to bring up the link, 0 otherwise. */ int loop_chars( unsigned char *p, int n) { int c, rv; rv = 0; for (; n > 0; --n) { c = *p++; if (c == PPP_FLAG) { if (!escape_flag && !flush_flag && framelen > 2 && fcs == PPP_GOODFCS) { framelen -= 2; if (loop_frame(frame, framelen)) rv = 1; } framelen = 0; flush_flag = 0; escape_flag = 0; fcs = PPP_INITFCS; continue; } if (flush_flag) continue; if (escape_flag) { c ^= PPP_TRANS; escape_flag = 0; } else if (c == PPP_ESCAPE) { escape_flag = 1; continue; } if (framelen >= framemax) { flush_flag = 1; continue; } frame[framelen++] = c; fcs = PPP_FCS(fcs, c); } return rv; }
int check_frame(unsigned char *outbuf, int res) { static int setup = 0; int x; unsigned short fcs = PPP_INITFCS; if (c < 1) { c = 1; } if (!setup) { c = outbuf[0]; setup++; } for (x = 0; x < res; x++) { if (outbuf[x] != c && (x < res - 2)) { printf("(Error %d): Unexpected result, %d != %d, position %d %d bytes since last error.\n", ++errors, outbuf[x], c, x, bytes); if (!x) { c = outbuf[0]; } bytes = 0; } else { bytes++; } fcs = PPP_FCS(fcs, outbuf[x]); } if (fcs != PPP_GOODFCS) { printf("FCS Check failed :( (%04x != %04x)\n", fcs, PPP_GOODFCS); } #if 0 if (res != c) { printf("Res is %d, expected %d\n", res, c+2); } #endif c = bit_next(c); return 0; }
/* Send a packet on the given connection. */ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) { int pd = (int)netif->state; u_short protocol = PPP_IP; PPPControl *pc = &pppControl[pd]; u_int fcsOut = PPP_INITFCS; struct pbuf *headMB = NULL, *tailMB = NULL, *p; u_char c; (void)ipaddr; /* Validate parameters. */ /* We let any protocol value go through - it can't hurt us * and the peer will just drop it if it's not accepting it. */ if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n", pd, protocol, pb)); #if LINK_STATS lwip_stats.link.opterr++; lwip_stats.link.drop++; #endif return ERR_ARG; } /* Check that the link is up. */ if (lcp_phase[pd] == PHASE_DEAD) { PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd)); #if LINK_STATS lwip_stats.link.rterr++; lwip_stats.link.drop++; #endif return ERR_RTE; } /* Grab an output buffer. */ headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); if (headMB == NULL) { PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd)); #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif /* LINK_STATS */ return ERR_MEM; } #if VJ_SUPPORT > 0 /* * Attempt Van Jacobson header compression if VJ is configured and * this is an IP packet. */ if (protocol == PPP_IP && pc->vjEnabled) { switch (vj_compress_tcp(&pc->vjComp, pb)) { case TYPE_IP: /* No change... protocol = PPP_IP_PROTOCOL; */ break; case TYPE_COMPRESSED_TCP: protocol = PPP_VJC_COMP; break; case TYPE_UNCOMPRESSED_TCP: protocol = PPP_VJC_UNCOMP; break; default: PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd)); #if LINK_STATS lwip_stats.link.proterr++; lwip_stats.link.drop++; #endif pbuf_free(headMB); return ERR_VAL; } } #endif tailMB = headMB; /* Build the PPP header. */ if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) tailMB = pppAppend(PPP_FLAG, tailMB, NULL); pc->lastXMit = sys_jiffies(); if (!pc->accomp) { fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); fcsOut = PPP_FCS(fcsOut, PPP_UI); tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); } if (!pc->pcomp || protocol > 0xFF) { c = (protocol >> 8) & 0xFF; fcsOut = PPP_FCS(fcsOut, c); tailMB = pppAppend(c, tailMB, &pc->outACCM); }
if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) tailMB = pppAppend(PPP_FLAG, tailMB, NULL); pc->lastXMit = sys_jiffies(); if (!pc->accomp) { fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); fcsOut = PPP_FCS(fcsOut, PPP_UI); tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); } if (!pc->pcomp || protocol > 0xFF) { c = (protocol >> 8) & 0xFF; fcsOut = PPP_FCS(fcsOut, c); tailMB = pppAppend(c, tailMB, &pc->outACCM); } c = protocol & 0xFF; fcsOut = PPP_FCS(fcsOut, c); tailMB = pppAppend(c, tailMB, &pc->outACCM); /* Load packet. */ for(p = pb; p; p = p->next) { int n; u_char *sPtr; sPtr = (u_char*)p->payload; n = p->len; while (n-- > 0) { c = *sPtr++; /* Update FCS before checking for special characters. */ fcsOut = PPP_FCS(fcsOut, c);
void dumpppp(FILE *f) { int c, n, k; int nb, nl, dn, proto, rv; char *dir, *q; unsigned char *p, *r, *endp; unsigned char *d; unsigned short fcs; struct pkt *pkt; spkt.cnt = rpkt.cnt = 0; spkt.esc = rpkt.esc = 0; while ((c = getc(f)) != EOF) { switch (c) { case 1: case 2: if (reverse) c = 3 - c; dir = c==1? "sent": "rcvd"; pkt = c==1? &spkt: &rpkt; n = getc(f); n = (n << 8) + getc(f); *(c==1? &tot_sent: &tot_rcvd) += n; for (; n > 0; --n) { c = getc(f); switch (c) { case EOF: printf("\nEOF\n"); if (spkt.cnt > 0) printf("[%d bytes in incomplete send packet]\n", spkt.cnt); if (rpkt.cnt > 0) printf("[%d bytes in incomplete recv packet]\n", rpkt.cnt); exit(0); case '~': if (pkt->cnt > 0) { q = dir; if (pkt->esc) { printf("%s aborted packet:\n ", dir); q = " "; } nb = pkt->cnt; p = pkt->buf; pkt->cnt = 0; pkt->esc = 0; if (nb <= 2) { printf("%s short packet [%d bytes]:", q, nb); for (k = 0; k < nb; ++k) printf(" %.2x", p[k]); printf("\n"); break; } fcs = PPP_INITFCS; for (k = 0; k < nb; ++k) fcs = PPP_FCS(fcs, p[k]); fcs &= 0xFFFF; nb -= 2; endp = p + nb; r = p; if (r[0] == 0xff && r[1] == 3) r += 2; if ((r[0] & 1) == 0) ++r; ++r; if (endp - r > mru) printf(" ERROR: length (%td) > MRU (%d)\n", endp - r, mru); if (decompress && fcs == PPP_GOODFCS) { /* See if this is a CCP or compressed packet */ d = dbuf; r = p; if (r[0] == 0xff && r[1] == 3) { *d++ = *r++; *d++ = *r++; } proto = r[0]; if ((proto & 1) == 0) proto = (proto << 8) + r[1]; if (proto == PPP_CCP) { handle_ccp(pkt, r + 2, endp - r - 2); } else if (proto == PPP_COMP) { if ((pkt->flags & CCP_ISUP) && (pkt->flags & CCP_DECOMP_RUN) && pkt->state && (pkt->flags & CCP_ERR) == 0) { struct packet in, out, *outp; in.buf = r; in.len = endp - r; out.buf = d; outp = &out; rv = pkt->comp->decompress(pkt->state, &in, &outp); dn = outp->len; d = outp->buf; switch (rv) { case DECOMP_OK: p = dbuf; nb = d + dn - p; if ((d[0] & 1) == 0) --dn; --dn; if (dn > mru) printf(" ERROR: decompressed length (%d) > MRU (%d)\n", dn, mru); break; case DECOMP_ERROR: printf(" DECOMPRESSION ERROR\n"); pkt->flags |= CCP_ERROR; break; case DECOMP_FATALERROR: printf(" FATAL DECOMPRESSION ERROR\n"); pkt->flags |= CCP_FATALERROR; break; } } } else if (pkt->state && (pkt->flags & CCP_DECOMP_RUN)) { struct packet in; in.buf = r; in.len = endp - r; pkt->comp->incomp(pkt->state, &in); } } do { nl = nb < 16? nb: 16; printf("%s ", q); for (k = 0; k < nl; ++k) printf(" %.2x", p[k]); for (; k < 16; ++k) printf(" "); printf(" "); for (k = 0; k < nl; ++k) { c = p[k]; putchar((' ' <= c && c <= '~')? c: '.'); } printf("\n"); q = " "; p += nl; nb -= nl; } while (nb > 0); if (fcs != PPP_GOODFCS) printf(" BAD FCS: (residue = %x)\n", fcs); } break; case '}': if (!pkt->esc) { pkt->esc = 1; break; } /* else fall through */ default: if (pkt->esc) { c ^= 0x20; pkt->esc = 0; } pkt->buf[pkt->cnt++] = c; break; } } break; case 3: case 4: if (reverse) c = 7 - c; dir = c==3? "send": "recv"; pkt = c==3? &spkt: &rpkt; printf("end %s", dir); if (pkt->cnt > 0) printf(" [%d bytes in incomplete packet]", pkt->cnt); printf("\n"); break; case 5: case 6: case 7: show_time(f, c); break; default: printf("?%.2x\n", c); } } }
void PppCreateMessageFrameIp(void) { U_INT msgLen, frameLen; U_SHORT fcs = PPP_INITFCS; U_CHAR *msgPtr = PppControl.OutMessageContainer.Buf; U_CHAR *framePtr = PppControl.OutFrameContainer.Buf; PPP_LOG_ENTRY(MDB_PppCreateMessageFrame); PPP_LOG_1(PppControl.OutMessageContainer.Length); PUTCHAR(PPP_FLAG, framePtr); frameLen = 1; for (msgLen = PppControl.OutMessageContainer.Length; msgLen > 0; msgLen--) { if ((*msgPtr == PPP_FLAG) || (*msgPtr == PPP_ESCAPE)) { frameLen++; PUTCHAR(PPP_ESCAPE, framePtr); PUTCHAR((*msgPtr) ^ PPP_TRANS, framePtr); } else { PUTCHAR(*msgPtr, framePtr); } PPP_FCS(fcs, *msgPtr); msgPtr++; frameLen++; } // Append FCS to Out Message, and update its length PPP_LOG_1(fcs); fcs ^= 0xffff; PPP_LOG_1(fcs); PUTCHAR_NOINC(fcs & 0xFF, msgPtr); PPP_LOG_1(*msgPtr); PUTCHAR_NOINC((fcs >> 8) & 0xFF, (msgPtr + 1)); PPP_LOG_1(*(msgPtr + 1)); PppControl.OutMessageContainer.Length += 2; // Add FCS to PPP encoded frame for (msgLen = 2; msgLen > 0; msgLen--) { if ((*msgPtr == PPP_FLAG) || (*msgPtr == PPP_ESCAPE)) { frameLen++; PUTCHAR(PPP_ESCAPE, framePtr); PUTCHAR((*msgPtr) ^ PPP_TRANS, framePtr); } else { PUTCHAR(*msgPtr, framePtr); } msgPtr++; frameLen++; } PUTCHAR(PPP_FLAG, framePtr); frameLen++; PPP_LOG_1(frameLen); PPP_TRACE_BUF("CreateMessageFrame: ", PppControl.OutFrameContainer.Buf, frameLen); PppControl.OutFrameContainer.Length = frameLen; PPP_LOG_EXIT(); }
void PppMessageReq(const U_CHAR *buf, U_INT length) { MessageBufS *newMessage = NULL; BOOL isEnd = FALSE; U_CHAR *s, *d; //s = running on source buffer, received from PC d = runs on destination buffer QueueMessageS qMsg; PPP_LOG_ENTRY(MDB_PppMessageReq); PPP_LOG_1(length); PPP_TRACE_BUF("PppMessageReq: ", (U_CHAR *)buf, length); s = (U_CHAR *) buf; do { PPP_LOG_1(length); if (PppControl.IsRxFragmented) { PPP_LOG(); newMessage = PppControl.InFramePlaceholder; if (newMessage == NULL) { PppControl.IsRxFragmented = FALSE; PppControl.IsEscapeFound = FALSE; PppControl.IncomingFcs = PPP_INITFCS; PppControl.APOOMDrops++; PPP_PRINTF("[PPP] %s: Fragmented Flag Error - Dropped %d AP packets\n", __func__, (int)PppControl.APOOMDrops); PPP_LOG_EXIT(); return; } d = &newMessage->Buf[newMessage->Length]; } else { PPP_LOG(); newMessage = PppAllocateMessage(PPP_FRAME_SIZE); PppControl.IsRxFragmented = FALSE; PppControl.IsEscapeFound = FALSE; PppControl.IncomingFcs = PPP_INITFCS; if (newMessage == NULL) { PppControl.APOOMDrops++; PPP_PRINTF("[PPP] %s: Dropped %d AP packets\n", __func__, (int)PppControl.APOOMDrops); PPP_LOG_EXIT(); return; } d = newMessage->Buf; } while ((length > 0) && (!isEnd)) { if (*s == PPP_FLAG) { switch (PppControl.FlagState) { case HDLC_FLAG_NONE: PppControl.FlagState = HDLC_FLAG_FIRST; PPP_LOG(); break; case HDLC_FLAG_FIRST: PPP_LOG(); if (newMessage->Length != 0) { PppControl.FlagState = HDLC_FLAG_LAST; isEnd = TRUE; PPP_LOG(); } break; default: break; } } else if (*s == PPP_ESCAPE) { PppControl.IsEscapeFound = TRUE; } else if (PppControl.IsEscapeFound) { PppControl.IsEscapeFound = FALSE; if (newMessage->Length < PppControl.lcpRecvParams.Mru.Mru + 3) //protocol+FCS is also copied to buffer so add 3 bytes to MRU limit { PPP_ESCAPE_C(*d, *s); PPP_FCS(PppControl.IncomingFcs, *d); d++; newMessage->Length++; } else { newMessage->Length = 0xFFFF; break; } } else { if (newMessage->Length < PppControl.lcpRecvParams.Mru.Mru + 3) //protocol+FCS is also copied to buffer so add 3 bytes to MRU limit { *d = *s; PPP_FCS(PppControl.IncomingFcs, *d); d++; newMessage->Length++; } else { newMessage->Length = 0xFFFF; break; } } s++; length--; } PPP_LOG_1(newMessage->Length); PPP_LOG_1(PppControl.lcpRecvParams.Mru.Mru); if (newMessage->Length > PppControl.lcpRecvParams.Mru.Mru + 3) { //Message too long - drop it, free memory and report PPP_PRINTF("[PPP] %s: Message too long, dropping...length=%d mru=%d\n", __func__, (int)newMessage->Length, (int)PppControl.lcpRecvParams.Mru.Mru); PppFreeMessage(newMessage); newMessage = NULL; pppResetRecvState(&PppControl); isEnd = FALSE; while (length > 0 && *s != PPP_FLAG) { s++; length--; } } else if (!isEnd) { PPP_LOG_1(PppControl.FlagState); if (PppControl.FlagState == HDLC_FLAG_FIRST) { PPP_TRACE("IsFrarmented = TRUE"); PppControl.IsRxFragmented = TRUE; PppControl.InFramePlaceholder = newMessage; newMessage = NULL; } } else { PPP_LOG_1(PppControl.IncomingFcs); if (PPP_GOODFCS == PppControl.IncomingFcs) { // Message is OK. newMessage.Length includes FCS, so decrease it by 2 newMessage->Length -= 2; PPP_LOG_3((U_INT) newMessage, (U_INT) newMessage->Buf, newMessage->Length); PPP_TRACE_BUF("In-Decoded: ", newMessage->Buf, newMessage->Length); if (pppIsWriteThrough(newMessage) == TRUE) { if (PppControl.PppState == PPP_STATE_CONNECTED) { pppRelayMessageToCommDirect(newMessage); } PppFreeMessage(newMessage); newMessage = NULL; } else { qMsg.Type = PPP_MSG_REQ; qMsg.Ptr = (U_CHAR *)newMessage; PPP_LOG_1((U_INT)qMsg.Ptr); PPP_SEND_Q_MSG(PppControl.MsgQRef, &qMsg, sizeof(qMsg)); newMessage = NULL; } } else { PppFreeMessage(newMessage); newMessage = NULL; PPP_PRINTF("[PPP] %s: Wrong checksum, dropping message:%x\n", __func__, PppControl.IncomingFcs); } pppResetRecvState(&PppControl); isEnd = FALSE; } } while (length > 0); if (newMessage != NULL) { PppFreeMessage(newMessage); } PPP_LOG_EXIT(); }