+
+#ifdef BGP
+static int cmd_router_bgp(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int as;
+
+ if (CLI_HELP_REQUESTED)
+ return cli_arg_help(cli, argc > 1,
+ "<1-65535>", "Autonomous system number", NULL);
+
+ if (argc != 1 || (as = atoi(argv[0])) < 1 || as > 65535)
+ {
+ cli_print(cli, "Invalid autonomous system number");
+ return CLI_OK;
+ }
+
+ if (bgp_configured && as != config->as_number)
+ {
+ cli_print(cli, "Can't change local AS on a running system");
+ return CLI_OK;
+ }
+
+ config->as_number = as;
+ cli_set_configmode(cli, MODE_CONFIG_BGP, "router");
+
+ return CLI_OK;
+}
+
+static int cmd_router_bgp_exit(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ if (CLI_HELP_REQUESTED)
+ return CLI_HELP_NO_ARGS;
+
+ cli_set_configmode(cli, MODE_CONFIG, NULL);
+ return CLI_OK;
+}
+
+static int find_bgp_neighbour(char *name)
+{
+ int i;
+ int new = -1;
+ struct hostent *h;
+ in_addr_t addrs[4] = { 0 };
+ char **a;
+
+ if (!(h = gethostbyname(name)) || h->h_addrtype != AF_INET)
+ return -2;
+
+ for (i = 0; i < sizeof(addrs) / sizeof(*addrs) && h->h_addr_list[i]; i++)
+ memcpy(&addrs[i], h->h_addr_list[i], sizeof(*addrs));
+
+ for (i = 0; i < BGP_NUM_PEERS; i++)
+ {
+ if (!config->neighbour[i].name[0])
+ {
+ if (new == -1) new = i;
+ continue;
+ }
+
+ if (!strcmp(name, config->neighbour[i].name))
+ return i;
+
+ if (!(h = gethostbyname(config->neighbour[i].name)) || h->h_addrtype != AF_INET)
+ continue;
+
+ for (a = h->h_addr_list; *a; a++)
+ {
+ int j;
+ for (j = 0; j < sizeof(addrs) / sizeof(*addrs) && addrs[j]; j++)
+ if (!memcmp(&addrs[j], *a, sizeof(*addrs)))
+ return i;
+ }
+ }
+
+ return new;
+}
+
+static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int i;
+ int keepalive;
+ int hold;
+
+ if (CLI_HELP_REQUESTED)
+ {
+ switch (argc)
+ {
+ case 1:
+ return cli_arg_help(cli, 0,
+ "A.B.C.D", "BGP neighbour address",
+ "NAME", "BGP neighbour name",
+ NULL);
+
+ case 2:
+ return cli_arg_help(cli, 0,
+ "remote-as", "Set remote autonomous system number",
+ "timers", "Set timers",
+ NULL);
+
+ default:
+ if (!strncmp("remote-as", argv[1], strlen(argv[1])))
+ return cli_arg_help(cli, argv[2][1], "<1-65535>", "Autonomous system number", NULL);
+
+ if (!strncmp("timers", argv[1], strlen(argv[1])))
+ {
+ if (argc == 3)
+ return cli_arg_help(cli, 0, "<1-65535>", "Keepalive time", NULL);
+
+ if (argc == 4)
+ return cli_arg_help(cli, argv[3][1], "<3-65535>", "Hold time", NULL);
+
+ if (argc == 5 && !argv[4][1])
+ return cli_arg_help(cli, 1, NULL);
+ }
+
+ return CLI_OK;
+ }
+ }
+
+ if (argc < 3)
+ {
+ cli_print(cli, "Invalid arguments");
+ return CLI_OK;
+ }
+
+ if ((i = find_bgp_neighbour(argv[0])) == -2)
+ {
+ cli_print(cli, "Invalid neighbour");
+ return CLI_OK;
+ }
+
+ if (i == -1)
+ {
+ cli_print(cli, "Too many neighbours (max %d)", BGP_NUM_PEERS);
+ return CLI_OK;
+ }
+
+ if (!strncmp("remote-as", argv[1], strlen(argv[1])))
+ {
+ int as = atoi(argv[2]);
+ if (as < 0 || as > 65535)
+ {
+ cli_print(cli, "Invalid autonomous system number");
+ return CLI_OK;
+ }
+
+ if (!config->neighbour[i].name[0])
+ {
+ snprintf(config->neighbour[i].name, sizeof(config->neighbour[i].name), argv[0]);
+ config->neighbour[i].keepalive = -1;
+ config->neighbour[i].hold = -1;
+ }
+
+ config->neighbour[i].as = as;
+ return CLI_OK;
+ }
+
+ if (argc != 4 || strncmp("timers", argv[1], strlen(argv[1])))
+ {
+ cli_print(cli, "Invalid arguments");
+ return CLI_OK;
+ }
+
+ if (!config->neighbour[i].name[0])
+ {
+ cli_print(cli, "Specify remote-as first");
+ return CLI_OK;
+ }
+
+ keepalive = atoi(argv[2]);
+ hold = atoi(argv[3]);
+
+ if (keepalive < 1 || keepalive > 65535)
+ {
+ cli_print(cli, "Invalid keepalive time");
+ return CLI_OK;
+ }
+
+ if (hold < 3 || hold > 65535)
+ {
+ cli_print(cli, "Invalid hold time");
+ return CLI_OK;
+ }
+
+ if (keepalive == BGP_KEEPALIVE_TIME)
+ keepalive = -1; // using default value
+
+ if (hold == BGP_HOLD_TIME)
+ hold = -1;
+
+ config->neighbour[i].keepalive = keepalive;
+ config->neighbour[i].hold = hold;
+
+ return CLI_OK;
+}
+
+static int cmd_router_bgp_no_neighbour(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int i;
+
+ if (CLI_HELP_REQUESTED)
+ return cli_arg_help(cli, argc > 0,
+ "A.B.C.D", "BGP neighbour address",
+ "NAME", "BGP neighbour name",
+ NULL);
+
+ if (argc != 1)
+ {
+ cli_print(cli, "Specify a BGP neighbour");
+ return CLI_OK;
+ }
+
+ if ((i = find_bgp_neighbour(argv[0])) == -2)
+ {
+ cli_print(cli, "Invalid neighbour");
+ return CLI_OK;
+ }
+
+ if (i < 0 || !config->neighbour[i].name[0])
+ {
+ cli_print(cli, "Neighbour %s not configured", argv[0]);
+ return CLI_OK;
+ }
+
+ memset(&config->neighbour[i], 0, sizeof(config->neighbour[i]));
+ return CLI_OK;
+}
+
+static int cmd_show_bgp(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int i;
+ int hdr = 0;
+ char *addr;
+
+ if (!bgp_configured)
+ return CLI_OK;
+
+ if (CLI_HELP_REQUESTED)
+ return cli_arg_help(cli, 1,
+ "A.B.C.D", "BGP neighbour address",
+ "NAME", "BGP neighbour name",
+ NULL);
+
+ cli_print(cli, "BGPv%d router identifier %s, local AS number %d",
+ BGP_VERSION, inet_toa(my_address), (int) config->as_number);
+
+ time(&time_now);
+
+ for (i = 0; i < BGP_NUM_PEERS; i++)
+ {
+ if (!*bgp_peers[i].name)
+ continue;
+
+ addr = inet_toa(bgp_peers[i].addr);
+ if (argc && strcmp(addr, argv[0]) &&
+ strncmp(bgp_peers[i].name, argv[0], strlen(argv[0])))
+ continue;
+
+ if (!hdr++)
+ {
+ cli_print(cli, "");
+ cli_print(cli, "Peer AS Address "
+ "State Retries Retry in Route Pend Timers");
+ cli_print(cli, "------------------ ----- --------------- "
+ "----------- ------- -------- ----- ---- ---------");
+ }
+
+ cli_print(cli, "%-18.18s %5d %15s %-11s %7d %7ds %5s %4s %4d %4d",
+ bgp_peers[i].name,
+ bgp_peers[i].as,
+ addr,
+ bgp_state_str(bgp_peers[i].state),
+ bgp_peers[i].retry_count,
+ bgp_peers[i].retry_time ? bgp_peers[i].retry_time - time_now : 0,
+ bgp_peers[i].routing ? "yes" : "no",
+ bgp_peers[i].update_routes ? "yes" : "no",
+ bgp_peers[i].keepalive,
+ bgp_peers[i].hold);
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_suspend_bgp(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int i;
+ char *addr;
+
+ if (!bgp_configured)
+ return CLI_OK;
+
+ if (CLI_HELP_REQUESTED)
+ return cli_arg_help(cli, 1,
+ "A.B.C.D", "BGP neighbour address",
+ "NAME", "BGP neighbour name",
+ NULL);
+
+ for (i = 0; i < BGP_NUM_PEERS; i++)
+ {
+ if (bgp_peers[i].state != Established)
+ continue;
+
+ if (!bgp_peers[i].routing)
+ continue;
+
+ addr = inet_toa(bgp_peers[i].addr);
+ if (argc && strcmp(addr, argv[0]) && strcmp(bgp_peers[i].name, argv[0]))
+ continue;
+
+ bgp_peers[i].cli_flag = BGP_CLI_SUSPEND;
+ cli_print(cli, "Suspending peer %s", bgp_peers[i].name);
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_no_suspend_bgp(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int i;
+ char *addr;
+
+ if (!bgp_configured)
+ return CLI_OK;
+
+ if (CLI_HELP_REQUESTED)
+ return cli_arg_help(cli, 1,
+ "A.B.C.D", "BGP neighbour address",
+ "NAME", "BGP neighbour name",
+ NULL);
+
+ for (i = 0; i < BGP_NUM_PEERS; i++)
+ {
+ if (bgp_peers[i].state != Established)
+ continue;
+
+ if (bgp_peers[i].routing)
+ continue;
+
+ addr = inet_toa(bgp_peers[i].addr);
+ if (argc && strcmp(addr, argv[0]) &&
+ strncmp(bgp_peers[i].name, argv[0], strlen(argv[0])))
+ continue;
+
+ bgp_peers[i].cli_flag = BGP_CLI_ENABLE;
+ cli_print(cli, "Un-suspending peer %s", bgp_peers[i].name);
+ }
+
+ return CLI_OK;
+}
+
+static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int argc)
+{
+ int i;
+ char *addr;
+
+ if (!bgp_configured)
+ return CLI_OK;
+
+ if (CLI_HELP_REQUESTED)
+ return cli_arg_help(cli, 1,
+ "A.B.C.D", "BGP neighbour address",
+ "NAME", "BGP neighbour name",
+ NULL);
+
+ for (i = 0; i < BGP_NUM_PEERS; i++)
+ {
+ if (!*bgp_peers[i].name)
+ continue;
+
+ addr = inet_toa(bgp_peers[i].addr);
+ if (argc && strcmp(addr, argv[0]) &&
+ strncmp(bgp_peers[i].name, argv[0], strlen(argv[0])))
+ continue;
+
+ bgp_peers[i].cli_flag = BGP_CLI_RESTART;
+ cli_print(cli, "Restarting peer %s", bgp_peers[i].name);
+ }
+
+ return CLI_OK;
+}
+#endif /* BGP*/
+
+// Convert a string in the form of abcd.ef12.3456 into char[6]
+void parsemac(char *string, char mac[6])
+{
+ if (sscanf(string, "%02x%02x.%02x%02x.%02x%02x", (unsigned int *)&mac[0], (unsigned int *)&mac[1], (unsigned int *)&mac[2], (unsigned int *)&mac[3], (unsigned int *)&mac[4], (unsigned int *)&mac[5]) == 6)
+ return;
+ if (sscanf(string, "%02x%02x:%02x%02x:%02x%02x", (unsigned int *)&mac[0], (unsigned int *)&mac[1], (unsigned int *)&mac[2], (unsigned int *)&mac[3], (unsigned int *)&mac[4], (unsigned int *)&mac[5]) == 6)
+ return;
+ memset(mac, 0, 6);
+}