VirtualBox

Changeset 90773 in vbox


Ignore:
Timestamp:
Aug 21, 2021 1:55:41 PM (3 years ago)
Author:
vboxsync
Message:

VBoxNetAdpCtl: bugref:8093. Rewrite command line processing to be
easier to follow, add getopt support.

Add --verbose and --dry-run options to be able to see which commands
are/will be executed to effect the requested change. --dry-run is not
supported by the actions that do VBox ioctls (it's not yet clear to me
what would be the best way to report the intended action here), but
since these options are mostly for internal use, it's not that much of
problem, I think.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp

    r90743 r90773  
    2323#include <list>
    2424#include <errno.h>
     25#include <getopt.h>
    2526#include <stdio.h>
    2627#include <stdarg.h>
     
    7374#define VBOXADPCTL_IFCONFIG_PATH2 "/bin/ifconfig"
    7475
    75 
    76 static void showUsage(void)
     76bool verbose;
     77bool dry_run;
     78
     79
     80static int usage(void)
    7781{
    7882    fprintf(stderr, "Usage: VBoxNetAdpCtl <adapter> <address> ([netmask <address>] | remove)\n");
    7983    fprintf(stderr, "     | VBoxNetAdpCtl [<adapter>] add\n");
    8084    fprintf(stderr, "     | VBoxNetAdpCtl <adapter> remove\n");
     85    return EXIT_FAILURE;
    8186}
    8287
     
    434439        return EXIT_FAILURE;
    435440
     441    if (verbose)
     442    {
     443        const char *sep = "";
     444        for (const char * const *pArg = argv; *pArg != NULL; ++pArg)
     445        {
     446            printf("%s%s", sep, *pArg);
     447            sep = " ";
     448        }
     449        printf("\n");
     450    }
     451    if (dry_run)
     452        return EXIT_SUCCESS;
     453
    436454    int rc = EXIT_FAILURE; /* o/~ hope for the best, expect the worst */
    437455    pid_t childPid = fork();
     
    738756{
    739757    char szAdapterName[VBOXNETADP_MAX_NAME_LEN];
    740     int rc = EXIT_SUCCESS;
     758    int rc;
    741759
    742760    AddressCommand& cmd = chooseAddressCommand();
    743761
    744     if (argc < 2)
    745     {
    746         fprintf(stderr, "Insufficient number of arguments\n\n");
    747         showUsage();
    748         return 1;
    749     }
    750     else if (argc == 2 && !strcmp("add", argv[1]))
    751     {
    752         /* Create a new interface */
     762
     763    static const struct option options[] = {
     764        { "dry-run", no_argument, NULL, 'n' },
     765        { "verbose", no_argument, NULL, 'v' },
     766        { NULL, 0, NULL, 0 }
     767    };
     768
     769    int ch;
     770    while ((ch = getopt_long(argc, argv, "nv", options, NULL)) != -1)
     771    {
     772        switch (ch)
     773        {
     774            case 'n':
     775                dry_run = true;
     776                verbose = true;
     777                break;
     778
     779            case 'v':
     780                verbose = true;
     781                break;
     782
     783            case '?':
     784            default:
     785                return usage();
     786        }
     787    }
     788    argc -= optind;
     789    argv += optind;
     790
     791    if (argc == 0)
     792        return usage();
     793
     794
     795    /*
     796     * VBoxNetAdpCtl add
     797     */
     798    if (strcmp(argv[0], "add") == 0)
     799    {
     800        if (argc > 1)           /* extraneous args */
     801            return usage();
     802
     803        /* Create a new interface, print its name. */
    753804        *szAdapterName = '\0';
    754805        rc = g_adapter.add(szAdapterName);
    755         if (rc == 0)
     806        if (rc == EXIT_SUCCESS)
    756807            puts(szAdapterName);
     808
    757809        return rc;
    758810    }
     811
     812
     813    /*
     814     * All other variants are of the form:
     815     *   VBoxNetAdpCtl if0 ...action...
     816     */
     817    const char * const ifname = argv[0];
     818    const char * const action = argv[1];
     819    if (argc < 2)
     820        return usage();
     821
     822
    759823#ifdef RT_OS_LINUX
    760     else if (argc == 3 && !strcmp("speed", argv[2]))
    761     {
    762         /*
    763          * This ugly hack is needed for retrieving the link speed on
    764          * pre-2.6.33 kernels (see @bugref{6345}).
    765          */
    766         if (strlen(argv[1]) >= IFNAMSIZ)
    767         {
    768             showUsage();
    769             return -1;
     824    /*
     825     * VBoxNetAdpCtl iface42 speed
     826     *
     827     * This ugly hack is needed for retrieving the link speed on
     828     * pre-2.6.33 kernels (see @bugref{6345}).
     829     *
     830     * This variant is used with any interface, not just host-only.
     831     */
     832    if (strcmp(action, "speed") == 0)
     833    {
     834        if (argc > 2)           /* extraneous args */
     835            return usage();
     836
     837        if (strlen(ifname) >= IFNAMSIZ)
     838        {
     839            fprintf(stderr, "Interface name too long\n");
     840            return EXIT_FAILURE;
    770841        }
     842
    771843        unsigned uSpeed = 0;
    772         rc = g_adapter.getSpeed(argv[1], &uSpeed);
    773         if (!rc)
     844        rc = g_adapter.getSpeed(ifname, &uSpeed);
     845        if (rc == EXIT_SUCCESS)
    774846            printf("%u", uSpeed);
     847
    775848        return rc;
    776849    }
    777 #endif
    778 
    779     rc = g_adapter.checkName(argv[1], szAdapterName, sizeof(szAdapterName));
    780     if (rc)
     850#endif  /* RT_OS_LINUX */
     851
     852
     853    /*
     854     * The rest of the actions only operate on host-only interfaces.
     855     */
     856    /** @todo Why the code below uses both ifname and szAdapterName? */
     857    rc = g_adapter.checkName(ifname, szAdapterName, sizeof(szAdapterName));
     858    if (rc != EXIT_SUCCESS)
    781859        return rc;
    782860
    783     switch (argc)
    784     {
    785         case 5:
    786         {
    787             /* Add a netmask to existing interface */
    788             if (strcmp("netmask", argv[3]))
    789             {
    790                 fprintf(stderr, "Invalid argument: %s\n\n", argv[3]);
    791                 showUsage();
    792                 return 1;
    793             }
    794             rc = cmd.set(argv[1], argv[2], argv[4]);
    795             break;
    796         }
    797 
    798         case 4:
    799         {
    800             /* Remove a single address from existing interface */
    801             if (strcmp("remove", argv[3]))
    802             {
    803                 fprintf(stderr, "Invalid argument: %s\n\n", argv[3]);
    804                 showUsage();
    805                 return 1;
    806             }
    807             rc = cmd.remove(argv[1], argv[2]);
    808             break;
    809         }
    810 
    811         case 3:
    812         {
    813             if (strcmp("remove", argv[2]) == 0)
    814             {
    815                 /* Remove an existing interface */
    816                 rc = g_adapter.remove(argv[1]);
    817             }
    818             else if (strcmp("add", argv[2]) == 0)
    819             {
    820                 /* Create an interface with given name */
    821                 rc = g_adapter.add(szAdapterName);
    822                 if (rc == 0)
    823                     puts(szAdapterName);
    824             }
    825             else
    826                 rc = cmd.set(argv[1], argv[2]);
    827             break;
    828         }
    829 
    830         default:
    831             fprintf(stderr, "Invalid number of arguments.\n\n");
    832             showUsage();
    833             return 1;
    834     }
    835 
    836     return rc;
    837 }
    838 
     861
     862    /*
     863     * VBoxNetAdpCtl vboxnetN remove
     864     */
     865    if (strcmp(action, "remove") == 0)
     866    {
     867        if (argc > 2)           /* extraneous args */
     868            return usage();
     869
     870        /* Remove an existing interface */
     871        return g_adapter.remove(ifname);
     872    }
     873
     874    /*
     875     * VBoxNetAdpCtl vboxnetN add
     876     */
     877    if (strcmp(action, "add") == 0)
     878    {
     879        if (argc > 2)           /* extraneous args */
     880            return usage();
     881
     882        /* Create an interface with the given name, print its name. */
     883        rc = g_adapter.add(szAdapterName);
     884        if (rc == EXIT_SUCCESS)
     885            puts(szAdapterName);
     886
     887        return rc;
     888    }
     889
     890
     891    /*
     892     * The rest of the actions are of the form
     893     *     VBoxNetAdpCtl vboxnetN $addr [...]
     894     *
     895     * Use the argument after the address to select the action.
     896     */
     897    /** @todo Do early verification of addr format here? */
     898    const char * const addr = argv[1];
     899    const char * const keyword = argv[2];
     900
     901
     902    /*
     903     * VBoxNetAdpCtl vboxnetN 1.2.3.4
     904     */
     905    if (keyword == NULL)
     906    {
     907        return cmd.set(ifname, addr);
     908    }
     909
     910    /*
     911     * VBoxNetAdpCtl vboxnetN 1.2.3.4 netmask 255.255.255.0
     912     */
     913    if (strcmp(keyword, "netmask") == 0)
     914    {
     915        if (argc != 4)          /* too few or too many args */
     916            return usage();
     917
     918        const char * const mask = argv[3];
     919        return cmd.set(ifname, addr, mask);
     920    }
     921
     922    /*
     923     * VBoxNetAdpCtl vboxnetN 1.2.3.4 remove
     924     */
     925    if (strcmp(keyword, "remove") == 0)
     926    {
     927        if (argc > 3)           /* extraneous args */
     928            return usage();
     929
     930        return cmd.remove(ifname, addr);
     931    }
     932
     933    return usage();
     934}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette