"Fossies" - the Fresh Open Source Software Archive

Member "open-fcoe-3.19/fcoe-utils/fcnsq.c" (15 Apr 2015, 10546 Bytes) of package /linux/misc/open-fcoe-3.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fcnsq.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.11_vs_3.19.

    1 /*
    2  * Copyright(c) 2009 Intel Corporation. All rights reserved.
    3  *
    4  * This program is free software; you can redistribute it and/or modify it
    5  * under the terms and conditions of the GNU General Public License,
    6  * version 2, as published by the Free Software Foundation.
    7  *
    8  * This program is distributed in the hope it will be useful, but WITHOUT
    9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   11  * more details.
   12  *
   13  * You should have received a copy of the GNU General Public License along with
   14  * this program; if not, write to the Free Software Foundation, Inc.,
   15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   16  *
   17  * Maintained at www.Open-FCoE.org
   18  */
   19 
   20 #define _GNU_SOURCE
   21 #include <stdio.h>
   22 #include <stdint.h>
   23 #include <stdlib.h>
   24 #include <stdarg.h>
   25 #include <stdbool.h>
   26 #include <unistd.h>
   27 #include <inttypes.h>
   28 #include <string.h>
   29 #include <errno.h>
   30 #include <fcntl.h>
   31 #include <getopt.h>
   32 #include <arpa/inet.h>
   33 #include <sys/types.h>
   34 #include <sys/ioctl.h>
   35 #include <sys/stat.h>
   36 #include <linux/types.h>
   37 typedef __u8 u8;
   38 typedef __u16 u16;
   39 typedef __u32 u32;
   40 typedef __u64 u64;
   41 #include <linux/bsg.h>
   42 #include <scsi/sg.h>
   43 #include "fc_gs.h"
   44 #include "fc_ns.h"
   45 #include "scsi_bsg_fc.h"
   46 
   47 static bool quiet = false;
   48 
   49 __attribute__((__format__(__printf__, 2, 3)))
   50 static int print_result(const char *prefix, const char *format, ...)
   51 {
   52     va_list ap;
   53     int rc;
   54 
   55     va_start(ap, format);
   56     if (!quiet)
   57         printf("%s: ", prefix);
   58     rc = vprintf(format, ap);
   59     va_end(ap);
   60     return rc;
   61 }
   62 
   63 __attribute__((__format__(__printf__, 1, 2)))
   64 static int print_err(const char *format, ...)
   65 {
   66     va_list ap;
   67     int rc;
   68 
   69     if (quiet)
   70         return 0;
   71     va_start(ap, format);
   72     rc = vprintf(format, ap);
   73     va_end(ap);
   74     return rc;
   75 }
   76 
   77 #define ntoh24(n) (u32) ((n)[0] << 16 | (n)[1] << 8  | (n)[2])
   78 #define hton24(h) { (h) >> 16 & 0xff, (h) >> 8 & 0xff, (h) & 0xff }
   79 
   80 static u64 ntohll(u64 netll)
   81 {
   82     u8 *_netll = (u8 *)&netll;
   83     return  (u64) _netll[0] << (7 * 8) |
   84         (u64) _netll[1] << (6 * 8) |
   85         (u64) _netll[2] << (5 * 8) |
   86         (u64) _netll[3] << (4 * 8) |
   87         (u64) _netll[4] << (3 * 8) |
   88         (u64) _netll[5] << (2 * 8) |
   89         (u64) _netll[6] << (1 * 8) |
   90         (u64) _netll[7];
   91 }
   92 
   93 static u64 htonll(u64 hostll)
   94 {
   95     u64 netll;
   96     u8 *_netll = (u8 *)&netll;
   97     _netll[0] = hostll >> (7 * 8) & 0xff;
   98     _netll[1] = hostll >> (6 * 8) & 0xff;
   99     _netll[2] = hostll >> (5 * 8) & 0xff;
  100     _netll[3] = hostll >> (4 * 8) & 0xff;
  101     _netll[4] = hostll >> (3 * 8) & 0xff;
  102     _netll[5] = hostll >> (2 * 8) & 0xff;
  103     _netll[6] = hostll >> (1 * 8) & 0xff;
  104     _netll[7] = hostll & 0xff;
  105     return netll;
  106 }
  107 
  108 static char* rjt_reason[] = {
  109     [1] = "Invalid command code",
  110     [2] = "Invalid version level",
  111     [3] = "Logical error",
  112     [4] = "Invalid CT_IU size",
  113     [5] = "Logical busy",
  114     [7] = "Protocol error",
  115     [9] = "Unable to perform command request",
  116     [0xB] = "Command not supported",
  117     [0xD] = "Server not available",
  118     [0xE] = "Session could not be established",
  119 };
  120 
  121 static char* rjt_explan[] = {
  122     [0] = "No additional explanation",
  123     [1] = "Port Identifier not registered",
  124     [2] = "Port Name not registered",
  125     [3] = "Node Name not registered",
  126     [4] = "Class of Service not registered",
  127     [6] = "Initial Process Associator not registered",
  128     [7] = "FC-4 Types not registered",
  129     [8] = "Symbolic Port Name not registered",
  130     [9] = "Symbolic Node Name not registered",
  131     [0xA] = "Port Type not registered",
  132     [0xC] = "Fabric Port Name not registered",
  133     [0xD] = "Hard Address not registered",
  134     [0xF] = "FC-4 Features not registered",
  135     [0x10] = "Access denied",
  136     [0x11] = "Unacceptable Port Identifier",
  137     [0x12] = "Data base empty",
  138     [0x13] = "No object registered in the specified scope",
  139     [0x14] = "Domain ID not present",
  140     [0x15] = "Port number not present",
  141     [0x16] = "No device attached",
  142     [0xf0] = "Authorization Exception",
  143     [0xf1] = "Authentication Exception",
  144     [0xf2] = "Data base full",
  145     [0xf3] = "Data base empty",
  146     [0xf4] = "Processing request",
  147     [0xf5] = "Unable to verify connection",
  148     [0xf6] = "Devices not in a common zone",
  149 };
  150 
  151 static u16 ct_rjt(u8 reason, u8 explan) {
  152     return (u16) reason << 8 | explan;
  153 }
  154 
  155 static u8 ct_rjt_reason(u16 rjt) {
  156     return (u8)(rjt >> 8);
  157 }
  158 
  159 static u8 ct_rjt_explan(u16 rjt) {
  160     return (u8) rjt & 0xff;
  161 }
  162 
  163 static int ns_query(int bsg, void *req, int req_len, void *resp, int resp_len)
  164 {
  165     char sense[96];
  166 
  167     struct fc_bsg_request cdb = {
  168         .msgcode    = FC_BSG_HST_CT,
  169         .rqst_data.h_ct = {
  170             .port_id = hton24(0xfffffc),
  171         }
  172     };
  173 
  174     struct sg_io_v4 sgio = {
  175         .guard          = 'Q',
  176         .protocol       = BSG_PROTOCOL_SCSI,
  177         .subprotocol        = BSG_SUB_PROTOCOL_SCSI_TRANSPORT,
  178         .request_len        = sizeof(cdb),
  179         .request        = (uintptr_t) &cdb,
  180         .dout_xfer_len      = req_len,
  181         .dout_xferp     = (uintptr_t) req,
  182         .din_xfer_len       = resp_len,
  183         .din_xferp      = (uintptr_t) resp,
  184         .max_response_len   = sizeof(sense),
  185         .response       = (uintptr_t) &sense,
  186         .timeout        = 1000,
  187     };
  188 
  189     return ioctl(bsg, SG_IO, &sgio);
  190 }
  191 
  192 static u16 gn_id(int bsg, u32 fcid, u16 cmd, u64 *wwn)
  193 {
  194     struct {
  195         struct fc_ct_hdr hdr;
  196         u64 wwn;
  197     } __attribute__((__packed__)) gn_resp;
  198 
  199     struct {
  200         struct fc_ct_hdr hdr;
  201         u8 resv;
  202         u8 port_id[3];
  203     } __attribute__((__packed__)) gn = {
  204         .hdr = {
  205             .ct_rev     = FC_CT_REV,
  206             .ct_fs_type = FC_FST_DIR,
  207             .ct_fs_subtype  = FC_NS_SUBTYPE,
  208             .ct_cmd     = htons(cmd),
  209             .ct_mr_size = htons(sizeof(gn_resp)),
  210             .ct_vendor  = 0,
  211         },
  212         .port_id = hton24(fcid),
  213     };
  214 
  215     if (ns_query(bsg, &gn, sizeof(gn), &gn_resp, sizeof(gn_resp)) < 0)
  216         return ~0;
  217     if (gn_resp.hdr.ct_cmd != htons(FC_FS_ACC))
  218         return ct_rjt(gn_resp.hdr.ct_reason, gn_resp.hdr.ct_explan);
  219     *wwn = ntohll(gn_resp.wwn);
  220     return 0;
  221 }
  222 
  223 #define FC_NS_GPN_ID    0x0112
  224 static int gpn_id(int bsg, u32 fcid)
  225 {
  226     u64 wwpn;
  227     u16 rjt;
  228 
  229     rjt = gn_id(bsg, fcid, FC_NS_GPN_ID, &wwpn);
  230     if (rjt)
  231         goto fail;
  232     print_result("Port Name", "%16.16jx\n", (uintmax_t)wwpn);
  233     return 0;
  234 fail:
  235     if (rjt == (u16) ~0)
  236         print_err("%s ioctl failed: %s\n", __func__, strerror(errno));
  237     else
  238         print_err("%s command failed: %s, %s\n", __func__,
  239               rjt_reason[ct_rjt_reason(rjt)],
  240               rjt_explan[ct_rjt_explan(rjt)]);
  241     return rjt;
  242 }
  243 
  244 #define FC_NS_GNN_ID    0x0113
  245 static int gnn_id(int bsg, u32 fcid)
  246 {
  247     u64 wwnn;
  248     u16 rjt;
  249 
  250     rjt = gn_id(bsg, fcid, FC_NS_GNN_ID, &wwnn);
  251     if (rjt)
  252         goto fail;
  253     print_result("Node Name", "%16.16jx\n", (uintmax_t)wwnn);
  254     return 0;
  255 fail:
  256     if (rjt == (u16) ~0)
  257         print_err("%s ioctl failed: %s\n", __func__, strerror(errno));
  258     else
  259         print_err("%s command failed: %s, %s\n", __func__,
  260               rjt_reason[ct_rjt_reason(rjt)],
  261               rjt_explan[ct_rjt_explan(rjt)]);
  262     return rjt;
  263 }
  264 
  265 #define FC_NS_GSPN_ID   0x0118
  266 static int gspn_id(int bsg, u32 fcid)
  267 {
  268     struct {
  269         struct fc_ct_hdr hdr;
  270         u8 len;
  271         char name[255];
  272     } __attribute__((__packed__)) gspn_resp;
  273 
  274     struct {
  275         struct fc_ct_hdr hdr;
  276         u8 resv;
  277         u8 port_id[3];
  278     } __attribute__((__packed__)) gspn = {
  279         .hdr = {
  280             .ct_rev     = FC_CT_REV,
  281             .ct_fs_type = FC_FST_DIR,
  282             .ct_fs_subtype  = FC_NS_SUBTYPE,
  283             .ct_cmd     = htons(FC_NS_GSPN_ID),
  284             .ct_mr_size = htons(sizeof(gspn_resp)),
  285             .ct_vendor  = 0,
  286         },
  287         .port_id = hton24(fcid),
  288     };
  289 
  290     if (ns_query(bsg, &gspn, sizeof(gspn), &gspn_resp, sizeof(gspn_resp)) < 0) {
  291         print_err("%s ioctl failed: %s\n", __func__, strerror(errno));
  292         return ~0;
  293     }
  294     if (gspn_resp.hdr.ct_cmd != htons(FC_FS_ACC)) {
  295         print_err("%s command failed: %s, %s\n", __func__,
  296               rjt_reason[gspn_resp.hdr.ct_reason],
  297               rjt_explan[gspn_resp.hdr.ct_explan]);
  298         return ct_rjt(gspn_resp.hdr.ct_reason, gspn_resp.hdr.ct_explan);
  299     }
  300     print_result("Symbolic Port Name", "%s\n", gspn_resp.name);
  301     return 0;
  302 }
  303 
  304 #define FC_NS_GSNN_NN   0x0139
  305 static int gsnn_nn(int bsg, u64 wwnn)
  306 {
  307     struct {
  308         struct fc_ct_hdr hdr;
  309         u8 len;
  310         char name[255];
  311     } __attribute__((__packed__)) gsnn_resp;
  312 
  313     struct {
  314         struct fc_ct_hdr hdr;
  315         u64 wwnn;
  316     } __attribute__((__packed__)) gsnn = {
  317         .hdr = {
  318             .ct_rev     = FC_CT_REV,
  319             .ct_fs_type = FC_FST_DIR,
  320             .ct_fs_subtype  = FC_NS_SUBTYPE,
  321             .ct_cmd     = htons(FC_NS_GSNN_NN),
  322             .ct_mr_size = htons(sizeof(gsnn_resp)),
  323             .ct_vendor  = 0,
  324         },
  325         .wwnn = htonll(wwnn),
  326     };
  327 
  328     if (ns_query(bsg, &gsnn, sizeof(gsnn), &gsnn_resp, sizeof(gsnn_resp)) < 0) {
  329         print_err("%s ioctl failed: %s\n", __func__, strerror(errno));
  330         return ~0;
  331     }
  332     if (gsnn_resp.hdr.ct_cmd != htons(FC_FS_ACC)) {
  333         print_err("%s command failed: %s, %s\n", __func__,
  334               rjt_reason[gsnn_resp.hdr.ct_reason],
  335               rjt_explan[gsnn_resp.hdr.ct_explan]);
  336         return ct_rjt(gsnn_resp.hdr.ct_reason, gsnn_resp.hdr.ct_explan);
  337     }
  338     print_result("Symbolic Node Name", "%s\n", gsnn_resp.name);
  339     return 0;
  340 }
  341 
  342 enum commands {
  343     NONE = 0,
  344     GPN_ID,
  345     GNN_ID,
  346     GSPN_ID,
  347     GSNN_NN,
  348 };
  349 
  350 static const struct option options[] = {
  351     { "gpn", required_argument, NULL, GPN_ID },
  352     { "gnn", required_argument, NULL, GNN_ID },
  353     { "gspn", required_argument, NULL, GSPN_ID },
  354     { "gsnn", required_argument, NULL, GSNN_NN },
  355     { "quiet", no_argument, NULL, 'q' },
  356     { NULL, 0, NULL, 0 },
  357 };
  358 
  359 static void help(int status)
  360 {
  361     printf(
  362         "Usage: fcnsq <host#> <command> [options]\n"
  363         "Commands:\n"
  364         "  --gpn  <port id>\n"
  365         "  --gnn  <port id>\n"
  366         "  --gspn <port id>\n"
  367         "  --gsnn <world wide node name>\n"
  368         "Options:\n"
  369         "  --quiet|-q   print minimal results on success, and no error messages\n"
  370         "\n"
  371         "Port IDs and World Wide Names must be specified in hexadecimal.\n"
  372         );
  373     exit(status);
  374 }
  375 
  376 int main(int argc, char *argv[])
  377 {
  378     char *bsg;
  379     int bsg_dev;
  380     u32 port_id = 0;
  381     u64 wwnn = 0;
  382     int rc = 0;
  383     enum commands cmd = 0;
  384     char c;
  385     uintmax_t wwnn_tmp = 0;
  386 
  387     while(1) {
  388         c = getopt_long_only(argc, argv, "", options, NULL);
  389         if (c < 0)
  390             break;
  391         switch(c) {
  392         case '?':
  393             help(-1);
  394             break;
  395         case 'q':
  396             quiet = true;
  397             break;
  398         case GPN_ID:
  399         case GNN_ID:
  400         case GSPN_ID:
  401             if (cmd)
  402                 help(-1);
  403             cmd = c;
  404             if (sscanf(optarg, "%x", &port_id) != 1)
  405                 help(-1);
  406             break;
  407         case GSNN_NN:
  408             if (cmd)
  409                 help(-1);
  410             cmd = c;
  411             if (sscanf(optarg, "%jx", &wwnn_tmp) == 1)
  412                 wwnn = (u64)wwnn_tmp;
  413             else
  414                 help(-1);
  415             break;
  416         }
  417     }
  418 
  419     if (cmd == NONE)
  420         help(-1);
  421 
  422     if (asprintf(&bsg, "/dev/bsg/fc_%s", argv[optind]) < 0) {
  423         if (!quiet)
  424             perror(NULL);
  425         return -1;
  426     }
  427     bsg_dev = open(bsg, O_RDWR);
  428     if (bsg_dev < 0) {
  429         if (!quiet)
  430             perror(bsg);
  431         return -1;
  432     }
  433     switch (cmd) {
  434     case GPN_ID:
  435         rc = gpn_id(bsg_dev, port_id);
  436         break;
  437     case GNN_ID:
  438         rc = gnn_id(bsg_dev, port_id);
  439         break;
  440     case GSPN_ID:
  441         rc = gspn_id(bsg_dev, port_id);
  442         break;
  443     case GSNN_NN:
  444         rc = gsnn_nn(bsg_dev, wwnn);
  445         break;
  446     default:
  447         help(-1);
  448         break;
  449     };
  450     close(bsg_dev);
  451     free(bsg);
  452     return rc;
  453 }
  454