📄 pppipcp.c
字号:
int option_result; /* option reply */ uint desired = 0; /* desired to negotiate */ OptHdr option; /* option header storage */ /*-------------------------------------------------------------------*/ /* Attempt to allocate buffer. Return NULL if unable. */ /*-------------------------------------------------------------------*/ buf = tcpGetBuf(NIMHLEN + PPP_MTU + CRC16_LEN); if (buf == NULL) return -1; /*-------------------------------------------------------------------*/ /* Establish those options that need to reset. */ /*-------------------------------------------------------------------*/ ipcp->remote.options = 0; /* negotiation flags */ ipcp->remote.address = 0; /* remote IP address */ ipcp->remote.comp_proto = 0; /* compression protocol */ ipcp->remote.slots = 0; /* number of slots (0-n) */ ipcp->remote.comp_slot = 0; /* slots may be compressed (flag) */ /*-------------------------------------------------------------------*/ /* Process each option requested by the peer. */ /*-------------------------------------------------------------------*/ while ((signed_length > 0) && (pppRdOpt(&option) != -1)) { /*-----------------------------------------------------------------*/ /* Verify configuration header length is not too short. */ /*-----------------------------------------------------------------*/ if ((signed_length -= option.len) < 0) {#if PPP_TRACE pppLog("IPCP REQ: bad header length");#endif tcpRetBuf(&buf); return -1; } /*-----------------------------------------------------------------*/ /* Verify option value is acceptable and packet length is okay. */ /*-----------------------------------------------------------------*/ option_result = check_req_opt(&ipcp->remote, &option); if (option_result == -1) {#if PPP_TRACE pppLog("IPCP REQ: ran out of data");#endif tcpRetBuf(&buf); return -1; }#if PPP_TRACE pppLog("IPCP REQ: result=%s, option=%02X, length=%u", fsmCodes[option_result], option.type, option.len);#endif /*-----------------------------------------------------------------*/ /* If NAK reached, ignore ACK options. If REJ reached, ignore ACK */ /* and NAK options. */ /*-----------------------------------------------------------------*/ if (option_result < reply_result) { continue; } /*-----------------------------------------------------------------*/ /* On transition to NAK or REJ, discard current reply list. */ /*-----------------------------------------------------------------*/ else if (option_result > reply_result) { NetRstBuf(buf); reply_result = option_result; } /*-----------------------------------------------------------------*/ /* Remember those option requests we have received. */ /*-----------------------------------------------------------------*/ ipcp->remote.options |= (1 << option.type); /*-----------------------------------------------------------------*/ /* Add option response to the return list. */ /*-----------------------------------------------------------------*/ add_option(buf, &ipcp->remote, option.type); } /*-------------------------------------------------------------------*/ /* If remote address is 0 and we're not default GW, need IP_ADDRESS. */ /*-------------------------------------------------------------------*/ if ((ipcp->remote.address == 0) && !(Ppp->public.flags & PPPF_DEF_GW)) desired = IPCP_N_ADDRESS; /*-------------------------------------------------------------------*/ /* If not at NAK limit, append any missing options that are desired. */ /*-------------------------------------------------------------------*/ desired &= ~ipcp->remote.options; if ((fsm->rcn_cnt < fsm->pdc->nak_limit) && desired) { switch (reply_result) { case CONFIG_ACK: NetRstBuf(buf); reply_result = CONFIG_NAK; /*lint -fallthrough */ case CONFIG_NAK: make_opts(buf, &ipcp->remote, desired); break; case CONFIG_REJ: /* do nothing */ break; } } /*-------------------------------------------------------------------*/ /* Else if result is NAK and too many already sent, reject instead. */ /*-------------------------------------------------------------------*/ else if ((reply_result == CONFIG_NAK) && (fsm->rcn_cnt >= fsm->pdc->nak_limit)) { reply_result = CONFIG_REJ; } /*-------------------------------------------------------------------*/ /* Send ACK, NAK, or REJ to the peer. */ /*-------------------------------------------------------------------*/ pppFsmSend(fsm, reply_result, config->id, buf); return reply_result;}/***********************************************************************//* check_ack: Process configuration ACK sent by the peer *//* *//* Returns: 0 if acknowledgment is acceptable, else -1 *//* *//***********************************************************************/static int check_ack(FSM *fsm, ConfigHdr *config){ NetBuf *buf; int error = FALSE; /*-------------------------------------------------------------------*/ /* The ID field must match the last request we sent. */ /*-------------------------------------------------------------------*/ if (config->id != fsm->lastid) {#if PPP_TRACE pppLog("IPCP ACK: wrong ID");#endif return -1; } /*-------------------------------------------------------------------*/ /* Get a copy of the last request we sent. */ /*-------------------------------------------------------------------*/ buf = make_req(fsm); if (buf == NULL) return -1; /*-------------------------------------------------------------------*/ /* Overall buffer length should match. */ /*-------------------------------------------------------------------*/ if (config->len != buf->length) {#if PPP_TRACE pppLog("IPCP ACK: buffer length mismatch");#endif error = TRUE; } /*-------------------------------------------------------------------*/ /* Each byte should match. */ /*-------------------------------------------------------------------*/ else { int req_char; int ack_char; while ((req_char = pullchar(buf)) != -1) { ack_char = pullchar(pppRcvBuf); if (ack_char != req_char) {#if PPP_TRACE pppLog("IPCP ACK: data mismatch");#endif error = TRUE; break; } } } /*-------------------------------------------------------------------*/ /* Free temporarily allocated request buffer. */ /*-------------------------------------------------------------------*/ tcpRetBuf(&buf); /*-------------------------------------------------------------------*/ /* Return success or failure code. */ /*-------------------------------------------------------------------*/ if (error) return -1; else {#if PPP_TRACE pppLog("IPCP ACK: valid");#endif return 0; }}/***********************************************************************//* check_nak_opt: Check a NAKed option, updating its local value *//* *//* Inputs: local = negotiation parameters for local side *//* opt = pointer to received option header *//* *//* Returns: -1 if ran out of data, else 0 *//* *//* Note: Called by nak_check() to update our local values *//* *//***********************************************************************/static int check_nak_opt(IpcpOpts *local, OptHdr *opt){ int toss = opt->len - OPTION_HDR_LEN; int test; /*-------------------------------------------------------------------*/ /* Parse option type. */ /*-------------------------------------------------------------------*/ switch (opt->type) { case IPCP_COMPRESS: /*---------------------------------------------------------------*/ /* Read the peer's requested compression option. */ /*---------------------------------------------------------------*/ local->comp_proto = pull16(pppRcvBuf); toss -= 2;#if PPP_TRACE pppLog(" checking IP compression 0x%04X", local->comp_proto);#endif /*---------------------------------------------------------------*/ /* Check if requested type is acceptable. */ /*---------------------------------------------------------------*/ switch (local->comp_proto) { case PPP_COMP_PROTO: test = pullchar(pppRcvBuf); if (test == -1) return -1; local->slots = test + 1; if (local->slots < VJ_SLOT_LO) local->slots = VJ_SLOT_LO; else if (local->slots > VJ_SLOT_HI) local->slots = VJ_SLOT_HI; test = pullchar(pppRcvBuf); if (test == -1) return -1; local->comp_slot = test; if (local->comp_slot > 1) local->comp_slot = 1; toss -= 2;#if PPP_TRACE pppLog(" with IP compression slots %u, flag %X", local->slots, local->comp_slot);#endif break; default: local->comp_proto = PPP_COMP_PROTO; local->slots = VJ_SLOT_DEF; local->comp_slot = IPCP_COMP_SLOT; break; } break; case IPCP_ADDRESS: /*---------------------------------------------------------------*/ /* Read the peer's suggested IP address. */ /*---------------------------------------------------------------*/ local->address = pull32(pppRcvBuf); toss -= 4;#if PPP_TRACE pppLog(" checking IP src address %s", pppIps(local->address));#endif /*---------------------------------------------------------------*/ /* Override change if undesirable. */ /*---------------------------------------------------------------*/ if (Ppp->public.local_addr) local->address = Ppp->public.local_addr; break; default:#if PPP_TRACE pppLog("IPCP NAK: unknown option");#endif break; } /*-------------------------------------------------------------------*/ /* Return error if buffer ran out of data. */ /*-------------------------------------------------------------------*/ if (toss < 0) return -1; /*-------------------------------------------------------------------*/ /* Toss remaining bytes in option. */ /*-------------------------------------------------------------------*/ while (toss-- > 0) { if (pullchar(pppRcvBuf) == -1) return -1; } return 0;}/***********************************************************************//* nak_check: Process configuration NAK sent by peer *//* *//* Note: Update our config request to reflect NAKed options *//* *//***********************************************************************/static int nak_check(FSM *fsm, ConfigHdr *config){ IpcpCB *ipcp = &Ppp->ipcp; int signed_length = config->len; OptHdr option; int result; /*-------------------------------------------------------------------*/ /* The ID field must match the last request we sent. */ /*-------------------------------------------------------------------*/ if (config->id != fsm->lastid) {#if PPP_TRACE pppLog("IPCP NAK: wrong ID");#endif return -1; } /*-------------------------------------------------------------------*/ /* Process options in the order received. */ /*-------------------------------------------------------------------*/ while ((signed_length > 0) && (pppRdOpt(&option) != -1)) { /*-----------------------------------------------------------------*/ /* Verify configuration header length is not too short. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -