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

📄 mp.c

📁 ppp协议实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	/* Insert new fragment before next element if possible. */	if (newfrag != NULL &&	    (nextf == NULL ||	     /* newseq < nextf->seq */	     ((newseq-nextf->seq) & sbit) != 0)) {	    newfrag->next = nextf;	    frag->next = nextf = newfrag;	    newfrag = NULL;	}	/* Check for start */	if (start != NULL) {	    if (start != frag && (frag->flags & MP_BEGIN)) {		syslog(LOG_NOTICE,"new BEGIN flag with no prior END");		while (start != frag) {		    nextf = start->next;		    free(start);		    start = nextf;		}		nextf = frag->next;		/* Packet has been dropped. */		link->frame_drops++;	    }	    /* If thisseq <= minseq */	} else if (((minseq-thisseq) & sbit) == 0) {	    if (frag->flags & MP_BEGIN)		start = frag;	    else {		syslog(LOG_NOTICE,"missing BEGIN; dropping %lu",thisseq);		if (frag->flags & MP_END)		    /* Packet has been dropped. */		    link->frame_drops++;		free(frag);		if ((frag = nextf) == NULL)		    break;		/* special case; have to allow for gaps here. */		goto nextfrag;	    }	}	if (start != NULL && (frag->flags & MP_END)) {	    /*	     * This next statement is not actually necessary, but can be	     * helpful in multitasking systems where delivery of a packet	     * may cause a task switch.	     */	    mp->frags = nextf;	    /* Reassemble packet into local buffer */	    bp = buffer;	    minseq = link->seq = (thisseq+1)&smask;	    while (start != nextf) {		frag = start->next;		if (bp != NULL && (bp-buffer)+start->length <= MAX_MRRU) {		    if (start->length > 0) {			memcpy(bp,start->data,start->length);			bp += start->length;		    }		} else		    bp = NULL;		free(start);		start = frag;	    }	    start = NULL;	    frag = NULL;	    /*	     * "bp" is used as a flag -- it's set to NULL when packet	     * is dropped.  At this point, it's null if the packet was	     * dropped due to MRRU.	     *	     * All reassembled and unfragmented data gets dispatched.	     */	    if (bp != NULL && bp > buffer+1) {		inlen = bp-buffer;		bp = buffer;		proto = *bp++;		inlen--;		if (!(proto & 1)) {		    proto = (proto << 8) | *bp++;		    inlen--;		}		/* Discard frames with illegal protocol fields or                   missing data. */		if (inlen <= 0 || (proto & 0x101) != 1)		    bp = NULL;		/*		 * If we're doing bundle level ECP, then we process it		 * first.  This is done to make the ECP code symmetric		 * with respect to the link level handling.		 */		if (bp != NULL && link->ecp_in_use && proto == PPP_PROTO_EP) {		    xcp = find_xcp(link,PPP_PROTO_EP);		    bp = ecp_decrypt(xcp,bp,&inlen);		    if (inlen < 1)			bp = NULL;		    if (bp != NULL) {			proto = *bp++;			inlen--;			if (!(proto & 1)) {			    if (inlen < 1)				bp = NULL;			    else {				proto = (proto << 8) | *bp++;				inlen--;			    }			}		    }		}		/*		 * If we're doing bundle level CCP, then we have to do it		 * before demultiplexing because CCP usually needs to inspect		 * all data.		 */		if (bp != NULL && link->ccp_in_use) {		    xcp = find_xcp(link,PPP_PROTO_CP);		    if (proto == PPP_PROTO_CP) {			bp = ccp_uncompress(xcp,bp,&inlen);			if (inlen < 1)			    bp = NULL;			if (bp != NULL) {			    proto = *bp++;			    inlen--;			    if (!(proto & 1)) {				if (inlen < 1)				    bp = NULL;				else {				    proto = (proto << 8) | *bp++;				    inlen--;				}			    }			}		    } else			ccp_uncompressed(xcp,proto,bp,inlen);		}		if (bp != NULL) {		    /* Dispatch to appropriate handler now. */		    xcp = find_xcp(link,proto);		    if (xcp != NULL)			(*xcp->handler)(xcp,bp,inlen);		    else {			/* No handler for this protocol, log it and                           reject it. */			send_lcp_protocol_reject(lptr,proto,bp,inlen);		    }		}	    }	    if (bp == NULL)		link->frame_drops++;	    mp->frags = NULL;	}	/*	 * If the next one is not contiguous then we don't have a complete	 * packet.	 */	if (nextf == NULL || ((thisseq+1)&smask) != nextf->seq) {	    if (frag == NULL)		;	    /* if thisseq < minseq */	    else if (((thisseq-minseq) & sbit) != 0) {		/* Packet has been dropped. */		syslog(LOG_DEBUG,"sequence %lu less than %lu",thisseq,minseq);		link->frame_drops++;		if (start != NULL)		    while (start != nextf) {			frag = start->next;			free(start);			start = frag;		    }		frag = NULL;	    } else if (mp->frags == NULL)		mp->frags = start;	    start = NULL;	} else {	    /* If we just reassembled and the next one is here, then do it. */	    if (frag == NULL) {		if (nextf->flags & MP_BEGIN)		    start = nextf;		else		    syslog(LOG_NOTICE,			   "END flag with no following BEGIN on %lu",			   nextf->seq);	    }	}	if (start == NULL && frag != NULL && mp->frags == NULL)	    mp->frags = frag;	frag = nextf;    }    if (mp->frags == NULL)	mp->frags = frag;}/* * This is called after a link goes through LCP and authentication, * but before any NCPs begin running.  If the link is part of a bundle, * then it is joined, otherwise a new bundle is created.  Assumes that * PPP MRRU has been negotiated. * * Returns pointer to link for bundle head. */struct ppp_link *find_bundle_head(struct ppp_link *newlink){    struct mp_state *mp;    struct xcp_state *xcp,*xcpp,*xcpn;    /* Search for matching bundle based on peer name and ED. */    for (mp = global_mp_list; mp != NULL; mp = mp->next)	if (((newlink->peername == NULL && mp->links->peername == NULL) ||	     (newlink->peername != NULL && mp->links->peername != NULL &&	      newlink->pn_size == mp->links->pn_size &&	      memcmp(newlink->peername,mp->links->peername,newlink->pn_size)	      == 0)) &&	    ((newlink->endpoint == NULL && mp->links->endpoint == NULL) ||	     (newlink->endpoint != NULL && mp->links->endpoint != NULL &&	      newlink->ep_size == mp->links->ep_size &&	      memcmp(newlink->endpoint,mp->links->endpoint,newlink->ep_size)	      == 0)))	    break;    /* If no such bundle exists, then create it now. */    if (mp == NULL) {	struct ppp_link *lptr;	mp = malloc(sizeof(*mp));	if (mp == NULL)	    return NULL;	memset(mp,'\0',sizeof(*mp));	mp->links = NULL;	mp->frags = NULL;	mp->next = global_mp_list;	global_mp_list = mp;	lptr = mp->lptr = create_ppp_link(NULL,NULL);	/* Everything but LCP and authentication moves to bundle level. */	xcpp = NULL;	for (xcp = newlink->xcp_list; xcp != NULL; xcpp = xcp, xcp = xcpn) {	    xcpn = xcp->next;	    if (xcp->proto < 0xC000 && xcp->proto != PPP_PROTO_ECP_LINK &&		xcp->proto != PPP_PROTO_CCP_LINK) {		if (xcpp != NULL)		    xcpp->next = xcp->next;		else		    newlink->xcp_list = xcp->next;		xcp->next = lptr->xcp_list;		lptr->xcp_list = xcp;		xcp->link = lptr;		xcp = xcpp;	    }	}	lptr->mp = mp;	/*	 * The MP defragmenter actually lives at the bundle level, since	 * all links actually demultiplex at the bundle level.	 */	lptr->handle = add_xcp(lptr,PPP_PROTO_MP,mp_handler,NULL);	lptr->link_output = mp_output;    } else {	/* Remove unwanted XCPs */	for (xcp = newlink->xcp_list; xcp != NULL; xcp = xcpn) {	    xcpn = xcp->next;	    if (xcp->proto < 0xC000 && xcp->proto != PPP_PROTO_ECP_LINK &&		xcp->proto != PPP_PROTO_CCP_LINK)		destroy_xcp(xcp);	}    }    /* Next output link must not be this new one unless it's the only one. */    if (mp->next_out_link == NULL)	mp->next_out_link = mp->links;    /* Attach the link to the bundle. */    newlink->seq = mp->lptr->seq;    newlink->next = mp->links;    mp->links = newlink;    mp->numlinks++;    newlink->mp = mp;    return mp->lptr;}/* * Add an XCP to a PPP link. */void *add_xcp(struct ppp_link *lptr, uint16 proto,	void (*handler)(struct xcp_state *xcp, octet *indata, int inlen),	void (*sender)(struct xcp_state *xcp, octet *indata, int inlen)){    struct xcp_state *xcp;    xcp = (struct xcp_state *)malloc(sizeof(*xcp));    if (xcp == NULL)	return NULL;    memset(xcp,'\0',sizeof(*xcp));    xcp->state = Initial;    xcp->proto = proto;    xcp->handler = handler;    xcp->send_data = sender;    xcp->link = lptr;    xcp->next = lptr->xcp_list;    lptr->xcp_list = xcp;    return (void *)xcp;}/* * Normal data sender for most NCP protocols. */voidgeneric_sender(struct xcp_state *xcp, octet *outdata, int outlen){    struct ppp_link *lptr = xcp->link;    (*lptr->link_output)(lptr,outdata,outlen,xcp->proto);}/* * This function creates a new PPP state structure for a single PPP * link.  The outhandler function will be called with the user's handle * (a blind pointer), a pointer to the data to send, and the length * of the data. */void *create_ppp_link(void *handle, void (*outhandler)(void *handle,						 octet *data,						 int datalen)){    struct ppp_link *lptr;    lptr = (struct ppp_link *)malloc(sizeof(*lptr));    if (lptr == NULL)	return NULL;    memset(lptr,'\0',sizeof(*lptr));    lptr->xcp_list = NULL;    lptr->handle = handle;    lptr->link_output = normal_output;    lptr->user_output = outhandler;    lptr->mtu = 1500;    lptr->mp = NULL;    if (add_xcp(lptr,PPP_PROTO_LCP,lcp_handler,generic_sender) == NULL) {	destroy_ppp_link((void *)lptr);	return NULL;    }    /* Other NCPs may be initialized here with add_xcp or added later. */    return (void *)lptr;}/* * Remove storage associated with an XCP. */voiddestroy_xcp(struct xcp_state *xcp){    struct ppp_link *lptr = xcp->link;    struct xcp_state *xcprev;    if (xcp == lptr->xcp_list)	lptr->xcp_list = xcp->next;    else {	for (xcprev = lptr->xcp_list; xcprev != NULL; xcprev =		 xcprev->next)	    if (xcprev->next == xcp) {		xcprev->next = xcp->next;		break;	    }    }    free(xcp);}/* * Delete an MP session. */static voiddestroy_mp(struct mp_state *mp){    struct mp_state *mlp;    struct mp_fragment *frag,*fragn;    if (global_mp_list == mp)	global_mp_list = mp->next;    else {	for (mlp = global_mp_list; mlp != NULL; mlp = mlp->next)	    if (mlp->next == mp) {		mlp->next = mp->next;		break;	    }    }    fragn = mp->frags;    while ((frag = fragn) != NULL) {	fragn = frag->next;	free(frag);    }    free(mp);}/* * Detach a link from an MP bundle and tear down the bundle if no * more links are active. */static voidmp_detach(struct ppp_link *link){    struct mp_state *mp = link->mp;    struct ppp_link *lp;    link->mp = NULL;    if (--mp->numlinks <= 0) {	destroy_mp(mp);	return;    }    if (mp->links == link)	mp->links = link->next;    else {	for (lp = mp->links; lp != NULL; lp = lp->next)	    if (lp->next == link) {		lp->next = link->next;		break;	    }    }    if (mp->next_out_link == link)	mp->next_out_link = NULL;}/* * Tear down a PPP link. */voiddestroy_ppp_link(void *link){    struct ppp_link *lptr = (struct ppp_link *)link;    struct xcp_state *xcp;    if (lptr->mp != NULL)	mp_detach(lptr);    while ((xcp = lptr->xcp_list) != NULL)	destroy_xcp(xcp);    free(lptr);}/* Only for testing purposes. */voidset_link_mtu(void *handle, int mtu){    struct ppp_link *lptr = (struct ppp_link *)handle;    lptr->mtu = mtu;}

⌨️ 快捷键说明

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