blob: 72b5a23ea1e09a759be248836ec67e41f19ef451 [file] [log] [blame]
/* MPLSCP - Serge.Krier@advalvas.be (C) 2001 */
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "pppd.h"
#include "fsm.h"
#include "mplscp.h"
/* local vars */
/* static int mplscp_is_up; */ /* have called np_up() */
/*
* Callbacks for fsm code. (CI = Configuration Information)
*/
static void mplscp_resetci (fsm *); /* Reset our CI */
static int mplscp_cilen (fsm *); /* Return length of our CI */
static void mplscp_addci (fsm *, u_char *, int *); /* Add our CI */
static int mplscp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */
static int mplscp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */
static int mplscp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */
static int mplscp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
static void mplscp_up (fsm *); /* We're UP */
static void mplscp_down (fsm *); /* We're DOWN */
static void mplscp_finished (fsm *); /* Don't need lower layer */
fsm mplscp_fsm[NUM_PPP]; /* MPLSCP fsm structure */
static fsm_callbacks mplscp_callbacks = { /* MPLSCP callback routines */
mplscp_resetci, /* Reset our Configuration Information */
mplscp_cilen, /* Length of our Configuration Information */
mplscp_addci, /* Add our Configuration Information */
mplscp_ackci, /* ACK our Configuration Information */
mplscp_nakci, /* NAK our Configuration Information */
mplscp_rejci, /* Reject our Configuration Information */
mplscp_reqci, /* Request peer's Configuration Information */
mplscp_up, /* Called when fsm reaches OPENED state */
mplscp_down, /* Called when fsm leaves OPENED state */
NULL, /* Called when we want the lower layer up */
mplscp_finished, /* Called when we want the lower layer down */
NULL, /* Called when Protocol-Reject received */
NULL, /* Retransmission is necessary */
NULL, /* Called to handle protocol-specific codes */
"MPLSCP" /* String name of protocol */
};
static option_t mplscp_option_list[] = {
{ "mpls", o_bool, &mplscp_protent.enabled_flag,
"Enable MPLSCP (and MPLS)", 1 },
{ NULL } };
/*
* Protocol entry points from main code.
*/
static void mplscp_init (int);
static void mplscp_open (int);
static void mplscp_close (int, char *);
static void mplscp_lowerup (int);
static void mplscp_lowerdown (int);
static void mplscp_input (int, u_char *, int);
static void mplscp_protrej (int);
static int mplscp_printpkt (u_char *, int,
void (*) (void *, char *, ...), void *);
struct protent mplscp_protent = {
PPP_MPLSCP,
mplscp_init,
mplscp_input,
mplscp_protrej,
mplscp_lowerup,
mplscp_lowerdown,
mplscp_open,
mplscp_close,
mplscp_printpkt,
NULL,
0, /* MPLS not enabled by default */
"MPLSCP",
"MPLS",
mplscp_option_list,
NULL,
NULL,
NULL
};
/*
* mplscp_init - Initialize MPLSCP.
*/
static void
mplscp_init(int unit) {
fsm *f = &mplscp_fsm[unit];
f->unit = unit;
f->protocol = PPP_MPLSCP;
f->callbacks = &mplscp_callbacks;
fsm_init(&mplscp_fsm[unit]);
}
/*
* mplscp_open - MPLSCP is allowed to come up.
*/
static void
mplscp_open(int unit) {
fsm_open(&mplscp_fsm[unit]);
}
/*
* mplscp_close - Take MPLSCP down.
*/
static void
mplscp_close(int unit, char *reason) {
fsm_close(&mplscp_fsm[unit], reason);
}
/*
* mplscp_lowerup - The lower layer is up.
*/
static void
mplscp_lowerup(int unit) {
fsm_lowerup(&mplscp_fsm[unit]);
}
/*
* mplscp_lowerdown - The lower layer is down.
*/
static void
mplscp_lowerdown(int unit) {
fsm_lowerdown(&mplscp_fsm[unit]);
}
/*
* mplscp_input - Input MPLSCP packet.
*/
static void
mplscp_input(int unit, u_char *p, int len) {
fsm_input(&mplscp_fsm[unit], p, len);
}
/*
* mplscp_protrej - A Protocol-Reject was received for MPLSCP.
* Pretend the lower layer went down, so we shut up.
*/
static void
mplscp_protrej(int unit) {
fsm_lowerdown(&mplscp_fsm[unit]);
}
/*
* mplscp_resetci - Reset our CI.
* Called by fsm_sconfreq, Send Configure Request.
*/
static void
mplscp_resetci(fsm *f) {
return;
}
/*
* mplscp_cilen - Return length of our CI.
* Called by fsm_sconfreq, Send Configure Request.
*/
static int
mplscp_cilen(fsm *f) {
return 0;
}
/*
* mplscp_addci - Add our desired CIs to a packet.
* Called by fsm_sconfreq, Send Configure Request.
*/
static void
mplscp_addci(fsm *f, u_char *ucp, int *lenp) {
}
/*
* ipcp_ackci - Ack our CIs.
* Called by fsm_rconfack, Receive Configure ACK.
*
* Returns:
* 0 - Ack was bad.
* 1 - Ack was good.
*/
static int
mplscp_ackci(fsm *f, u_char *p, int len) {
return 1;
}
/*
* mplscp_nakci - Peer has sent a NAK for some of our CIs.
* This should not modify any state if the Nak is bad
* or if MPLSCP is in the OPENED state.
* Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
*
* Returns:
* 0 - Nak was bad.
* 1 - Nak was good.
*/
static int
mplscp_nakci(fsm *f, u_char *p, int len) {
return 1;
}
/*
* MPLSVP_rejci - Reject some of our CIs.
* Callback from fsm_rconfnakrej.
*/
static int
mplscp_rejci(fsm *f, u_char *p, int len) {
return 1;
}
/*
* mplscp_reqci - Check the peer's requested CIs and send appropriate response.
* Callback from fsm_rconfreq, Receive Configure Request
*
* Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
* appropriately. If reject_if_disagree is non-zero, doesn't return
* CONFNAK; returns CONFREJ if it can't return CONFACK.
*/
static int
mplscp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) {
int rc = CONFACK; /* Final packet return code */
PUTCHAR(CONFACK,inp);
return rc;
}
static void
mplscp_up(fsm *f) {
sifnpmode(f->unit, PPP_MPLS_UC, NPMODE_PASS);
/* sifnpmode(f->unit, PPP_MPLS_MC, NPMODE_PASS);*/
np_up(f->unit, PPP_MPLS_UC);
/* np_up(f->unit, PPP_MPLS_MC);*/
/* ipcp_is_up = 1;*/
#if 1
printf("MPLSCP is OPENED\n");
#endif
}
static void
mplscp_down(fsm *f) {
sifnpmode(f->unit, PPP_MPLS_UC, NPMODE_DROP);
/* sifnpmode(f->unit, PPP_MPLS_MC, NPMODE_DROP);*/
sifdown(f->unit);
#if 1
printf("MPLSCP is CLOSED\n");
#endif
}
static void
mplscp_finished(fsm *f) {
np_finished(f->unit, PPP_MPLS_UC);
/* np_finished(f->unit, PPP_MPLS_MC);*/
}
/*
* mpls_printpkt - print the contents of an MPLSCP packet.
*/
static char *mplscp_codenames[] = {
"ConfReq", "ConfAck", "ConfNak", "ConfRej",
"TermReq", "TermAck", "CodeRej"
};
static int
mplscp_printpkt(u_char *p, int plen,
void (*printer) (void *, char *, ...),
void *arg) {
int code, id, len, olen;
u_char *pstart, *optend;
if (plen < HEADERLEN)
return 0;
pstart = p;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(mplscp_codenames) / sizeof(char *))
printer(arg, " %s", mplscp_codenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= HEADERLEN;
switch (code) {
case CONFREQ:
case CONFACK:
case CONFNAK:
case CONFREJ:
/* print option list */
while (len >= 2) {
GETCHAR(code, p);
GETCHAR(olen, p);
p -= 2;
if (olen < 2 || olen > len) {
break;
}
printer(arg, " <");
len -= olen;
optend = p + olen;
while (p < optend) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
printer(arg, ">");
}
break;
case TERMACK:
case TERMREQ:
if (len > 0 && *p >= ' ' && *p < 0x7f) {
printer(arg, " ");
print_string((char *)p, len, printer, arg);
p += len;
len = 0;
}
break;
}
/* print the rest of the bytes in the packet */
for (; len > 0; --len) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
return p - pstart;
}