📄 ppp.c
字号:
p = lcp_cfg_req(pcb, NULL); if((ret = ppp_cp_output(pcb, PPP_LCP, LCP_CFG_REQ, ppp_next_id(), p)) == ERR_OK) { pcb->state = PPP_LCP_CFG; } } return ret;}/*-----------------------------------------------------------------------------------*//* * ppp_disconnect(): * * Closes the connection held by the PCB but does not dealloc it. Call the * disconnected callback when disconnection is complete. *//*-----------------------------------------------------------------------------------*/err_tppp_disconnect(struct ppp_pcb *pcb){ err_t ret; if(pcb->state == PPP_LCP_CLOSED || pcb->state == PPP_LCP_LISTEN || pcb->state == PPP_LCP_CLOSING) { PPP_EVENT_DISCONNECTED(pcb, ERR_OK, PPP_LCP, ret); return ERR_OK; } pcb->state = PPP_LCP_CLOSING; return ppp_cp_output(pcb, PPP_LCP, LCP_TERM_REQ, ppp_next_id(), NULL);}/*-----------------------------------------------------------------------------------*//* * ppp_echo(): * * Sends an empty PPP echo request message. Also specify the function that should * be called when a PPP echo reply has been received. *//*-----------------------------------------------------------------------------------*/err_tppp_echo(struct ppp_pcb *pcb, err_t (* echo_rsp)(void *arg, struct ppp_pcb *tpcb, err_t err)){ if(pcb->state == PPP_LCP_CLOSED || pcb->state == PPP_LCP_LISTEN || pcb->state == PPP_LCP_CFG || pcb->state == PPP_LCP_CLOSING) { return ERR_CLSD; } pcb->echo_rsp = echo_rsp; return ppp_cp_output(pcb, PPP_LCP, LCP_ECHO_REQ, ppp_next_id(), NULL);}/*-----------------------------------------------------------------------------------*//* * ppp_cp_output(): * * Sends a PPP control protocol packet (IPCP or LCP). *//*-----------------------------------------------------------------------------------*/err_tppp_cp_output(struct ppp_pcb *pcb, u16_t proto, u8_t code, u8_t id, struct pbuf *q){ struct pbuf *p, *r; struct ppp_req *req; err_t ret; u16_t fcs; u8_t j = 0; LWIP_DEBUGF(LWBT_PPP_DEBUG, ("ppp_cp_output: Code == 0x%x\n", code)); if(pcb->lcpcfg & LCP_CFG_OUT_ACCOMP && pcb->state != PPP_LCP_CFG) { p = pbuf_alloc(PBUF_RAW, PPP_HDR_LEN - 2 + PPP_CPHDR_LEN, PBUF_RAM); } else { p = pbuf_alloc(PBUF_RAW, PPP_HDR_LEN + PPP_CPHDR_LEN, PBUF_RAM); } if(!(pcb->lcpcfg & LCP_CFG_OUT_ACCOMP && pcb->state != PPP_LCP_CFG)) { ((u16_t *)p->payload)[j/2] = htons(PPP_ADDRCTRL); /* Set adddress control field */ j+= 2; } ((u16_t *)p->payload)[j/2] = htons(proto); /* Set protocol field */ j+= 2; ((u8_t *)p->payload)[j++] = code; /* Set type of control packet */ ((u8_t *)p->payload)[j++] = id; /* Set packet identifier */ if(q == NULL) { ((u16_t *)p->payload)[j/2] = htons(PPP_CPHDR_LEN); /* Set length of control packet */ j+= 2; } else { ((u16_t *)p->payload)[j/2] = htons(q->tot_len + PPP_CPHDR_LEN); /* Set length of control packet */ j+= 2; pbuf_chain(p, q); pbuf_free(q); } r = pbuf_alloc(PBUF_RAW, 2, PBUF_RAM); /* Alloc a pbuf for fcs */ /* Add FCS to packet */ fcs = fcs16_crc_calc(p, p->tot_len); ((u8_t *)r->payload)[0] = (fcs & 0xFF); /* Least significant byte first */ ((u8_t *)r->payload)[1] = ((fcs >> 8) & 0xFF); pbuf_chain(p, r); pbuf_free(r); ret = ppp_output(pcb, p); /* Check if a timer should be associated with the request */ if(ret == ERR_OK && (code == LCP_CFG_REQ || code == IPCP_CFG_REQ || code == LCP_TERM_REQ || code == IPCP_TERM_REQ)) { /* Check if the request already is in the outstanding requests list */ for(req = pcb->reqs; req != NULL; req = req->next) { if(req->id == id) { break; } } if(req == NULL) { /* Add request to outstanding requests list */ LWIP_DEBUGF(LWBT_PPP_DEBUG, ("ppp_cp_output: Allocate memory for request with ID 0x%x Code 0x%x***********\n", id, code)); if((req = lwbt_memp_malloc(MEMP_PPP_REQ)) == NULL) { LWIP_DEBUGF(LWBT_PPP_DEBUG, ("ppp_cp_output: could not allocate memory for request\n")); pbuf_free(p); /* Dealloc control packet */ return ERR_MEM; } req->p = p; req->id = id; req->proto = proto; if((req->rto = (PPP_RTO/(PPP_NRTX + 1))) == 0) { req->rto = 1; } req->nrtx = PPP_NRTX; PPP_REQ_REG(&(pcb->reqs), req); } } else { pbuf_free(p); /* Free control packet */ } return ret;}/*-----------------------------------------------------------------------------------*//* * ppp_netif_output(): * * Output IP data from a lwIP network interface over PPP. *//*-----------------------------------------------------------------------------------*/err_tppp_netif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr){ struct ppp_pcb *pcb; /* struct pbuf *q; u16_t i; for(q = p; q != NULL; q = q->next) { for(i = 0; i < q->len; ++i) { LWIP_DEBUGF(TCP_DEBUG, ("Out: 0x%x\n", ((u8_t *)q->payload)[i])); } LWIP_DEBUGF(TCP_DEBUG, ("\n")); } */ for(pcb = ppp_active_pcbs; pcb != NULL; pcb = pcb->next) { if(pcb->bluetoothif == netif) { break; } } if(pcb != NULL) { LWIP_DEBUGF(LWBT_PPP_DEBUG, ("ppp_netif_output: Local IP address: %d.%d.%d.%d\n", (u8_t)(ntohl(pcb->bluetoothif->ip_addr.addr) >> 24) & 0xff, (u8_t)(ntohl(pcb->bluetoothif->ip_addr.addr) >> 16) & 0xff, (u8_t)(ntohl(pcb->bluetoothif->ip_addr.addr) >> 8) & 0xff, (u8_t)ntohl(pcb->bluetoothif->ip_addr.addr) & 0xff)); return ppp_data_output(pcb, p); } return ERR_CONN; /* No matching PPP connection exists */}/*-----------------------------------------------------------------------------------*//* * ppp_data_output(): * * Output IP data over PPP. *//*-----------------------------------------------------------------------------------*/err_tppp_data_output(struct ppp_pcb *pcb, struct pbuf *q){ struct pbuf *r, *p; u8_t hdrlen = PPP_HDR_LEN; u8_t i = 0; err_t ret; u16_t fcs; LWIP_DEBUGF(LWBT_PPP_DEBUG, ("ppp_data_output: q->tot_len = %d\n", q->tot_len)); if(pcb == NULL) { return ERR_CONN; /* Not connected */ } if(pcb->state != PPP_IPCP_OPEN) { return ERR_CONN; /* Not connected */ } if(pcb->lcpcfg & LCP_CFG_OUT_ACCOMP) { hdrlen -= 2; } if(pcb->lcpcfg & LCP_CFG_OUT_PCOMP) { --hdrlen; } p = pbuf_alloc(PBUF_RAW, hdrlen, PBUF_RAM); if(!(pcb->lcpcfg & LCP_CFG_OUT_ACCOMP)) { *((u16_t *)p->payload) = htons(PPP_ADDRCTRL); i += 2; } if(pcb->lcpcfg & LCP_CFG_OUT_PCOMP) { ((u8_t *)p->payload)[i] = PPP_IP_DATA; } else { ((u16_t *)p->payload)[i/2] = htons(PPP_IP_DATA); //TODO: WE MAY DIVIDE BY ZERO HERE... } /* Chain any information data to header */ if(q != NULL) { pbuf_chain(p, q); //pbuf_free(q); } r = pbuf_alloc(PBUF_RAW, 2, PBUF_RAM); /* Alloc a pbuf for fcs */ /* Add FCS to packet */ fcs = fcs16_crc_calc(p, p->tot_len); ((u8_t *)r->payload)[0] = (fcs & 0x00ff); /* Least significant byte first */ ((u8_t *)r->payload)[1] = ((fcs >> 8) & 0x00ff); pbuf_chain(p, r); pbuf_free(r); ret = ppp_output(pcb, p); /* Free PPP header. Higher layers will handle rest of packet */ if(q != NULL) { pbuf_dechain(p); pbuf_realloc(q, q->tot_len-2); /* Remove FCS from packet */ } pbuf_free(p); return ret;}/*-----------------------------------------------------------------------------------*//* * ppp_output_alloc(): * * Called by ppp_output() to allocate a pbuf with the same size as the remaining * characters in the packet to be byte stuffed. *//*-----------------------------------------------------------------------------------*/struct pbuf *ppp_output_alloc(struct pbuf *p, u16_t i){ struct pbuf *q; u16_t k = 0; /* Get length of remaining characters in packet */ for(q = p; q != NULL; q = q->next) { k += q->len; } k -= i; q = pbuf_alloc(PBUF_RAW, k, PBUF_RAM); /* Alloc a pbuf for that size */ return q;}/*-----------------------------------------------------------------------------------*//* * ppp_output(): * * Output PPP data. Byte stuffs the packet and forward it to RFCOMM. *//*-----------------------------------------------------------------------------------*/err_tppp_output(struct ppp_pcb *pcb, struct pbuf *p) { struct pbuf *q, *r, *s; u16_t i; u16_t j = 0; u8_t c; err_t ret; /* To minimize the number of pbufs we need to chain together we always allocate the same size as the number of characters remaining to be checked */ r = pbuf_alloc(PBUF_RAW, p->tot_len + 1, PBUF_RAM); s = r; ((u8_t *)s->payload)[j++] = PPP_END; for(q = p; q != NULL; q = q->next) { for(i = 0; i < q->len; ++i) { c = ((u8_t *)q->payload)[i]; if(j == s->len) { s = ppp_output_alloc(q, i); pbuf_chain(r, s); pbuf_free(s); j = 0; } switch(c) { case PPP_END: ((u8_t *)s->payload)[j++] = PPP_ESC; if(j == s->len) { s = ppp_output_alloc(q, i); pbuf_chain(r, s); pbuf_free(s); j = 0; } ((u8_t *)s->payload)[j++] = PPP_ESC_END; break; case PPP_ESC: ((u8_t *)s->payload)[j++] = PPP_ESC; if(j == s->len) { s = ppp_output_alloc(q, i); pbuf_chain(r, s); pbuf_free(s); j = 0; } ((u8_t *)s->payload)[j++] = PPP_ESC_ESC; break; default: /* Check if the character should be escaped according to the ACCM */ if(c < 0x20) { if(pcb->outaccm & (1 << c) || pcb->state == PPP_LCP_CFG) { ((u8_t *)s->payload)[j++] = PPP_ESC; if(j == s->len) { s = ppp_output_alloc(q, i); pbuf_chain(r, s); pbuf_free(s); j = 0; } ((u8_t *)s->payload)[j++] = c ^ 0x20; /* Character following escape character is exclusive-ord with 0x20 */ } else { ((u8_t *)s->payload)[j++] = c; } } else { ((u8_t *)s->payload)[j++] = c; } break; } } } s = pbuf_alloc(PBUF_RAW, 1, PBUF_RAM); /* Alloc a pbuf for PPP_END */ *((u8_t *)s->payload) = PPP_END; pbuf_chain(r, s); pbuf_free(s); LWIP_DEBUGF(LWBT_PPP_DEBUG, ("ppp_output: r->tot_len = %d\n", r->tot_len)); /* for(s = r; s != NULL; s = s->next) { //u8_t i; for(i = 0; i < s->len; ++i) { LWIP_DEBUGF(SDP_DEBUG, ("ppp_output: REQ 0x%x\n", ((u8_t *)s->payload)[i])); } LWIP_DEBUGF(SDP_DEBUG, ("ppp_output: STOP\n")); } */ /* Check which convergence layer is in use */ if(rfcomm_cl(pcb->rfcommpcb)) { ret = rfcomm_uih_credits(pcb->rfcommpcb, PBUF_POOL_SIZE - rfcomm_remote_credits(pcb->rfcommpcb), r); } else { ret = rfcomm_uih(pcb->rfcommpcb, rfcomm_cn(pcb->rfcommpcb), r); } pbuf_free(r); /* Free byte stuffed copy of outgoing packet */ return ret;}/*-----------------------------------------------------------------------------------*//* * ppp_next_id(): * * Return a new control protocol identifier. Aids in matching requests and replies. *//*-----------------------------------------------------------------------------------*/u8_tppp_next_id(void){ return ++id_nxt;}/*-----------------------------------------------------------------------------------*//* * ppp_disconnected(): * * Used to specify the function that should be called when a PPP connection is * disconnected *//*-----------------------------------------------------------------------------------*/voidppp_disconnected(struct ppp_pcb *pcb, err_t (* disconnected)(void *arg, struct ppp_pcb *pcb, u16_t proto, err_t err)){ pcb->disconnected = disconnected;}/*-----------------------------------------------------------------------------------*//* * ppp_listen(): * * Set the state of the connection to be PPP_LCP_LISTEN, which means that it is able * to accept incoming connections. *//*---------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -