📄 ppp_oe.c
字号:
if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) {#if 0 if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { /* slow retry mode */ retry_wait = PPPOE_SLOW_RETRY; } else#endif { pppoe_abort_connect(sc); return; } } if ((err = pppoe_send_padi(sc)) != 0) { sc->sc_padi_retried--; PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } sys_timeout(retry_wait, pppoe_timeout, sc); break; case PPPOE_STATE_PADR_SENT: sc->sc_padr_retried++; if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_state = PPPOE_STATE_PADI_SENT; sc->sc_padr_retried = 0; if ((err = pppoe_send_padi(sc)) != 0) { PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); return; } if ((err = pppoe_send_padr(sc)) != 0) { sc->sc_padr_retried--; PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); break; case PPPOE_STATE_CLOSING: pppoe_do_disconnect(sc); break; default: return; /* all done, work in peace */ }}/* Start a connection (i.e. initiate discovery phase) */intpppoe_connect(struct pppoe_softc *sc){ int err; if (sc->sc_state != PPPOE_STATE_INITIAL) { return EBUSY; }#ifdef PPPOE_SERVER /* wait PADI if IFF_PASSIVE */ if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { return 0; }#endif /* save state, in case we fail to send PADI */ sc->sc_state = PPPOE_STATE_PADI_SENT; sc->sc_padr_retried = 0; err = pppoe_send_padi(sc); PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); return err;}/* disconnect */voidpppoe_disconnect(struct pppoe_softc *sc){ if (sc->sc_state < PPPOE_STATE_SESSION) { return; } /* * Do not call pppoe_disconnect here, the upper layer state * machine gets confused by this. We must return from this * function and defer disconnecting to the timeout handler. */ sc->sc_state = PPPOE_STATE_CLOSING; sys_timeout(20, pppoe_timeout, sc);}static intpppoe_do_disconnect(struct pppoe_softc *sc){ int err; if (sc->sc_state < PPPOE_STATE_SESSION) { err = EBUSY; } else { PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); } /* cleanup softc */ sc->sc_state = PPPOE_STATE_INITIAL; MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_ac_cookie_len = 0;#ifdef PPPOE_SERVER if (sc->sc_hunique) { mem_free(sc->sc_hunique); sc->sc_hunique = NULL; } sc->sc_hunique_len = 0;#endif sc->sc_session = 0; sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ return err;}/* Connection attempt aborted */static voidpppoe_abort_connect(struct pppoe_softc *sc){ printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); sc->sc_state = PPPOE_STATE_CLOSING; sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ /* clear connection state */ MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_state = PPPOE_STATE_INITIAL;}/* Send a PADR packet */static err_tpppoe_send_padr(struct pppoe_softc *sc){ struct pbuf *pb; u8_t *p; size_t len;#ifdef PPPOE_TODO size_t l1 = 0; /* XXX: gcc */#endif /* PPPOE_TODO */ if (sc->sc_state != PPPOE_STATE_PADR_SENT) { return ERR_CONN; } len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */#ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ l1 = strlen(sc->sc_service_name); len += l1; }#endif /* PPPOE_TODO */ if (sc->sc_ac_cookie_len > 0) { len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ } LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); if (!pb) { return ERR_MEM; } LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME);#ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { PPPOE_ADD_16(p, l1); MEMCPY(p, sc->sc_service_name, l1); p += l1; } else#endif /* PPPOE_TODO */ { PPPOE_ADD_16(p, 0); } if (sc->sc_ac_cookie_len > 0) { PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); PPPOE_ADD_16(p, sc->sc_ac_cookie_len); MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); p += sc->sc_ac_cookie_len; } PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); PPPOE_ADD_16(p, sizeof(sc)); MEMCPY(p, &sc, sizeof sc); return pppoe_output(sc, pb);}/* send a PADT packet */static err_tpppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest){ struct pbuf *pb; struct eth_hdr *ethhdr; err_t res; u8_t *p; pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM); if (!pb) { return ERR_MEM; } LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); ethhdr = (struct eth_hdr *)pb->payload; ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr)); p = (u8_t*)(ethhdr + 1); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); res = outgoing_if->linkoutput(outgoing_if, pb); pbuf_free(pb); return res;}#ifdef PPPOE_SERVERstatic err_tpppoe_send_pado(struct pppoe_softc *sc){ struct pbuf *pb; u8_t *p; size_t len; if (sc->sc_state != PPPOE_STATE_PADO_SENT) { return ERR_CONN; } /* calc length */ len = 0; /* include ac_cookie */ len += 2 + 2 + sizeof(sc); /* include hunique */ len += 2 + 2 + sc->sc_hunique_len; pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); if (!pb) { return ERR_MEM; } LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); PPPOE_ADD_16(p, sizeof(sc)); MEMCPY(p, &sc, sizeof(sc)); p += sizeof(sc); PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); PPPOE_ADD_16(p, sc->sc_hunique_len); MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); return pppoe_output(sc, pb);}static err_tpppoe_send_pads(struct pppoe_softc *sc){ struct pbuf *pb; u8_t *p; size_t len, l1 = 0; /* XXX: gcc */ if (sc->sc_state != PPPOE_STATE_PADO_SENT) { return ERR_CONN; } sc->sc_session = mono_time.tv_sec % 0xff + 1; /* calc length */ len = 0; /* include hunique */ len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ l1 = strlen(sc->sc_service_name); len += l1; } pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); if (!pb) { return ERR_MEM; } LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME); if (sc->sc_service_name != NULL) { PPPOE_ADD_16(p, l1); MEMCPY(p, sc->sc_service_name, l1); p += l1; } else { PPPOE_ADD_16(p, 0); } PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); PPPOE_ADD_16(p, sc->sc_hunique_len); MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); return pppoe_output(sc, pb);}#endiferr_tpppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb){ u8_t *p; size_t len; /* are we ready to process data yet? */ if (sc->sc_state < PPPOE_STATE_SESSION) { /*sppp_flush(&sc->sc_sppp.pp_if);*/ pbuf_free(pb); return ERR_CONN; } len = pb->tot_len; /* make room for Ethernet header - should not fail */ if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) { /* bail out */ PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); LINK_STATS_INC(link.lenerr); pbuf_free(pb); return ERR_BUF; } p = (u8_t*)pb->payload + sizeof(struct eth_hdr); PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); return pppoe_output(sc, pb);}#if 0 /*def PFIL_HOOKS*/static intpppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir){ struct pppoe_softc *sc; int s; if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { return 0; } LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { if (sc->sc_ethif != ifp) { continue; } if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); printf("%c%c%"U16_F": ethernet interface detached, going down\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); } sc->sc_ethif = NULL; pppoe_clear_softc(sc, "ethernet interface detached"); } return 0;}#endifstatic voidpppoe_clear_softc(struct pppoe_softc *sc, const char *message){ LWIP_UNUSED_ARG(message); /* stop timer */ sys_untimeout(pppoe_timeout, sc); PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); /* fix our state */ sc->sc_state = PPPOE_STATE_INITIAL; /* notify upper layers */ sc->sc_linkStatusCB(sc->sc_pd, 0); /* clean up softc */ MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); sc->sc_ac_cookie_len = 0; sc->sc_session = 0;}#endif /* PPPOE_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -