1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "Error.h"
18
19 #include "../MessageDefinition.h"
20
21 #include <libnl++/printer.h>
22
23 #include <map>
24
25 #include <linux/netlink.h>
26 #ifndef _UAPI__LINUX_NETLINK_H
27 // linux_glibc (host) includes source headers instead of uapi headers
28 enum nlmsgerr_attrs {
29 NLMSGERR_ATTR_UNUSED,
30 NLMSGERR_ATTR_MSG,
31 NLMSGERR_ATTR_OFFS,
32 NLMSGERR_ATTR_COOKIE,
33 };
34 #endif
35
36 namespace android::nl::protocols::base {
37
38 using DataType = AttributeDefinition::DataType;
39
40 // clang-format off
Error(int protocol)41 Error::Error(int protocol) : MessageDefinition<nlmsgerr>("nlmsg", {
42 {NLMSG_ERROR, {"ERROR", MessageGenre::Ack}},
43 }, {
44 {NLMSGERR_ATTR_MSG, {"MSG", DataType::String}},
45 {NLMSGERR_ATTR_OFFS, {"OFFS", DataType::Uint}},
46 {NLMSGERR_ATTR_COOKIE, {"COOKIE", DataType::Raw}},
47 }), mProtocol(protocol) {}
48 // clang-format on
49
50 std::map<int, std::string> errnoNames{
51 {EPERM, "EPERM"}, // Operation not permitted
52 {ENOENT, "ENOENT"}, // No such file or directory
53 {ESRCH, "ESRCH"}, // No such process
54 {EINTR, "EINTR"}, // Interrupted system call
55 {EIO, "EIO"}, // I/O error
56 {ENXIO, "ENXIO"}, // No such device or address
57 {E2BIG, "E2BIG"}, // Argument list too long
58 {ENOEXEC, "ENOEXEC"}, // Exec format error
59 {EBADF, "EBADF"}, // Bad file number
60 {ECHILD, "ECHILD"}, // No child processes
61 {EAGAIN, "EAGAIN"}, // Try again
62 {ENOMEM, "ENOMEM"}, // Out of memory
63 {EACCES, "EACCES"}, // Permission denied
64 {EFAULT, "EFAULT"}, // Bad address
65 {ENOTBLK, "ENOTBLK"}, // Block device required
66 {EBUSY, "EBUSY"}, // Device or resource busy
67 {EEXIST, "EEXIST"}, // File exists
68 {EXDEV, "EXDEV"}, // Cross-device link
69 {ENODEV, "ENODEV"}, // No such device
70 {ENOTDIR, "ENOTDIR"}, // Not a directory
71 {EISDIR, "EISDIR"}, // Is a directory
72 {EINVAL, "EINVAL"}, // Invalid argument
73 {ENFILE, "ENFILE"}, // File table overflow
74 {EMFILE, "EMFILE"}, // Too many open files
75 {ENOTTY, "ENOTTY"}, // Not a typewriter
76 {ETXTBSY, "ETXTBSY"}, // Text file busy
77 {EFBIG, "EFBIG"}, // File too large
78 {ENOSPC, "ENOSPC"}, // No space left on device
79 {ESPIPE, "ESPIPE"}, // Illegal seek
80 {EROFS, "EROFS"}, // Read-only file system
81 {EMLINK, "EMLINK"}, // Too many links
82 {EPIPE, "EPIPE"}, // Broken pipe
83 {EDOM, "EDOM"}, // Math argument out of domain of func
84 {ERANGE, "ERANGE"}, // Math result not representable
85 {EDEADLK, "EDEADLK"}, // Resource deadlock would occur
86 {ENAMETOOLONG, "ENAMETOOLONG"}, // File name too long
87 {ENOLCK, "ENOLCK"}, // No record locks available
88 {ENOSYS, "ENOSYS"}, // Invalid system call number
89 {ENOTEMPTY, "ENOTEMPTY"}, // Directory not empty
90 {ELOOP, "ELOOP"}, // Too many symbolic links encountered
91 {ENOMSG, "ENOMSG"}, // No message of desired type
92 {EIDRM, "EIDRM"}, // Identifier removed
93 {ECHRNG, "ECHRNG"}, // Channel number out of range
94 {EL2NSYNC, "EL2NSYNC"}, // Level 2 not synchronized
95 {EL3HLT, "EL3HLT"}, // Level 3 halted
96 {EL3RST, "EL3RST"}, // Level 3 reset
97 {ELNRNG, "ELNRNG"}, // Link number out of range
98 {EUNATCH, "EUNATCH"}, // Protocol driver not attached
99 {ENOCSI, "ENOCSI"}, // No CSI structure available
100 {EL2HLT, "EL2HLT"}, // Level 2 halted
101 {EBADE, "EBADE"}, // Invalid exchange
102 {EBADR, "EBADR"}, // Invalid request descriptor
103 {EXFULL, "EXFULL"}, // Exchange full
104 {ENOANO, "ENOANO"}, // No anode
105 {EBADRQC, "EBADRQC"}, // Invalid request code
106 {EBADSLT, "EBADSLT"}, // Invalid slot
107 {EBFONT, "EBFONT"}, // Bad font file format
108 {ENOSTR, "ENOSTR"}, // Device not a stream
109 {ENODATA, "ENODATA"}, // No data available
110 {ETIME, "ETIME"}, // Timer expired
111 {ENOSR, "ENOSR"}, // Out of streams resources
112 {ENONET, "ENONET"}, // Machine is not on the network
113 {ENOPKG, "ENOPKG"}, // Package not installed
114 {EREMOTE, "EREMOTE"}, // Object is remote
115 {ENOLINK, "ENOLINK"}, // Link has been severed
116 {EADV, "EADV"}, // Advertise error
117 {ESRMNT, "ESRMNT"}, // Srmount error
118 {ECOMM, "ECOMM"}, // Communication error on send
119 {EPROTO, "EPROTO"}, // Protocol error
120 {EMULTIHOP, "EMULTIHOP"}, // Multihop attempted
121 {EDOTDOT, "EDOTDOT"}, // RFS specific error
122 {EBADMSG, "EBADMSG"}, // Not a data message
123 {EOVERFLOW, "EOVERFLOW"}, // Value too large for defined data type
124 {ENOTUNIQ, "ENOTUNIQ"}, // Name not unique on network
125 {EBADFD, "EBADFD"}, // File descriptor in bad state
126 {EREMCHG, "EREMCHG"}, // Remote address changed
127 {ELIBACC, "ELIBACC"}, // Can not access a needed shared library
128 {ELIBBAD, "ELIBBAD"}, // Accessing a corrupted shared library
129 {ELIBSCN, "ELIBSCN"}, // .lib section in a.out corrupted
130 {ELIBMAX, "ELIBMAX"}, // Attempting to link in too many shared libraries
131 {ELIBEXEC, "ELIBEXEC"}, // Cannot exec a shared library directly
132 {EILSEQ, "EILSEQ"}, // Illegal byte sequence
133 {ERESTART, "ERESTART"}, // Interrupted system call should be restarted
134 {ESTRPIPE, "ESTRPIPE"}, // Streams pipe error
135 {EUSERS, "EUSERS"}, // Too many users
136 {ENOTSOCK, "ENOTSOCK"}, // Socket operation on non-socket
137 {EDESTADDRREQ, "EDESTADDRREQ"}, // Destination address required
138 {EMSGSIZE, "EMSGSIZE"}, // Message too long
139 {EPROTOTYPE, "EPROTOTYPE"}, // Protocol wrong type for socket
140 {ENOPROTOOPT, "ENOPROTOOPT"}, // Protocol not available
141 {EPROTONOSUPPORT, "EPROTONOSUPPORT"}, // Protocol not supported
142 {ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT"}, // Socket type not supported
143 {EOPNOTSUPP, "EOPNOTSUPP"}, // Operation not supported on transport endpoint
144 {EPFNOSUPPORT, "EPFNOSUPPORT"}, // Protocol family not supported
145 {EAFNOSUPPORT, "EAFNOSUPPORT"}, // Address family not supported by protocol
146 {EADDRINUSE, "EADDRINUSE"}, // Address already in use
147 {EADDRNOTAVAIL, "EADDRNOTAVAIL"}, // Cannot assign requested address
148 {ENETDOWN, "ENETDOWN"}, // Network is down
149 {ENETUNREACH, "ENETUNREACH"}, // Network is unreachable
150 {ENETRESET, "ENETRESET"}, // Network dropped connection because of reset
151 {ECONNABORTED, "ECONNABORTED"}, // Software caused connection abort
152 {ECONNRESET, "ECONNRESET"}, // Connection reset by peer
153 {ENOBUFS, "ENOBUFS"}, // No buffer space available
154 {EISCONN, "EISCONN"}, // Transport endpoint is already connected
155 {ENOTCONN, "ENOTCONN"}, // Transport endpoint is not connected
156 {ESHUTDOWN, "ESHUTDOWN"}, // Cannot send after transport endpoint shutdown
157 {ETOOMANYREFS, "ETOOMANYREFS"}, // Too many references: cannot splice
158 {ETIMEDOUT, "ETIMEDOUT"}, // Connection timed out
159 {ECONNREFUSED, "ECONNREFUSED"}, // Connection refused
160 {EHOSTDOWN, "EHOSTDOWN"}, // Host is down
161 {EHOSTUNREACH, "EHOSTUNREACH"}, // No route to host
162 {EALREADY, "EALREADY"}, // Operation already in progress
163 {EINPROGRESS, "EINPROGRESS"}, // Operation now in progress
164 {ESTALE, "ESTALE"}, // Stale file handle
165 {EUCLEAN, "EUCLEAN"}, // Structure needs cleaning
166 {ENOTNAM, "ENOTNAM"}, // Not a XENIX named type file
167 {ENAVAIL, "ENAVAIL"}, // No XENIX semaphores available
168 {EISNAM, "EISNAM"}, // Is a named type file
169 {EREMOTEIO, "EREMOTEIO"}, // Remote I/O error
170 {EDQUOT, "EDQUOT"}, // Quota exceeded
171 {ENOMEDIUM, "ENOMEDIUM"}, // No medium found
172 {EMEDIUMTYPE, "EMEDIUMTYPE"}, // Wrong medium type
173 {ECANCELED, "ECANCELED"}, // Operation Canceled
174 {ENOKEY, "ENOKEY"}, // Required key not available
175 {EKEYEXPIRED, "EKEYEXPIRED"}, // Key has expired
176 {EKEYREVOKED, "EKEYREVOKED"}, // Key has been revoked
177 {EKEYREJECTED, "EKEYREJECTED"}, // Key was rejected by service
178 {EOWNERDEAD, "EOWNERDEAD"}, // Owner died
179 {ENOTRECOVERABLE, "ENOTRECOVERABLE"}, // State not recoverable
180 {ERFKILL, "ERFKILL"}, // Operation not possible due to RF-kill
181 {EHWPOISON, "EHWPOISON"}, // Memory page has hardware error
182
183 // Duplicates: EWOULDBLOCK (Operation would block), EDEADLOCK
184 };
185
toStream(std::stringstream & ss,const nlmsgerr & data) const186 void Error::toStream(std::stringstream& ss, const nlmsgerr& data) const {
187 ss << "nlmsgerr{";
188 if (data.error == 0) {
189 ss << "ACK";
190 } else {
191 ss << "error=";
192 const auto nameIt = errnoNames.find(-data.error);
193 if (nameIt == errnoNames.end()) {
194 ss << data.error;
195 } else {
196 ss << nameIt->second;
197 }
198 }
199 ss << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol, false) << "}";
200 }
201
202 } // namespace android::nl::protocols::base
203