Files
m241Neelima/components/ip_net2-6.9/ipmpls/src/ipmpls_cmd_mplsctl.c
T
2026-07-30 11:19:44 +05:30

1123 lines
33 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmpls_cmd_mplsctl.c,v $ $Revision: 1.19.10.2 $
* $Source: /home/interpeak/CVSRoot/ipmpls/src/ipmpls_cmd_mplsctl.c,v $
* $Author: hsun $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
*
* Design and implementation by Jonas Rendel <jonas@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmpls_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPMPLS_INCLUDE_CMD
#define IPCOM_USE_CLIB_PROTO
#include <ipcom.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_syslog.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_err.h>
#include <ipcom_shell.h>
#include <ipcom_sock.h>
#include <ipcom_inet.h>
#include <ipcom_getopt.h>
#include <ipcom_cmd.h>
#include "ipmpls.h"
#include "ipmpls_h.h"
struct Ipmpls_op_cmd
{
char *name;
Ip_u16 code;
};
IP_STATIC struct Ipmpls_op_cmd ipmpls_op[] = {
{
"pop",
IPMPLS_OP_POP
},
{
"peek",
IPMPLS_OP_PEEK
},
{
"push",
IPMPLS_OP_PUSH
},
{
"dlv",
IPMPLS_OP_DLV
},
{
"fwd",
IPMPLS_OP_FWD
},
{
"set",
IPMPLS_OP_SET
},
{
"setrx",
IPMPLS_OP_SET_RX
},
{
"rtab",
IPMPLS_OP_SET_VR
},
{
"vr",
IPMPLS_OP_SET_VR
},
{
IP_NULL,
IPMPLS_OP_NOP
},
};
IP_STATIC int ipmpls_cmd_handle_op(unsigned long sioc, char *key,
char *labelspace, char *op, Ip_bool silent);
IP_STATIC Ip_fd mpls_fd = IP_INVALID_SOCKET;
/*
*===========================================================================
* impls_cmd_handle_labelspace
*===========================================================================
* Description: Label Space command handler
*
* Parameters: cmd - command
* if_name - interface name
* labelspace - label space
* silent - silent flag
*
* Returns: 0 = success,
*
*/
IP_STATIC int
impls_cmd_handle_labelspace(int cmd, char *if_name, char *labelspace, Ip_bool silent)
{
struct Ipmpls_labelspace_req lreq;
unsigned long sioc;
int ret = -1;
lreq.mls_family = 0;
lreq.mls_ifindex = ipcom_if_nametoindex(if_name);
lreq.mls_labelspace = labelspace ? ipcom_atoi(labelspace) : 0;
switch (cmd)
{
case 'd':
lreq.mls_labelspace = 0;
/* fall through */
case 'a':
sioc = IPMPLS_SIOCSLABELSPACEMPLS;
break;
case 'g':
sioc = IPMPLS_SIOCGLABELSPACEMPLS;
break;
default:
return ret;
}
ret = ipcom_socketioctl(mpls_fd, sioc, &lreq);
if(((ret == 0) && (cmd == 'g')) && !silent)
ipcom_printf("Interface: %s ,Labelspace: %d",if_name, lreq.mls_labelspace);
return ret;
}
/*
*===========================================================================
* ipmpls_cmd_handle_tunnel
*===========================================================================
* Description: MPLS tunnel command handler.
*
* Parameters: cmd - IOCTL command
* if_name - interoace name.
* nhlfe_key - NHLFE key
* mtu - MTU
*
* Returns: 0 = success,
*
*/
IP_STATIC int
ipmpls_cmd_handle_tunnel(int cmd, char *if_name, char *nhlfe_key, char *mtu)
{
int ret = -1;
unsigned long sioc;
struct Ip_ifreq ifreq;
struct Ipmpls_label label;
Ipmpls_ifreq_data data;
char *d;
ipcom_memset(&data, 0, sizeof(data));
d = ipcom_strchr(if_name,'#');
if (d)
{
*d++ = 0;
data.vr = (Ip_u16)ipcom_atoi(d);
}
if (ipcom_strlen(if_name) >= IP_IFNAMSIZ)
{
return ret;
}
ipcom_strcpy(ifreq.ifr_name, if_name);
ifreq.ip_ifr_data = &data;
switch (cmd)
{
case 'a':
if (mtu)
data.mtu = ipcom_atoi(mtu);
sioc = IPMPLS_SIOCMPLSTUNNELADD;
break;
case 'd':
sioc = IPMPLS_SIOCMPLSTUNNELDEL;
break;
case 'g':
sioc = IPMPLS_SIOCMPLSTUNNELGETOUT;
break;
case 'b':
sioc = IPMPLS_SIOCMPLSTUNNELADDOUT;
goto do_key;
case 'u':
sioc = IPMPLS_SIOCMPLSTUNNELDELOUT ;
do_key:
if (nhlfe_key)
{
label.ml_type = IPMPLS_LABEL_TYPE_KEY;
label.u.ml_key = ipcom_atoi(nhlfe_key);
label.ml_index = 0;
label.__refcnt = 0;
ipcom_memcpy(&ifreq.ip_ifr_data, &label, sizeof(label));
}
else
goto out;
break;
default:
goto out;
}
ret = ipcom_socketioctl(mpls_fd, sioc, &ifreq);
if ((sioc == IPMPLS_SIOCMPLSTUNNELGETOUT) && (ret == 0))
{
ipcom_memcpy(&label, &ifreq.ip_ifr_data, sizeof(label));
ipcom_printf("NHLFE Key: %d\n",label.u.ml_key);
}
out:
return ret;
}
/*
*===========================================================================
* ipmpls_cmd_handle_nhlfe
*===========================================================================
* Description: NHLFE command handler
*
* Parameters: cmd - Command
* nlhfe_key - Key
* op - Operation Code String
* mtu - MTU op string
* silent - Silent flag
*
* Returns: 0 = success,
*
*/
IP_STATIC int
ipmpls_cmd_handle_nhlfe(int cmd, char *nhlfe_key, char *op, char *mtu, Ip_bool silent, Ip_u8 ttl)
{
int ret = -1;
unsigned long sioc;
struct Ipmpls_out_label_req olreq;
ipcom_memset(&olreq, 0 , sizeof(olreq));
olreq.mol_mtu = mtu ? ipcom_atoi(mtu) : 0;
olreq.mol_propagate_ttl = ttl;
if (!nhlfe_key)
goto out;
switch (cmd)
{
case 'a':
if (op)
{
ret = ipmpls_cmd_handle_op(IPMPLS_SIOCSMPLSOUTINSTR, nhlfe_key, IP_NULL, op, silent);
goto out;
}
else
sioc = IPMPLS_SIOCMPLSNHLFEADD;
break;
case 'd':
sioc = IPMPLS_SIOCMPLSNHLFEDEL;
break;
case 'g':
sioc = IPMPLS_SIOCMPLSNHLFEGET;
break;
default:
goto out;
}
olreq.mol_label.ml_type = IPMPLS_LABEL_TYPE_KEY;
olreq.mol_label.u.ml_key = ipcom_atoi(nhlfe_key);
olreq.mol_label.ml_index = 0;
if ((ret = ipcom_socketioctl(mpls_fd, sioc, &olreq)) == 0)
{
if (!silent && cmd == 'a')
{
ipcom_printf("NHLFE Key: %lu"IP_LF, olreq.mol_label.u.ml_key);
}
else if (cmd == 'g')
{
char buf[30];
(void)ipcom_strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", ipcom_localtime((Ip_time_t*)&olreq.mol_age));
if (!silent)
{
ipcom_printf("NHLFE Key : %lu"IP_LF, olreq.mol_label.u.ml_key);
ipcom_printf("Label Space: %u"IP_LF, olreq.mol_label.ml_index);
ipcom_printf("Age : %s"IP_LF, buf);
ipcom_printf("MTU : %lu"IP_LF, olreq.mol_mtu);
ipcom_printf("TTL : %d"IP_LF, olreq.mol_propagate_ttl);
}
(void)ipcom_sprintf(buf, "%lu", olreq.mol_label.u.ml_key);
if ((ret = ipmpls_cmd_handle_op(IPMPLS_SIOCGMPLSOUTINSTR, buf, IP_NULL, IP_NULL, silent)) < 0)
{
if (!silent)
ipcom_printf("Operations: No label operations found"IP_LF);
ret = 0;
}
}
}
out:
return ret;
}
/*
*===========================================================================
* ipmpls_cmd_handle_ilm
*===========================================================================
* Description: ILM command handler
*
* Parameters: cmd - ILM command
* ilm_key - ILM key
* proto - Protocol string
* op - Operation Code string
* silent - Silent flag
*
* Returns: 0 = success,
*
*/
IP_STATIC int
ipmpls_cmd_handle_ilm(int cmd, char *ilm_key, char *proto, char *op, Ip_bool silent)
{
int ret = -1;
unsigned long sioc;
struct Ipmpls_in_label_req ilreq;
char *labelspace;
if (!ilm_key)
goto out;
labelspace = strchr(ilm_key, ':');
if(labelspace)
*labelspace++ = 0;
ipcom_memset(&ilreq, 0 , sizeof(ilreq));
switch (cmd)
{
case 'a':
if (op)
{
ret = ipmpls_cmd_handle_op(IPMPLS_SIOCSMPLSININSTR,
ilm_key, labelspace, op, silent);
goto out;
}
else
{
sioc = IPMPLS_SIOCMPLSILMADD;
if (proto && (ipcom_strcmp("ipv4",proto) == 0))
ilreq.mil_proto = IP_IPPROTO_IP;
else if (proto && (ipcom_strcmp("ipv6",proto) == 0))
ilreq.mil_proto = IP_IPPROTO_IPV6;
else
goto out;
}
break;
case 'd':
sioc = IPMPLS_SIOCMPLSILMDEL;
break;
case 'g':
sioc = IPMPLS_SIOCMPLSILMGET;
break;
default:
goto out;
}
ilreq.mil_label.ml_type = IPMPLS_LABEL_TYPE_GEN;
ilreq.mil_label.u.ml_gen = ipcom_atoi(ilm_key);
ilreq.mil_label.ml_index = labelspace ? ipcom_atoi(labelspace) : 0;
if ((ret = ipcom_socketioctl(mpls_fd, sioc, &ilreq)) == 0)
{
if (cmd == 'g')
{
char buf[30];
(void)ipcom_strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", ipcom_localtime((Ip_time_t*)&ilreq.mil_age));
if (!silent)
{
ipcom_printf("Label : %lu"IP_LF, ilreq.mil_label.u.ml_gen);
ipcom_printf("Label Space: %d"IP_LF, ilreq.mil_label.ml_index);
ipcom_printf("Age : %s"IP_LF, buf);
ipcom_printf("Protocol : %s"IP_LF, ilreq.mil_proto == IP_IPPROTO_IP ? "ipv4" : "ipv6");
}
if ((ret = ipmpls_cmd_handle_op(IPMPLS_SIOCGMPLSININSTR, ilm_key, labelspace, IP_NULL, silent)) < 0)
{
if (!silent)
ipcom_printf("Operations : No label operations found"IP_LF);
ret = 0;
}
}
}
out:
return ret;
}
/*
*===========================================================================
* ipmpls_cmd_handle_xc
*===========================================================================
* Description: Cross-Connect command handler
*
* Parameters: cmd - command
* ilm_key - ILM key
* nhlfe_key - NHLFE key
*
* Returns: 0 = success,
*
*/
IP_STATIC int
ipmpls_cmd_handle_xc(int cmd, char *ilm_key, char *nhlfe_key)
{
int ret = -1;
struct Ipmpls_xconnect_req xcreq;
unsigned long sioc;
char *labelspace;
if ((!ilm_key) || (!nhlfe_key))
goto out;
switch (cmd)
{
case 'b':
sioc = IPMPLS_SIOCMPLSXCADD;
break;
case 'u':
sioc = IPMPLS_SIOCMPLSXCDEL;
break;
case 'g':
sioc = IPMPLS_SIOCMPLSXCGET;
break;
default:
goto out;
}
labelspace = ipcom_strchr(ilm_key, ':');
if (labelspace)
*labelspace++ = 0;
xcreq.mx_in.ml_type = IPMPLS_LABEL_TYPE_GEN;
xcreq.mx_in.u.ml_gen = ipcom_atoi(ilm_key);
xcreq.mx_in.ml_index = labelspace ? ipcom_atoi(labelspace) : 0;
xcreq.mx_out.ml_type = IPMPLS_LABEL_TYPE_KEY;
xcreq.mx_out.u.ml_key = ipcom_atoi(nhlfe_key);
xcreq.mx_out.ml_index = 0;
ret = ipcom_socketioctl(mpls_fd, sioc, &xcreq);
out:
return ret;
}
/*
*===========================================================================
* impls_cmd_ll_ntop
*===========================================================================
* Description: Creates a string representation of the hardware address.
* Parameters: dl - The hardware address.
* strptr - Will hold the sting representation of the address.
* strlen - The length of the buffer pointer to by 'strptr'
* Returns: The string represenstion.
*
*/
#if 0
IP_STATIC IP_CONST char *
ipmpls_cmd_ll_ntop(struct Ip_sockaddr_ll *ll, char *str, Ip_size_t len)
{
int alen;
alen = ll->sll_halen;
if (alen > 0)
{
int x;
int slen;
for (x = 0; x < alen; x++)
{
slen = len - x * 3;
if (slen < 0)
break;
ipcom_snprintf(&str[x * 3], slen, "%02x%s", ll->sll_addr[x],
x + 1 == alen ? "\0" : ":");
}
}
return str;
}
#endif
/*
*===========================================================================
* ipmpls_cmd_handle_op(
*===========================================================================
* Description: Operation code command handler
*
* Parameters: sioc - IOCTL command
* key - Key string
* labelspace - Labe Space string
* op - Operation Code String
* silent - Silent flag
*
* Returns: 0 = success,
*
*/
IP_STATIC int
ipmpls_cmd_handle_op(unsigned long sioc, char *key, char* labelspace, char *op, Ip_bool silent)
{
struct Ipmpls_instr_req opreq;
int ret = -1;
int i = 0;
ipcom_memset(&opreq, 0, sizeof(opreq));
if ((sioc == IPMPLS_SIOCSMPLSININSTR) || (sioc == IPMPLS_SIOCGMPLSININSTR))
opreq.mir_label.ml_type = IPMPLS_LABEL_TYPE_GEN;
else
opreq.mir_label.ml_type = IPMPLS_LABEL_TYPE_KEY;
opreq.mir_label.u.ml_gen = ipcom_atoi(key);
opreq.mir_label.ml_index = labelspace ? ipcom_atoi(labelspace) : 0;
if ((sioc == IPMPLS_SIOCSMPLSININSTR) || (sioc == IPMPLS_SIOCSMPLSOUTINSTR))
{
int j;
char *d;
struct Ip_sockaddr *sa;
/* Set operation */
for(i = 0; i < IPMPLS_NUM_OPS && op && *op; i++)
{
if (sioc == IPMPLS_SIOCSMPLSININSTR)
opreq.mir_instr[i].mir_direction = IPMPLS_IN;
else
opreq.mir_instr[i].mir_direction = IPMPLS_OUT;
/* Operations are stored as op:data:data:data:op:data:op:op */
if ((d = ipcom_strchr(op, ',')) != IP_NULL)
*d++ = 0;
/* Get opcode */
for (j = 0; ipmpls_op[j].name; j++)
if (ipcom_strcmp(op, ipmpls_op[j].name) == 0)
break;
opreq.mir_instr[i].mir_opcode = ipmpls_op[j].code;
/* Handle opcode */
switch (ipmpls_op[j].code)
{
case IPMPLS_OP_POP:
case IPMPLS_OP_PEEK:
case IPMPLS_OP_DLV:
/* These ops do not come with any data */
op = d && *d ? --d : IP_NULL;
break;
case IPMPLS_OP_PUSH:
case IPMPLS_OP_FWD:
{
char *c;
/* Format op,key or op,type:labelspace:label */
if (!d || !*d)
goto bad_data_out;
/* Setup null-terminated label string */
op = ipcom_strchr(d, ',');
if (op)
*op = 0;
c = ipcom_strchr(d,':');
if (c)
{
/* type:labelspace:label syntax */
*c = 0;
opreq.mir_instr[i].mir_data.push.ml_type = ipcom_atoi(d);
d = c + 1;
c = ipcom_strchr(d,':');
if (!c)
goto bad_data_out;
*c = 0;
opreq.mir_instr[i].mir_data.push.ml_index = ipcom_atoi(d);
d = c + 1;
opreq.mir_instr[i].mir_data.push.u.ml_key = ipcom_atoi(d);
}
else
{
/* key syntax */
opreq.mir_instr[i].mir_data.push.ml_type = IPMPLS_LABEL_TYPE_KEY;
opreq.mir_instr[i].mir_data.push.u.ml_key = ipcom_atoi(d);
opreq.mir_instr[i].mir_data.push.ml_index = 0;
}
}
break;
case IPMPLS_OP_SET:
/*
* Format:
* NHLFE: op,<interface name>,<next hop address>
* ILM : op,<gateway address>
*/
if (!d || !*d)
goto bad_data_out;
if (sioc == IPMPLS_SIOCSMPLSOUTINSTR)
{
/* NHLFE SET */
/* Setup null-terminated interface string */
op = ipcom_strchr(d, ',');
if (!op || !*op)
goto bad_data_out;
*op++ = 0;
opreq.mir_instr[i].mir_data.set.mni_if = ipcom_if_nametoindex(d);
d = op;
}
sa = &opreq.mir_instr[i].mir_data.set.a.sa;
op = ipcom_strchr(d, ',');
/* Setup null-terminated address string */
if (op)
*op = 0;
/* Convert address string to sockaddr */
if (ipcom_getsockaddrbyaddr(IP_AF_INET, d, sa) < 0)
if (ipcom_getsockaddrbyaddr(IP_AF_INET6, d, sa) < 0)
{
if (ipcom_getsockaddrbyaddr(IP_AF_LINK, d, sa) < 0)
goto bad_data_out;
}
break;
case IPMPLS_OP_SET_RX:
/* Format op,<interface name> */
if (!d || !*d)
goto bad_data_out;
/* Setup null-terminated interface name string */
op = ipcom_strchr(d, ',');
if (op)
*op = 0;
opreq.mir_instr[i].mir_data.set_rx = ipcom_if_nametoindex(d);
break;
case IPMPLS_OP_SET_VR:
/* Format op,<rtab index> */
if (!d || !*d)
goto bad_data_out;
/* Setup null-terminated interface name string */
op = ipcom_strchr(d, ',');
if (op)
*op = 0;
opreq.mir_instr[i].mir_data.set_rtab = ipcom_atoi(d);
break;
case IPMPLS_OP_NOP:
/* oops. Invalid opname */
goto bad_op_out;
}
if (op)
op++;
}
opreq.mir_instr_length = (Ip_u8)i;
}
ret = ipcom_socketioctl(mpls_fd, sioc, &opreq);
if ((ret == 0) && ((sioc == IPMPLS_SIOCGMPLSININSTR) || (sioc == IPMPLS_SIOCGMPLSOUTINSTR)))
{
char buf[50];
if (!silent)
ipcom_printf("Operations : ");
/* Get operation */
for (i=0; i < opreq.mir_instr_length; i++)
{
if (i > 0)
{
if (!silent)
ipcom_printf(",");
}
/* Handle opcode */
switch (opreq.mir_instr[i].mir_opcode)
{
case IPMPLS_OP_POP:
if (!silent)
ipcom_printf("pop");
break;
case IPMPLS_OP_PEEK:
if (!silent)
ipcom_printf("peek");
break;
case IPMPLS_OP_DLV:
if (!silent)
ipcom_printf("dlv,%s",opreq.mir_family == IP_IPPROTO_IP ? "ipv4" : "ipv6");
break;
case IPMPLS_OP_PUSH:
if (!silent)
ipcom_printf("push,%lu",opreq.mir_instr[i].mir_data.push.u.ml_gen);
break;
case IPMPLS_OP_FWD:
if (!silent)
ipcom_printf("fwd,%lu:%lu:%lu",
opreq.mir_instr[i].mir_data.push.ml_type,
opreq.mir_instr[i].mir_data.push.ml_index,
opreq.mir_instr[i].mir_data.push.u.ml_key);
break;
case IPMPLS_OP_SET:
if (sioc == IPMPLS_SIOCGMPLSOUTINSTR)
{
char addrstr[64];
char namebuf[64];
void* addr = IP_NULL;
struct Ip_sockaddr *sa = &opreq.mir_instr[i].mir_data.set.a.sa;
switch (sa->sa_family)
{
#ifdef IPCOM_USE_INET
case IP_AF_INET:
addr = &opreq.mir_instr[i].mir_data.set.a.sin.sin_addr;
break;
#endif
#ifdef IPCOM_USE_INET6
case IP_AF_INET6:
addr = &opreq.mir_instr[i].mir_data.set.a.sin6.sin6_addr;
break;
#endif
default:
goto bad_data_out;
}
ipcom_inet_ntop(sa->sa_family,
addr,
addrstr,
sizeof(addrstr));
/* NHFLE */
if (!silent)
ipcom_printf("set,%s,%s", ipcom_if_indextoname(opreq.mir_instr[i].mir_data.set.mni_if, namebuf), addrstr);
}
else
{
/* ILM */
if (!silent)
ipcom_printf("set,%s",
ipcom_cmd_sockaddr_to_str(&opreq.mir_instr[i].mir_data.set.a.sa,
IP_FALSE,
IP_TRUE,
buf,
sizeof(buf)));
}
break;
case IPMPLS_OP_SET_RX:
if (!silent)
ipcom_printf("setrx,%s",ipcom_if_indextoname(opreq.mir_instr[i].mir_data.set_rx, buf));
break;
case IPMPLS_OP_SET_VR:
if (!silent)
ipcom_printf("vr,%lu",opreq.mir_instr[i].mir_data.set_rtab);
break;
case IPMPLS_OP_NOP:
goto out;
}
}
out:
if (!silent)
ipcom_printf(IP_LF);
}
return ret;
bad_data_out:
if (!silent)
ipcom_fprintf(ip_stderr,"Invalid data for operation code: %s"IP_LF,op);
return ret;
bad_op_out:
if (!silent)
ipcom_fprintf(ip_stderr,"Invalid operation code: %s"IP_LF,op);
return ret;
}
/*
*===========================================================================
* ipmpls_cmd_handle_table
*===========================================================================
* Description: Table command handler
*
* Parameters: cmd - command
* table - table string
*
* Returns: 0 = success,
*
*/
IP_STATIC int
ipmpls_cmd_handle_table(int cmd, char *table)
{
int ret = -1;
unsigned long sioc;
(void)cmd;
if (table && (ipcom_strcmp(table,"nhlfe") == 0))
sioc = IPMPLS_SIOCMPLSNHLFEFLUSH;
else if (table && (ipcom_strcmp(table,"ilm") == 0))
sioc = IPMPLS_SIOCMPLSILMFLUSH;
else
goto out;
ret = ipcom_socketioctl(mpls_fd, sioc, IP_NULL);
out:
return ret;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps_cmd_dhcps
*===========================================================================
* Description: Shell command used to start,stop and configure the DHCP
* server.
* Parameters: argc - The number of arguments passed to the command.
* argv - The arguments passed to the command.
* Returns: 0 = success,
*
*/
IP_GLOBAL int
ipmpls_cmd_mplsctl(int argc, char **argv)
{
char *op = IP_NULL;
char *ilm_key = IP_NULL;
char *nhlfe_key = IP_NULL;
char *if_name = IP_NULL;
char *proto = IP_NULL;
char *mtu = IP_NULL;
char *labelspace = IP_NULL;
char *table = IP_NULL;
char *vr = IP_NULL;
int ret = -1;
int cmd = 0;
int opt;
int cur_vr;
int new_vr;
Ip_bool silent = IP_FALSE;
Ip_u8 ttl = 0;
if (argc < 3)
goto usage;
#ifndef IP_PORT_LAS
new_vr = cur_vr = ipcom_proc_vr_get();
#else
(void)cur_vr;
#endif
ipcom_getopt_clear();
while ((opt = ipcom_getopt(argc, argv, "stadgbuf:i:n:l:I:o:m:p:V:")) != -1)
{
switch (opt)
{
case 'f':
table = ip_optarg;
/* fall through */
case 'a':
case 'd':
case 'g':
case 'b':
case 'u':
cmd = opt;
break;
case 'i':
ilm_key = ip_optarg;
break;
case 'n':
nhlfe_key = ip_optarg;
break;
case 'l':
labelspace = ip_optarg;
break;
case 'I':
if_name = ip_optarg;
break;
case 'o':
op = ip_optarg;
break;
case 'p':
proto = ip_optarg;
break;
case 'm':
mtu = ip_optarg;
break;
case 'V':
vr = ip_optarg;
break;
case 's':
silent = IP_TRUE;
break;
case 't':
ttl = 1;
break;
default:
goto usage;
}
}
mpls_fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM,0);
if (mpls_fd < 0)
{
ipcom_fprintf(ip_stderr, "Failed to open socket with error code %d (%s)"IP_LF,
ipcom_errno,
ipcom_strerror(ipcom_errno));
return -1;
}
if (vr != IP_NULL)
{
new_vr = ipcom_atoi(vr);
#ifdef IP_PORT_LAS
ret = ipcom_setsockopt(mpls_fd, IP_SOL_SOCKET, IP_SO_X_VR, &new_vr, sizeof(new_vr));
if (ret < 0)
{
ipcom_fprintf(ip_stderr, "Failed to set VR to %d"IP_LF, new_vr);
return -1;
}
#else
ipcom_proc_vr_set(new_vr);
#endif
}
switch (cmd)
{
case 'a':
case 'd':
if (if_name && labelspace)
ret = impls_cmd_handle_labelspace(cmd, if_name, labelspace, silent);
else if (if_name)
ret = ipmpls_cmd_handle_tunnel(cmd, if_name, nhlfe_key, mtu);
else if (nhlfe_key)
ret = ipmpls_cmd_handle_nhlfe(cmd, nhlfe_key, op, mtu, silent, ttl);
else if (ilm_key)
ret = ipmpls_cmd_handle_ilm(cmd, ilm_key, proto, op, silent);
break;
case 'g':
if (if_name)
{
ret = impls_cmd_handle_labelspace(cmd, if_name, IP_NULL, silent);
if (ret < 0)
ret = ipmpls_cmd_handle_tunnel(cmd, if_name, nhlfe_key, mtu);
}
if (nhlfe_key)
ret = ipmpls_cmd_handle_nhlfe(cmd, nhlfe_key, IP_NULL, IP_NULL, silent, ttl);
if (ilm_key)
ret = ipmpls_cmd_handle_ilm(cmd, ilm_key, IP_NULL, IP_NULL, silent);
break;
case 'b':
case 'u':
if (ilm_key && nhlfe_key)
ret = ipmpls_cmd_handle_xc(cmd, ilm_key, nhlfe_key);
else if (if_name && nhlfe_key)
ret = ipmpls_cmd_handle_tunnel(cmd, if_name, nhlfe_key, mtu);
break;
case 'f':
ret = ipmpls_cmd_handle_table (cmd, table);
break;
}
ipcom_socketclose(mpls_fd);
#ifndef IP_PORT_LAS
if (cur_vr != new_vr)
ipcom_proc_vr_set(cur_vr);
#endif
if (ret < 0)
{
ipcom_fprintf(ip_stderr, "Failed with error code %d (%s)"IP_LF,
ipcom_errno,
ipcom_strerror(ipcom_errno));
}
return ret;
usage:
ipcom_fprintf(ip_stderr,
"Usage: mplsctl [-s] [-a] [-d] [-b] [-u] [-f ilm | nhlfe]"IP_LF
"[-I <interface name>] [-n <nhlfe key>] [-i <ilm key>]"IP_LF
"[-l <label space>] [-o <label operations>] [-m <mtu>]"IP_LF
"[-p <proto>] [-t <ttl>]" IP_LF);
ipcom_fprintf(ip_stderr,
"Command options:"IP_LF
"-s Silent mode (i.e. no output to stdout)"IP_LF
"-a Add an object"IP_LF
"-d Delete an object"IP_LF
"-b Bind an object to another"IP_LF
"-u Unbind an object"IP_LF
"-f Flush the ilm | nhlfe table"IP_LF);
ipcom_fprintf(ip_stderr,
"Object options:"IP_LF
"-I Interface name. Used together with tunnels and label spaces"IP_LF
"-n NHLFE key. Used with NHLFE:s, Tunnels and Cross-Connects"IP_LF
"-i ILM key. Used with ILM:s and Cross-Connects"IP_LF
"-p Protocol descriptor. Either ipv4 or ipv6"IP_LF
"-m MTU. Used with tunnels and NHLFE:s"IP_LF
"-t Set MPLS TTL to the value specified in the payload IP header (default 255)."IP_LF
" Used with NHLFE:s"IP_LF
"-o Label operations (comma separated). Used with NHLFE:s and ILM:s"IP_LF);
ipcom_fprintf(ip_stderr,
"Other options:"IP_LF
"-V Virtual router index"IP_LF);
ipcom_fprintf(ip_stderr,
" Valid NHLFE label operations:"IP_LF
" push,<label> - Push a label"IP_LF
" fwd,<key> - Forward the packet using the NHLFE identified with the key."IP_LF
" set,<ifname>,<next hop address> - For NHLFE: Set the outgoing interface and nexthop address."IP_LF
" Valid formats for the nexthop address: IPv4,IPv6,MAC"IP_LF);
ipcom_fprintf(ip_stderr,
" Valid ILM label operations:"IP_LF
" pop - Pop a label"IP_LF
" peek - Look at the label on top of the label stack and perform"IP_LF
" the operations associated with it"IP_LF
" dlv - Deliver packet to the IPv4/IPv6 stack"IP_LF
" push,<label> - Push a label"IP_LF
" fwd,<key> - Forward the packet using the NHLFE identified with the key."IP_LF
" set,<destination address> - For ILM: Set destination address to route to"IP_LF
" Valid formats for the destination address: IPv4,IPv6"IP_LF
" setrx,<ifname> - Set receiving interface."IP_LF
" vr,<index> - Set IPv4/IPv6 route table to use when forwarding."IP_LF IP_LF
" NOTE: The setrx operation can not be used in combination with the vr operation"IP_LF IP_LF);
ipcom_fprintf(ip_stderr,
"Examples:"IP_LF
" Add an IPv4 ILM with label 4711 in labelspace 17:"IP_LF
" mplsctl -a -i 4711:17 -p ipv4"IP_LF
" Add some operations on an ILM:"IP_LF
" mplsctl -a -i 4711:17 -o pop,setrx,eth0,dlv"IP_LF
" Add a NHLFE with autogenerated key:"IP_LF
" mplsctl -a -n 0"IP_LF
" Add a NHLFE with user defined key (1234):"IP_LF
" mplsctl -a -n 1234"IP_LF
" Add some operations on an NHLFE:"IP_LF
" mplsctl -a -n 1234 -o push,2345,set,eth0,10.1.1.1"IP_LF
" Add a Cross-Connect (ILM-NHLFE):"IP_LF
" mplsctl -b -i 4711:17 -n 1234"IP_LF);
return ret;
}
#endif /* #ifdef IPMPLS_INCLUDE_CMD */