From fe74cffdd670221283dd86834c867dea71e6132a Mon Sep 17 00:00:00 2001
From: Ross Lagerwall <ross.lagerwall@citrix.com>
Date: Fri, 21 Feb 2025 12:40:52 +0000
Subject: [PATCH 2/2] Fix handling multiple designators in VPD page
A VPD 0x83 page may have both an EUI-64 designator as well as an NAA
designator. The code attempts to put them in the same buffer which
results in a weird concatenated, truncated id like this:
0x600a098038313577792450384a4a62750x2450384a4a62750000a09838313
Instead, prefer NAA, then EUI-64, then SCSI name string. Also guard
against the same designator appearing multiple times.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
scsicmds.cpp | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/scsicmds.cpp b/scsicmds.cpp
index e5e26851685a..ecae021cf6e4 100644
a
|
b
|
scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len,
|
740 | 740 | return (k == page_len) ? -1 : -2; |
741 | 741 | } |
742 | 742 | |
743 | | /* Decode VPD page 0x83 logical unit designator into a string. If both |
744 | | * numeric address and SCSI name string present, prefer the former. |
| 743 | /* Decode VPD page 0x83 logical unit designator into a string. If multiple |
| 744 | * designators are present, the order of preference is NAA, EUI-64, SCSI name |
| 745 | * string. |
745 | 746 | * Returns 0 on success, -1 on error with error string in s. */ |
746 | 747 | int |
747 | 748 | scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen, |
… |
… |
scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
|
758 | 759 | #define SLEN(a, b) ((a) > (b) ? ((a) - (b)) : 0) |
759 | 760 | s[0] = '\0'; |
760 | 761 | int si = 0; |
761 | | int have_scsi_ns = 0; |
| 762 | int have_scsi_ns = 0, have_eui_64 = 0, have_naa = 0; |
762 | 763 | int off = -1; |
763 | 764 | int u; |
764 | 765 | while ((u = scsi_vpd_dev_id_iter(b, blen, &off, -1, -1, -1)) == 0) { |
… |
… |
scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
|
787 | 788 | snprintf(s+si, SLEN(slen, si), "error: EUI-64 length"); |
788 | 789 | return -1; |
789 | 790 | } |
| 791 | if (have_eui_64) { |
| 792 | snprintf(s+si, SLEN(slen, si), "error: Duplicate EUI-64 designator"); |
| 793 | return -1; |
| 794 | } |
| 795 | if (have_naa) |
| 796 | continue; |
790 | 797 | if (have_scsi_ns) |
791 | 798 | si = 0; |
792 | 799 | si += snprintf(s+si, SLEN(slen, si), "0x"); |
793 | 800 | for (int m = 0; m < i_len; ++m) |
794 | 801 | si += snprintf(s+si, SLEN(slen, si), "%02x", (unsigned int)ip[m]); |
| 802 | have_eui_64++; |
795 | 803 | break; |
796 | 804 | case 3: /* NAA */ |
797 | 805 | if (1 != c_set) { |
… |
… |
scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
|
803 | 811 | snprintf(s+si, SLEN(slen, si), "error: unexpected NAA"); |
804 | 812 | return -1; |
805 | 813 | } |
806 | | if (have_scsi_ns) |
| 814 | if (have_naa) { |
| 815 | snprintf(s+si, SLEN(slen, si), "error: Duplicate NAA designator"); |
| 816 | return -1; |
| 817 | } |
| 818 | if (have_eui_64 || have_scsi_ns) |
807 | 819 | si = 0; |
808 | 820 | if (2 == naa) { /* NAA IEEE Extended */ |
809 | 821 | if (8 != i_len) { |
… |
… |
scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
|
831 | 843 | for (int m = 0; m < 16; ++m) |
832 | 844 | si += snprintf(s+si, SLEN(slen, si), "%02x", (unsigned int)ip[m]); |
833 | 845 | } |
| 846 | have_naa++; |
834 | 847 | break; |
835 | 848 | case 4: /* Relative target port */ |
836 | 849 | case 5: /* (primary) Target port group */ |
… |
… |
scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
|
842 | 855 | snprintf(s+si, SLEN(slen, si), "error: SCSI name string"); |
843 | 856 | return -1; |
844 | 857 | } |
845 | | /* does %s print out UTF-8 ok?? */ |
846 | | if (si == 0) { |
847 | | si += snprintf(s+si, SLEN(slen, si), "%s", (const char *)ip); |
848 | | ++have_scsi_ns; |
| 858 | if (have_scsi_ns) { |
| 859 | snprintf(s+si, SLEN(slen, si), "error: Duplicate SCSI name string designator"); |
| 860 | return -1; |
849 | 861 | } |
| 862 | if (have_eui_64 || have_naa) |
| 863 | continue; |
| 864 | /* does %s print out UTF-8 ok?? */ |
| 865 | si += snprintf(s+si, SLEN(slen, si), "%s", (const char *)ip); |
| 866 | ++have_scsi_ns; |
850 | 867 | break; |
851 | 868 | default: /* reserved */ |
852 | 869 | break; |