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