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

📄 minimal-ppp.c

📁 ppp协议实现源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		    if (retv == 0) {			state->xcps[i].restart_point = 0;			/* Hack -- send with same ID on timeout. */			if (state->xcps[i].restart > 0)			    state->xcps[i].ident--;			if (debugtimer)			    printf("Sending TO%c to %s\n",				   state->xcps[i].restart > 0 ? '+' : '-',				   state->xcps[i].name);			send_event(state,state->xcps+i,				   state->xcps[i].restart > 0 ? evTOp : evTOm);		    } else /* Hack. */			state->xcps[i].restart_point = now+1;		}	    /* If nothing waiting, then no need to read. */	    if (retv == 0)		continue;	}	/* Fetch input packet */	if (retv > 0)	    retv = read(state->sock,state->inbuffer,sizeof(state->inbuffer));	if (retv <= 0) {	    /* Wait for UDP peer to come up at least once. */	    if (errno == ECONNREFUSED && !rcvd_anything)		continue;	    /* Ignore interrupt nonsense. */	    if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)		continue;	    if (retv < 0)		perror("read");	    break;	}	if (showraw)	    buffer_print("Received",state->inbuffer,retv);	rcvd_anything = 1;	/* ACFC would go here. */	if (state->inbuffer[0] != 0xFF || state->inbuffer[1] != 0x03) {	    printf("Bad address and control field %02X %02X.\n",		   state->inbuffer[0],state->inbuffer[1]);	    continue;	}	/* PFC would go here. */	if ((state->inbuffer[2] & 1) != 0 || (state->inbuffer[3] & 1) == 0) {	    printf("Bad protocol field %02X %02X.\n",		   state->inbuffer[2],state->inbuffer[3]);	    continue;	}	/* Find XCP for indicated protocol */	proto = ntohs(*(unsigned short *)(state->inbuffer+2));	for (i = 0; i < Dim(state->xcps); i++)	    if (state->xcps[i].proto == proto)		break;	if (i >= Dim(state->xcps)) {	    /* Generate LCP Protocol-Reject for unknown things. */	    printf("Unknown protocol %04X\n",proto);	    if (state->xcps[XCP_LCP].state == stOpened) {		bp = code_id(state,&state->xcps[XCP_LCP],			     CODE_PROTO_REJ);		i = sizeof(state->upbuf) - (bp-state->upbuf);		retv -= 2;		if (retv > i)		    retv = i;		memcpy(bp,state->inbuffer+2,retv);		retv += bp-state->upbuf;		*(unsigned short *)(state->upbuf+2) = htons(retv-4);		ppp_write(state,&state->xcps[XCP_LCP],state->upbuf,retv);	    }	    continue;	}	/* Remove HDLC headers and PPP Protocol Field and deliver */	state->bp = state->inbuffer+4;	state->mlen = retv-4;	(*state->xcps[i].deliver)(state,state->xcps+i);    }}/* * Add current option to list of options to be sent in Configure-Reject. */voidset_reject(struct ppp_state *state,	   struct ppp_xcp *xcp,	   const unsigned char *bp){    int i;    if (state->parse_state == psBad)	return;    /* If this is the first reject for this packet, then set up. */    if (state->parse_state != psRej) {	state->up = code_reply(state,xcp,CODE_CONF_REJ);	state->parse_state = psRej;    }    /*     * Handle malformed options; make sure we don't send anything illegal     * to the peer (even if he's sending us junk).     */    if ((i = bp[1]) < 2)	i = 2;    memcpy(state->up,bp,i);    state->up[1] = i;    state->up += i;}/* * Add current option to list of options to be sent in Configure-Nak. */voidset_nak(struct ppp_state *state,	struct ppp_xcp *xcp,	int type, int len,	const unsigned char *bp){    /* If we're rejecting, then no point in doing naks. */    if (state->parse_state == psBad || state->parse_state == psRej)	return;    /* If this is the first nak for this packet, then set up. */    if (state->parse_state != psNak) {	state->up = code_reply(state,xcp,CODE_CONF_NAK);	state->parse_state = psNak;    }    *state->up++ = type;    *state->up++ = len;    while (--len > 1)	*state->up++ = *bp++;}/* * Check Configure-Request options from peer against list of * known, valid, and desired options. */intvalidate_request(struct ppp_state *state,		 struct ppp_xcp *xcp){    int rlen,i;    const unsigned char *bp;    const struct xcp_type *tp;    state->parse_state = psOK;    rlen = state->mlen;    bp = state->bp;    while (rlen > 0) {	if (rlen < 2 || bp[1] > rlen) {	    state->parse_state = psBad;	    break;	}	for (tp = xcp->types; tp->type != -1; tp++)	    if (tp->type == bp[0])		break;	if (tp->type == -1)	    set_reject(state,xcp,bp);	else if (bp[1] < tp->minlen)	    set_nak(state,xcp,tp->type,tp->minlen,bp+2);	else if (bp[1] > tp->maxlen)	    set_nak(state,xcp,tp->type,tp->maxlen,bp+2);	else if (tp->validate_req == NULL)	    ;	else	    (*tp->validate_req)(state,xcp,tp,bp+2,bp[1]);	if ((i = bp[1]) < 2)	    i = 2;	rlen -= i;	bp += i;    }    if (state->parse_state == psNak || state->parse_state == psRej) {	i = (state->up - state->upbuf) - 4;	state->upbuf[6] = (i >> 8) & 0xFF;	state->upbuf[7] = i & 0xFF;    }    return state->parse_state == psOK;}/* * Process options in a Configure-{Ack,Nak,Reject}. */voidprocess_rcx(struct ppp_state *state,	    struct ppp_xcp *xcp,	    unsigned char code){    int rlen,i,val;    unsigned char *bp;    const struct xcp_type *tp;    struct option_state *os;    rlen = state->mlen;    bp = state->bp;    while (rlen > 0) {	if (rlen < 2 || bp[1] > rlen)	    break;	for (tp = xcp->types; tp->type != -1; tp++)	    if (tp->type == bp[0])		break;	if (tp->type != -1) {	    os = xcp->opts + (tp-xcp->types);	    if (code == CODE_CONF_REJ)		os->state = osUnusable;	    else if (code == CODE_CONF_ACK || tp->validate_nak == NULL) {		if (bp[1] > 6 || bp[1] <= 2)		    os->my_value = tp->default_value;		else {		    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->my_value = val;		}	    } else		(*tp->validate_nak)(state,xcp,tp,bp+2,bp[1]);	}	if ((i = bp[1]) < 2)	    i = 2;	rlen -= i;	bp += i;    }}/* * Standard negotiation entry point.  This is assigned as the * 'delivery' function for control protocols, like LCP and IPCP. */voidstd_negotiation(struct ppp_state *state,		struct ppp_xcp *xcp){    unsigned char code,id;    unsigned short proto;    int i,length;    /* Validate overall message length */    if (state->mlen < 4) {	printf("Malformed negotiation message; %d < 4\n",	       state->mlen);	return;    }    code = *state->bp++;    id = *state->bp++;    length = (state->bp[0] << 8) + state->bp[1];    if (length > state->mlen) {	printf("Truncated negotiation message; %d > %d\n",	       length,state->mlen);	return;    }    if (length < state->mlen) {	printf("Trimmed negotiation message; %d < %d\n",	       length,state->mlen);	state->mlen = length;    }    state->bp += 2;    state->mlen -= 4;    if (showpackets) {	show_neg_packet("RCVD",state,xcp,state->bp-4,state->mlen+4);    }    /* Now switch out on received code number */    switch (code) {    case CODE_CONF_REQ:	/* If request is good, then RCR+, if bad, then RCR- */	if (validate_request(state,xcp))	    send_event(state,xcp,evRCRp);	else	    send_event(state,xcp,evRCRm);	break;    case CODE_CONF_ACK:	/* Configure-Ack ID number must match last sent. */	if (id != xcp->ident)	    break;	/* Should validate contents against last req sent, but we don't. */	process_rcx(state,xcp,code);	send_event(state,xcp,evRCA);	break;    case CODE_CONF_NAK:    case CODE_CONF_REJ:	/* Configure-Nak/Reject ID number must match last sent. */	if (id != xcp->ident)	    break;	process_rcx(state,xcp,code);	send_event(state,xcp,evRCN);	break;    case CODE_TERM_REQ:	send_event(state,xcp,evRTR);	break;    case CODE_TERM_ACK:	if (id != xcp->ident)	    break;	send_event(state,xcp,evRTA);	break;    case CODE_CODE_REJ:	code = *state->bp++;	/* Peer cannot reject well-known code numbers. */	if (code != 0 && code < CODE_ECHO_REQ) {	    printf("Invalid code reject for %d\n",code);	    send_event(state,xcp,evRXJm);	} else	    send_event(state,xcp,evRXJp);	break;    case CODE_PROTO_REJ:	proto = (state->bp[0] << 8) + state->bp[1];	/* Peer cannot reject LCP! */	if (proto == state->xcps[XCP_LCP].proto) {	    printf("Peer protocol-rejected LCP itself!\n");	    send_event(state,&state->xcps[XCP_LCP],evRXJm);	} else {	    send_event(state,xcp,evRXJp);	    for (i = 0; i < Dim(state->xcps); i++)		if (state->xcps[i].proto == proto)		    state->xcps[i].state = stInitial;	}	break;    case CODE_ECHO_REQ:	/* Should be sending a reply here. */    case CODE_DISCARD_REQ:	send_event(state,xcp,evRXR);	break;    case CODE_ECHO_REP:	/* ID number in Echo-Reply must match last echo sent. */	if (id != xcp->ident)	    break;	send_event(state,xcp,evRXR);	break;    default:	state->bp -= 4;	send_event(state,xcp,evRUC);	break;    }}/* * Initialize an XCP (LCP or NCP). */voidinit_xcp(const char *name, struct ppp_xcp *xcp,	 void (*deliver)(struct ppp_state *state,			 struct ppp_xcp *xcp),	 const struct xcp_type *types,	 int ntypes,	 unsigned short proto){    struct option_state *os;    xcp->name = name;    xcp->state = stInitial;    xcp->restart = 0;    xcp->restart_point = 0;    xcp->deliver = deliver;    xcp->types = types;    xcp->proto = proto;    /* If no options, then no vector to store negotiated values. */    if (ntypes <= 0) {	xcp->opts = NULL;	return;    }    /* Otherwise, allocate vector and initialize options */    os = xcp->opts = (struct option_state *)	malloc(ntypes*sizeof(struct option_state));    while (--ntypes >= 0) {	os->my_value = os->peer_value = types->default_value;	os->state = osUsable;	os++;	types++;    }}/* * Initialize PPP state machine and add LCP and IPCP. */voidset_up_ppp(struct ppp_state *state, int sock){    state->phase = phDead;    state->sock = sock;    state->timeout_period = INITIAL_TIMEOUT;    init_xcp("LCP",&state->xcps[XCP_LCP],std_negotiation,lcp_types,	     Dim(lcp_types)-1,PROT_LCP);    init_xcp("IPCP",&state->xcps[XCP_IPCP],std_negotiation,ipcp_types,	     Dim(ipcp_types)-1,PROT_IPCP);}/* * Handle Configure-Request from peer.  If it's in the range we think * it should be, then do nothing (allow Configure-Ack).  Otherwise, * send Configure-Nak with something more appropriate. */voidipcp_addr_req(struct ppp_state *state,	      struct ppp_xcp *xcp,	      const struct xcp_type *tp,	      const unsigned char *buf,	      int len){    int addr;    unsigned char lbuf[4];    struct option_state *os;    addr = (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + buf[3];    os = xcp->opts + (tp-xcp->types);    if (addr != os->my_value &&	(addr & remote_ip_mask) == remote_ip_base)	return;    addr = xcp->opts[tp-xcp->types].peer_value;    lbuf[0] = (addr >> 24) & 0xFF;    lbuf[1] = (addr >> 16) & 0xFF;    lbuf[2] = (addr >> 8) & 0xFF;    lbuf[3] = addr & 0xFF;    set_nak(state,xcp,tp->type,tp->minlen,lbuf);}/* * Got a Configure-Nak of our address.  Just change; we're flexible. */voidipcp_addr_nak(struct ppp_state *state,	      struct ppp_xcp *xcp,	      const struct xcp_type *tp,	      const unsigned char *buf,	      int len){    xcp->opts[tp-xcp->types].my_value =	(buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + buf[3];}/* * Show address. */voidipcp_addr_show(const struct ppp_state *state,	       const struct ppp_xcp *xcp,	       const struct xcp_type *tp,	       const unsigned char *buf,	       int len){    struct in_addr addr;    addr.s_addr = (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + buf[3];    printf("%s",inet_ntoa(addr));}/* * Set local value (for Configure-Request). */voidset_option_value_lcl(struct ppp_xcp *xcp, int type, int value){    struct option_state *os;    if ((os = find_option(xcp,type)) != NULL)	os->my_value = value;}/* * Set desired value for peer (we'll Configure-Nak with this). */voidset_option_value_rem(struct ppp_xcp *xcp, int type, int value){    struct option_state *os;    if ((os = find_option(xcp,type)) != NULL)	os->peer_value = value;}intmain(argc,argv)int argc;char **argv;{    int sock,i;    struct ppp_state mystate;    myname = argv[0];    while ((i=getopt(argc,argv,"adpstv")) != EOF)	switch (i) {	case 'a':	    debugactions++;	    break;	case 'd':	    showraw++;	    break;	case 'p':	    debugphases++;	    break;	case 's':	    debugstates++;	    break;	case 't':	    debugtimer++;	    break;	case 'v':	    showpackets++;	    break;	case '?':	    usage();	    return 1;	}    if ((sock = set_up_tunnel(argv+optind)) < 0) {	usage();	return 1;    }    /* Request that IPCP go open! */    set_up_ppp(&mystate,sock);    /* Set some random addresses to try */    srand(getpid());    set_option_value_lcl(&mystate.xcps[XCP_IPCP],3,0x0A000000+(rand()%1000));    set_option_value_rem(&mystate.xcps[XCP_IPCP],3,0x0A00000A+(rand()%1000));    /* Tell LCP to open */    send_event(&mystate,&mystate.xcps[XCP_IPCP],evOpen);    signal(SIGALRM,alarm_handle);    read_packets(&mystate);    return 0;}

⌨️ 快捷键说明

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