⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minimal-ppp.c

📁 ppp协议实现源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	printf("  %04X: ",i);	for (j = i; j < len && j < i+16; j++)	    printf(" %02X",buf[j]);	putchar('\n');    }}/* Print text string safely. */voidsafe_string(const unsigned char *bp, int len){    char chr;    putchar('"');    while (--len >= 0) {	chr = *bp++;	if (isascii(chr) && isprint(chr))	    putchar(chr);	else	    printf("\\%03o",chr);    }    putchar('"');}/* Show all options in negotiation message. */voidoption_show(const struct ppp_state *state,	    const struct ppp_xcp *xcp,	    const unsigned char *bp,	    int rlen){    int i;    const struct xcp_type *tp;    while (rlen > 0) {	putchar(' ');	if (rlen < 2) {	    printf("[trail %02X]\n",bp[0]);	    break;	}	if (bp[1] > rlen) {	    printf("[trunc %02X %d>%d]\n",bp[0],bp[1],rlen);	    break;	}	for (tp = xcp->types; tp->type != -1; tp++)	    if (tp->type == bp[0])		break;	if (tp->show != NULL) {	    /* Valid option; use defined printing routine */	    (*tp->show)(state,xcp,tp,bp+2,bp[1]);	} else {	    /* Undefined option; just dump contents. */	    if (tp->name == NULL)		printf("%02X:",bp[0]);	    else		printf("%s:",tp->name);	    for (i = 2; i < bp[1]; i++)		printf("%02X",bp[i]);	}	if ((i = bp[1]) < 2)	    i = 2;	rlen -= i;	bp += i;    }}/* * Show a negotiation packet. * Assumes 'bp' points to the code number (after PPP Protocol ID). */voidshow_neg_packet(const char *inout, const struct ppp_state *state,		const struct ppp_xcp *xcp,		const unsigned char *bp, int len){    int code, id, length;    code = *bp++;    id = *bp++;    length = (bp[0] << 8) + bp[1];    bp += 2;    if (len > length)	len = length;    len -= 4;    printf("%s %s ",inout,xcp->name);    if (code < Dim(code_str) && code_str[code] != NULL)	printf("%s",code_str[code]);    else	printf("code:%d",code);    printf(" ID:%d",id);    if ((code == CODE_CONF_ACK || code == CODE_CONF_NAK ||	 code == CODE_CONF_REJ || code == CODE_TERM_ACK ||	 code == CODE_ECHO_REP) && id != xcp->ident)	printf(" **ERR**");    printf(" len:%d",length);    switch (code) {    case CODE_CONF_REQ: case CODE_CONF_ACK:    case CODE_CONF_NAK: case CODE_CONF_REJ:	option_show(state,xcp,bp,len);	break;    case CODE_TERM_REQ: case CODE_TERM_ACK:	if (len > 0) {	    putchar(' ');	    safe_string(bp,len);	}	break;    case CODE_CODE_REJ:	printf(" code %d",*bp);	break;    case CODE_PROTO_REJ:	printf(" protocol %02X%02X",bp[0],bp[1]);	break;    case CODE_ECHO_REQ: case CODE_ECHO_REP:    case CODE_DISCARD_REQ:	if (len >= 4)	    printf(" magic %02X%02X%02X%02X",bp[0],bp[1],bp[2],bp[3]);	if (len > 4) {	    putchar(' ');	    safe_string(bp+4,len-4);	}	break;    }    putchar('\n');}/* * Write packet to tunnel.  Display contents if debugging. * (Wrapper around recalcitrant system call interface.) */voidppp_write(const struct ppp_state *state, const struct ppp_xcp *xcp,	  const unsigned char *buf, int len){    int retv,sock;    if (showraw)	buffer_print("Transmitting",buf,len);    if (showpackets) {	retv = buf[0] == 0xFF ? 2 : 0;	retv += buf[retv] & 1 ? 1 : 2;	show_neg_packet("SENT",state,xcp,buf+retv,len-retv);    }    sock = state->sock;    for (;;) {	retv = write(sock,buf,len);	if (retv < 0) {	    if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)		continue;	    perror("write");	    exit(1);	}	break;    }}/* * Insert HDLC Address/Control and PPP protocol fields. */unsigned char *set_up_acpf(unsigned char *buf, int proto){    buf[0] = 0xFF;    buf[1] = 0x03;    buf[2] = proto>>8;    buf[3] = proto&0xFF;    return buf+4;}/* * Set up buffer for a new message (Configure-Request, Protocol-Reject, * Echo-Request, or Discard-Request). */unsigned char *code_id(struct ppp_state *state, struct ppp_xcp *xcp, int code){    unsigned char *buf;    buf = set_up_acpf(state->upbuf,xcp->proto);    *buf++ = code;    *buf++ = ++xcp->ident;    *buf++ = 0;    *buf++ = 4;    return buf;}/* * Set up buffer for a reply to a previous message (Configure-Ack, * Configure-Nak, Configure-Reject, Echo-Reply). */unsigned char *code_reply(struct ppp_state *state, struct ppp_xcp *xcp, int code){    unsigned char *buf;    buf = set_up_acpf(state->upbuf,xcp->proto);    *buf++ = code;    *buf++ = state->inbuffer[5];    *buf++ = 0;    *buf++ = 4;    return buf;}/* * Find a given option in the list for an XCP. */struct option_state *find_option(const struct ppp_xcp *xcp, int type){    const struct xcp_type *tp;    for (tp = xcp->types; tp->type != -1; tp++)	if (tp->type == type)	    return xcp->opts+(tp-xcp->types);    return NULL;}/* * Loop over all known options and insert into a Configure-Request * being built. */voidcreate_request(struct ppp_state *state,	       struct ppp_xcp *xcp){    unsigned char *bp,*obp;    const struct xcp_type *tp;    struct option_state *os;    obp = bp = code_id(state,xcp,CODE_CONF_REQ);    for (tp = xcp->types, os = xcp->opts; tp->type != -1; tp++, os++) {	if (os->state == osUnusable)	    continue;	if (!tp->flag && os->my_value == tp->default_value)	    continue;	bp[0] = tp->type;	bp[1] = tp->minlen;	if (tp->minlen > 2)	    bp[2] = (os->my_value >> (8 * (tp->minlen-3))) & 0xFF;	if (tp->minlen > 3)	    bp[3] = (os->my_value >> (8 * (tp->minlen-4))) & 0xFF;	if (tp->minlen > 4)	    bp[4] = (os->my_value >> (8 * (tp->minlen-5))) & 0xFF;	if (tp->minlen > 5)	    bp[5] = os->my_value & 0xFF;	bp += bp[1];    }    *(unsigned short *)(obp - 2) = htons((bp-obp)+4);    state->up = bp;}/* * We've gotten a Configure-Request we like (RCR+), so we're agreeing * with the peer.  Set up to send Configure-Ack. */voidcopy_peer_values(const struct ppp_state *state,		 struct ppp_xcp *xcp){    const unsigned char *bp;    const struct xcp_type *tp;    struct option_state *os;    int rlen,val;    for (tp = xcp->types, os = xcp->opts; tp->type != -1; tp++, os++)	os->peer_value = tp->default_value;    bp = state->bp;    rlen = state->mlen;    while (rlen > 0) {	for (tp = xcp->types; tp->type != -1; tp++)	    if (tp->type == bp[0])		break;	os = xcp->opts + (tp-xcp->types);	val = bp[2];	if (bp[1] > 3)	    val = (val << 8) + bp[3];	if (bp[1] > 4)	    val = (val << 8) + bp[4];	if (bp[1] > 5)	    val = (val << 8) + bp[5];	os->peer_value = val;	rlen -= bp[1];	bp += bp[1];    }}/* * Perform RFC 1661 actions as indicated by state machine. */voiddispatch_action(struct ppp_state *state,		struct ppp_xcp *xcp,		enum xcp_action act){    unsigned char *bp;    if (act == acNull)	return;    if (debugactions)	printf("%s action %s (%d)\n",xcp->name,ac_str[(int)act],(int)act);    switch (act) {    case acNull:	break;    case acIrc:	xcp->restart = state->phase == phTerminate ? MAX_TERMINATE :	    MAX_CONFIGURE;	state->timeout_period = INITIAL_TIMEOUT;	break;    case acScr:	if (xcp->restart > 0) {	    xcp->restart--;	    create_request(state,xcp);	    ppp_write(state,xcp,state->upbuf,state->up-state->upbuf);	}	xcp->restart_point = time(NULL)+state->timeout_period;	break;    case acTls:	if (xcp == &state->xcps[XCP_IPCP])	    send_event(state,&state->xcps[XCP_LCP],evOpen);	else	    change_phase(state,phEstablish);	break;    case acTlf:	if (xcp == &state->xcps[XCP_IPCP])	    send_event(state,&state->xcps[XCP_LCP],evClose);	else	    change_phase(state,phTerminate);	break;    case acStr:	if (xcp->restart > 0) {	    xcp->restart--;	    bp = code_id(state,xcp,CODE_TERM_REQ);	    ppp_write(state,xcp,state->upbuf,bp-state->upbuf);	}	xcp->restart_point = time(NULL)+state->timeout_period;	break;    case acSta:	bp = code_reply(state,xcp,CODE_TERM_ACK);	ppp_write(state,xcp,state->upbuf,bp-state->upbuf);	break;    case acSca:	copy_peer_values(state,xcp);	state->inbuffer[4] = CODE_CONF_ACK;	ppp_write(state,xcp,state->inbuffer,		  state->mlen+(state->bp-state->inbuffer));	break;    case acScn:	if (xcp->naks_sent++ >= MAX_FAILURE)	    state->upbuf[4] = CODE_CONF_REJ;    case acScj:	ppp_write(state,xcp,state->upbuf,state->up-state->upbuf);	break;    case acTld:	if (xcp == &state->xcps[XCP_LCP])	    change_phase(state,phTerminate);	else	    printf("IPCP is now down!\n");	break;    case acTlu:	if (xcp == &state->xcps[XCP_LCP])	    change_phase(state,phAuthenticate);	else {	    struct option_state *os = find_option(xcp,3);	    struct in_addr addr;	    addr.s_addr = htonl(os->my_value);	    printf("IPCP is now up!  Local address %s, ",		   inet_ntoa(addr));	    addr.s_addr = htonl(os->peer_value);	    printf("remote %s\n",inet_ntoa(addr));	}	xcp->restart = MAX_CONFIGURE;	xcp->restart_point = 0;	break;    case acZrc:	xcp->restart = 0;	state->timeout_period = INITIAL_TIMEOUT;	break;    case acSer:	state->inbuffer[4] = CODE_ECHO_REP;	*(long *)(state->inbuffer+8) = htonl(state->mymagic);	ppp_write(state,xcp,state->inbuffer,		  state->mlen+(state->bp-state->inbuffer));	break;    }}/* * Issue event into XCP state machine -- go to next state and * invoke associated actions. */voidsend_event(struct ppp_state *state,	   struct ppp_xcp *xcp,	   enum ppp_event event){    const struct ppp_dispatch *dp;    dp = &ppp_dispatch[(int)xcp->state][(int)event];    if (dp->next == stNoChange) {	if (debugstates)	    printf("%s got illegal %s event (%d) in %s state (%d)\n\\t(RFC 1661 section 4.4)\n",		   xcp->name,ev_str[(int)event],event,		   st_str[(int)xcp->state],xcp->state);    } else {	if (debugstates)	    printf("%s got %s event (%d) in %s state (%d), next is %s state (%d)\n",		   xcp->name,ev_str[(int)event],event,		   st_str[(int)xcp->state],xcp->state,		   st_str[(int)dp->next],dp->next);	xcp->state = dp->next;    }    dispatch_action(state,xcp,dp->act[0]);    dispatch_action(state,xcp,dp->act[1]);    dispatch_action(state,xcp,dp->act[2]);}/* * Change overall link phase.  Central routine helps with * debugging. */voidchange_phase(struct ppp_state *state,	     enum ppp_phase phase){    if (debugphases)	printf("Current PPP phase is %s, switching to %s\n",	       ph_str[(int)state->phase],ph_str[(int)phase]);    switch (phase) {    case phEstablish:	if (state->phase == phDead)	    send_event(state,&state->xcps[XCP_LCP],evUp);	break;    case phAuthenticate:	break;    case phNetwork:	if (state->phase == phAuthenticate)	    send_event(state,&state->xcps[XCP_IPCP],evUp);	break;    case phTerminate:	send_event(state,&state->xcps[XCP_IPCP],evDown);	break;    case phDead:	break;    }    state->phase = phase;    if (phase == phAuthenticate)	change_phase(state,phNetwork);		/* XXX - no auth yet */}/* * Main loop.  Handle timers and packet input. */voidread_packets(struct ppp_state *state){    unsigned char *bp;    int retv,proto,i,rcvd_anything,alarm_running;    struct timeval tv,*tvp;    fd_set rfd;    struct ppp_xcp *minsel;    time_t now;    rcvd_anything = 0;    alarm_running = 0;    for (;;) {	/* Find earliest timer expiry. */	tvp = NULL;	tv.tv_sec = 1000;	tv.tv_usec = 0;	minsel = NULL;	now = time(NULL);	for (i = 0; i < Dim(state->xcps); i++)	    if (state->xcps[i].restart_point != 0) {		if (now > state->xcps[i].restart_point) {		    tv.tv_sec = 0;		} else if (now+tv.tv_sec > state->xcps[i].restart_point) {		    tv.tv_sec = state->xcps[i].restart_point-now;		} else		    continue;		minsel = state->xcps+i;		tvp = &tv;	    }	/* If all NCPs up, then cancel main alarm. */	if (minsel == NULL) {	    alarm_running = 0;	    alarm(0);	} else if (!alarm_running) {	    /*	     * If NCP negotiation (re)started, then set alarm.  This	     * acts as an overall time limit on negotiation.  If it	     * takes longer than MAX_WAIT, then give up.	     */	    alarm_running = 1;	    alarm(MAX_WAIT);	}	if (debugtimer) {	    if (minsel == NULL)		printf("No timers running.\n");	    else		printf("Timer set for %d seconds.\n",tv.tv_sec);	}	/* Wait for something. */	FD_ZERO(&rfd);	FD_SET(state->sock,&rfd);	retv = select(state->sock+1,&rfd,NULL,NULL,tvp);	/* Check for timer events. */	if (retv >= 0 && minsel != NULL) {	    if (retv == 0 && state->timeout_period < MAX_TIMEOUT)		state->timeout_period <<= 1;	    now = time(NULL);	    for (i = 0; i < Dim(state->xcps); i++)		if (state->xcps[i].restart_point == 0)		    ;		else if (now >= state->xcps[i].restart_point) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -