?? mp.c
字號:
#include "net.h"
#include "local.h"
#include "support.h"
#include "ppp.h"
#define MP_START 0x80 /* Start of Multilink reconstructed frame */
#define MP_END 0x40 /* End of Multilink reconstructed frame */
struct MPbundle {
char linkno;
char addclass;
char addlen;
char addr[20];
unsigned long rxseq;
unsigned long txseq;
MESS *queue;
};
/* Each interface has a bundle that it belongs to. */
static char MPno[NNETS];
/*
** Potentially, each interface could be using PPP with Multi-link
** and not bundle. This makes for NNETS possible bundles.
*/
static struct MPbundle MPbundle[NNETS];
/*
** * * * * * *
** mpInit() Put Multilink in its default state
**
** void mpInit(int netno)
**
** PARAMETERS:
** (in) int netno A network number
**
** DESCRIPTION:
** This function will place the Multilink Protocol for yfnet in its default
** state so that negotiations may proceed correctly on a particular link.
** * * * * * *
*/
void mpInit(int netno)
{
memset((char *)&MPbundle[netno], 0, sizeof(MPbundle[netno]));
MPno[netno] = -1;
}
/*
** * * * * * *
** mpShut() Make Multilink not ready on a link
**
** void mpShut(int netno);
**
** PARAMETERS:
** (in) int netno A network number
**
** DESCRIPTION:
** This function will stop the Multilink protocol on a particular link.
**
*/
void mpShut(int netno)
{
MPno[netno] = -1;
}
/*
** * * * * * *
** mpStart() Make MP ready to negotiate
**
** void mpStart(int netno);
**
** PARAMETERS:
** (in) int netno A network number
**
** DESCRIPTION:
** This function will
** * * * * * *
*/
void mpStart(int netno)
{
nets[netno].hw.opt5 = MPmrru | MPendd;
MPno[netno] = -1;
}
/*
** * * * * * *
** mpFindBundle() Find or create an MP bundle
**
** int mpFindBundle(int netno, int addclass, int addlen, char *addr);
**
** PARAMETERS:
** (in) int netno A network number
** (in) int addclass The class of the bundle
** (in) int addlen The length of the bundle name
** (in) char *addr The bundle name
**
** RETURNS
** # The MP bundle number
**
** DESCRIPTION:
** This function will find an MP bundle to associate this link with.
** If it cannot find an appropriate bundle in existance, it will
** create one.
** * * * * * *
*/
int mpFindBundle(int netno, int addclass, int addlen, char *addr)
{
int i1, i2, i3, new;
struct MPbundle *MPptr;
new = 1;
BLOCKPREE();
for (i1=0,i2=-1; i1<NNETS; i1++) {
MPptr = &MPbundle[i1];
for (i3=0; i3<NNETS; i3++)
if (MPno[i3] == i1)
goto lab26;
i2 = i1;
continue;
lab26:
if (MPptr->addclass == addclass &&
MPptr->addlen == addlen &&
memcmp(MPptr->addr, addr, i1) == 0)
{
i2 = i1;
new = 0;
break;
}
}
MPno[netno] = (char)i2;
if (i2 != -1) {
MPptr = &MPbundle[i2];
if (new) {
MPptr->txseq = MPptr->rxseq = 0;
MPptr->addclass = (char)addclass;
MPptr->addlen = (char)addlen;
Nmemcpy(MPptr->addr, addr, addlen);
}
}
RESUMEPREE();
return i2;
}
/*
** * * * * * *
** mpScreen() Screen an MP fragment
**
** int mpScreen(MESS *mess);
**
** PARAMETERS:
** (in/out) MESS *mess A message buffer (MP fragment)
**
** RETURNS
** protocol PPP protocol packet to process
** 0 Got a fragment
** -1 Failure, reject packet
**
** DESCRIPTION:
** This function will receive either fragmented or unfragmented MP frames.
**
** * * * * * *
*/
int mpScreen(MESS *mess)
{
int i1, i2, i3, i4, netno;
unsigned short protocol;
unsigned char *cp, *cp2;
unsigned long ul1;
MESS *mp, *mp3;
struct MPbundle *MPptr;
struct NET *netp;
union {unsigned char c[4]; short s[2]; long l;} UL;
netno = mess->netno;
netp = &nets[netno];
if ((netp->hw.opt5 & MPmrru) == 0)
return -1;
cp = (unsigned char *)mess + mess->offset;
MPptr = &MPbundle[MPno[netno]];
/* Get start/stop flags */
i1 = *cp & (MP_START | MP_END);
/* Get fragment sequence number */
if (netp->hw.opt5 & MPsnhf) {
ul1 = *cp++ & 0xf; /* |B|E|0|0| sequence number | */
}
else {
cp++;
ul1 = *cp++; /* |B|E|0|0|0|0|0|0|sequence number| */
ul1 = ul1 << 8 + *cp++; /* | sequence number (L) | */
}
ul1 = ul1 << 8 + *cp++;
MPptr->rxseq = ul1;
/*
** If the protocol value is 0xff03, the peer is probably sending the
** address and control fields from the AHDLC frame in the MP packet.
** The solution is to strip those values here. However, if the peer
** also encapsulates the checksum, we cannot handle that very easily.
** Perhaps the end of the message - 2 will be the location of the
** extra checksum. The normal checksum would be at the end of the
** message.
*/
if (cp[0] == 0xff && cp[1] == 0x03)
cp += 2;
/* Get protocol value of fragment (Multilink data field) */
UL.c[0] = *cp++;
#if COMPRESSION & 1
if ((netp->hw.remopts & COMPpcmp) && (UL.c[0] & 1)) {
UL.c[1] = UL.c[0];
UL.c[0] = 0;
}
else
#endif
UL.c[1] = *cp++;
protocol = UL.s[0];
/*
** Move start fragment to fixed network data location if necessary.
**
** cp2 points to the start of the network data and the network data
** needs to be at mess + MESSH_SZ + LHDRSZ. The input routine (comec)
** should handle the alignment, but if the peer does not correctly
** format their fragment due to inconsistant protocol compression or
** incorrect address/control insertion, we must adjust.
*/
i2 = cp - (unsigned char *)mess - MESSH_SZ - LHDRSZ;
if (i1 & MP_START && i2) {
#if NTRACE >= 7
Nprintf("PPP MP: Packet adjusted [%d]\n", i2);
#endif
mess->mlen -= i2;
cp2 = (unsigned char *)mess + MESSH_SZ + LHDRSZ;
i2 = mess->mlen - MESSH_SZ - LHDRSZ;
if (cp > cp2)
while (i2--)
*cp2++ = *cp++;
else
while (i2--)
*cp++ = *cp2++;
PH(mess)->protocol = protocol;
}
/* Save important values in the link layer header */
PH(mess)->MPflags = i1;
PH(mess)->bseqno = PH(mess)->eseqno = (short)ul1;
mess->timems = TimeMS();
/*
** Scan MP fragment queue and find the fragment before and after
** the current one based on the sequence number.
*/
mp3 = (MESS *)&MPptr->queue;
for (i2=0, mp = mp3->next; mp; i2++, mp3 = mp, mp = mp->next)
if (PH(mp)->bseqno - (short)ul1 > 0)
break;
/* If the packet is a new fragment */
if (i1 & MP_START)
goto newpacket;
/* Otherwise, the packet must be prepended/appended to another */
i3 = 0;
if (i2 == 0)
goto lab11;
/* Append new data */
if ((short)ul1 - PH(mp3)->eseqno == 1) {
i4 = mess->mlen - MESSH_SZ - LHDRSZ;
if (mp3->mlen + i4 > MAXBUF)
return -1;
i3 = 1;
Nmemcpy((char *)mp3+mp3->mlen, (char *)mess+MESSH_SZ+LHDRSZ, i4);
mp3->mlen += i4;
PH(mp3)->eseqno = (short)ul1;
PH(mp3)->MPflags |= i1;
mess = mp3;
}
lab11:
if (mp == 0)
goto lab12;
/* Prepend new data */
if (PH(mp)->bseqno - (short)ul1 == 1) {
i4 = mp->mlen - MESSH_SZ - LHDRSZ;
if (mess->mlen + i4 > MAXBUF)
return -1;
i3 |= 2;
Nmemcpy((char *)mess+mess->mlen, (char *)mp+MESSH_SZ+LHDRSZ, i4);
mess->mlen += i4;
PH(mess)->eseqno++;
PH(mess)->MPflags |= PH(mp)->MPflags;
mess->next = mp->next;
Nrelbuf(mp);
}
lab12:
if (i3 == 0) {
newpacket:
if (i2 > MPBUF)
return -1;
mp3->next = mess;
mess->next = mp;
}
/*
** If the top of queue is a whole packet, unqueue and use it.
**
** If all member links of the bundle have overshot the missing sequence
** number for a fragment packet, assume that it will never be completed
** and discard it.
**
** ul1 is the running minimum sequence number.
*/
for (i1 = 0; i1 < NNETS; i1++) {
i3 = MPno[i1];
if (i3 != -1 && i3 == MPno[netno])
if (ul1 - MPbundle[i3].rxseq > 0)
ul1 = MPbundle[i3].rxseq;
}
mp3 = (MESS *)&MPptr->queue; /* scan the queue */
for (mp = mp3->next; mp; mp3 = mp,mp = mp->next) {
/* If a reconstructed frame is found, return the protocol */
if ((PH(mp)->MPflags & (MP_START | MP_END)) == (MP_START | MP_END)) {
mp3->next = mp->next;
return protocol;
}
if ((short)ul1 - PH(mp)->eseqno <= 0)
break;
mp3->next = mp->next;
Nrelbuf(mp);
}
return 0; /* No reconstructed packets to return */
}
/*
** * * * * * *
** mpWrite() Write a Multilink packet
**
** int mpWrite(int netno, unsigned char **cpp);
**
** PARAMETERS:
** (in) int netno A network number
** (in/out) char **cpp A pointer to the packet head pointer
**
** RETURNS
** # The network number to transmit on
**
** DESCRIPTION:
** This function will encapsulate a frame with the Multilink headers.
** * * * * * *
*/
int mpWrite(int netno, unsigned char **cpp)
{
int i1;
char *cp = *cpp;
struct MPbundle *MPptr;
union {unsigned char c[4]; short s[2]; long l;} UL;
i1 = MPno[netno];
MPptr = &MPbundle[i1];
for (;;)
if ((netno = MPptr->linkno++) >= NNETS)
MPptr->linkno = 0;
else if (MPno[netno] == i1)
break;
*--cp = MPptr->txseq; /* Sequence (long format) */
*--cp = MPptr->txseq >> 8;
*--cp = MPptr->txseq >> 16;
*--cp = 0xc0; /* Both beginning and ending flags */
*--cp = 0x3d; /* Protocol code */
#if COMPRESSION & 1
if ((nets[netno].hw.remopts & COMPpcmp) == 0)
#endif
*--cp = 0;
MPptr->txseq++;
*cpp = cp;
return netno;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -