Skip to content

Commit 415c5b8

Browse files
haryvensmfrench
authored andcommitted
smb/client: autogenerate SMB1 NT status to DOS error mapping
Introduce `gen_smb1_mapping` script to autogenerate the NT status to DOS error mapping table for SMB1. This script parses nterr.h to generate smb1_mapping_table.c, which is then directly included as the content of the ntstatus_to_dos_map[] array at compile time. The generated array is numerically sorted during the build process to ensure a consistent structure, providing the necessary groundwork for future introduction of binary search lookups. Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 378f75b commit 415c5b8

5 files changed

Lines changed: 122 additions & 555 deletions

File tree

fs/smb/client/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
smb1_mapping_table.c
12
smb2_mapping_table.c

fs/smb/client/Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += \
4444

4545
cifs-$(CONFIG_CIFS_COMPRESSION) += compress.o compress/lz77.o
4646

47+
ifneq ($(CONFIG_CIFS_ALLOW_INSECURE_LEGACY),)
48+
#
49+
# Build the SMB1 error mapping tables from nterr.h
50+
#
51+
smb1-gen-y := smb1_mapping_table.c
52+
53+
$(obj)/smb1_mapping_table.c: $(src)/nterr.h $(src)/gen_smb1_mapping FORCE
54+
$(call if_changed,gen_smb1_mapping)
55+
56+
$(obj)/smb1maperror.o: $(addprefix $(obj)/, $(smb1-gen-y))
57+
58+
quiet_cmd_gen_smb1_mapping = GEN $@
59+
cmd_gen_smb1_mapping = perl $(src)/gen_smb1_mapping $< $@
60+
endif
61+
4762
#
4863
# Build the SMB2 error mapping table from smb2status.h
4964
#
@@ -59,4 +74,4 @@ quiet_cmd_gen_smb2_mapping = GEN $@
5974
obj-$(CONFIG_SMB_KUNIT_TESTS) += smb2maperror_test.o
6075

6176
# Let Kbuild handle tracking and cleaning
62-
targets += smb2_mapping_table.c
77+
targets += smb2_mapping_table.c $(smb1-gen-y)

fs/smb/client/gen_smb1_mapping

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/perl -w
2+
# SPDX-License-Identifier: GPL-2.0-or-later
3+
#
4+
# Script to generate SMB1 error mapping tables.
5+
#
6+
# Copyright (C) 2026 KylinSoft Co., Ltd. All rights reserved.
7+
# Author(s): Huiwen He <hehuiwen@kylinos.cn>
8+
# ChenXiaoSong <chenxiaosong@kylinos.cn>
9+
#
10+
use strict;
11+
12+
if ($#ARGV != 1) {
13+
print STDERR "Usage: $0 <in-file> <out-file>\n";
14+
exit(2);
15+
}
16+
17+
# Parse input parameters and extract filenames
18+
my $in_file = $ARGV[0];
19+
my $out_file = $ARGV[1];
20+
my $input_name = (split m|/|, $in_file)[-1];
21+
my $output_name = (split m|/|, $out_file)[-1];
22+
my $script_name = (split m|/|, $0)[-1];
23+
my @list = ();
24+
my %seen = ();
25+
26+
# Parse annotated entries from the input file
27+
open(my $in, "<", $in_file) or die "Cannot open $in_file: $!";
28+
if ($in_file =~ /nterr\.h$/) {
29+
while (<$in>) {
30+
# Handle backslash line continuation
31+
$_ .= <$in> while s/\\\s*\n//;
32+
33+
# Match #define NT_STATUS_... followed by // CLASS, CODE or /* CLASS, CODE */
34+
my $re = qr{^\s*#define\s+(NT_STATUS_[A-Za-z0-9_]+)\s+(.+?)\s*} .
35+
qr{(?://\s*|/\*\s*)([A-Z0-9_]+)\s*,\s*([A-Za-z0-9_]+)};
36+
37+
if (/$re/) {
38+
my ($name, $val_str, $class, $code) = ($1, $2, $3, $4);
39+
40+
# Skip duplicate macro names
41+
next if $seen{$name}++;
42+
43+
# Clean up value string (remove parens, spaces)
44+
$val_str =~ s/[\s\(\)]//g;
45+
my $val = 0;
46+
foreach my $part (split(/\|/, $val_str)) {
47+
$val |= hex($part);
48+
}
49+
push @list, { val => $val, name => $name, class => $class, code => $code };
50+
} elsif (/^\s*#define\s+NT_STATUS_.*(?:\/\/|\/\*)/) {
51+
# Error if macro has a comment (// or /*) but fails mapping format
52+
die "Error: Invalid mapping comment format in $in_file: $_";
53+
}
54+
}
55+
}
56+
close($in);
57+
58+
# Fail if no entries were found to avoid broken builds
59+
die "Error: No mapping entries found in $in_file\n" unless @list;
60+
61+
# Sort entries numerically by value
62+
@list = sort { $a->{val} <=> $b->{val} } @list;
63+
64+
# Generate the C mapping table output file
65+
open(my $out, ">", $out_file) or die "Cannot open $out_file: $!";
66+
print $out "/* Autogenerated from $input_name by $script_name */\n\n";
67+
68+
if ($output_name eq "smb1_mapping_table.c") {
69+
# Generate NT status -> DOS error mapping file
70+
71+
my $count = scalar @list;
72+
my $full_names = "";
73+
74+
for (my $i = 0; $i < $count; $i++) {
75+
my $e = $list[$i];
76+
my $val = $e->{val};
77+
78+
$full_names .= $e->{name};
79+
80+
# Merge synonyms
81+
if ($i < $count - 1 && $list[$i + 1]->{val} == $val) {
82+
$full_names .= " or ";
83+
next;
84+
}
85+
86+
printf $out "\t{ %s, %s, 0x%08x, \"%s\" },\n", $e->{class}, $e->{code}, $val, $full_names;
87+
88+
$full_names = "";
89+
}
90+
}
91+
close($out);

fs/smb/client/nterr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ extern const struct nt_err_code_struct nt_errs[];
3030
/*
3131
* NTSTATUS Values extracted using a loop in smbclient then printing a netmon
3232
* sniff to a file.
33+
*
34+
* The comment at the end of each definition indicates `dos_class`
35+
* and `dos_code` fields of the `ntstatus_to_dos_map` array; it is
36+
* used to generate the `smb1_mapping_table.c` file.
3337
*/
3438

3539
#define NT_STATUS_OK 0x0000 // SUCCESS, 0

0 commit comments

Comments
 (0)