Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 Cisco and/or its affiliates. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | /* |
| 16 | Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus |
| 17 | |
| 18 | Permission is hereby granted, free of charge, to any person obtaining |
| 19 | a copy of this software and associated documentation files (the |
| 20 | "Software"), to deal in the Software without restriction, including |
| 21 | without limitation the rights to use, copy, modify, merge, publish, |
| 22 | distribute, sublicense, and/or sell copies of the Software, and to |
| 23 | permit persons to whom the Software is furnished to do so, subject to |
| 24 | the following conditions: |
| 25 | |
| 26 | The above copyright notice and this permission notice shall be |
| 27 | included in all copies or substantial portions of the Software. |
| 28 | |
| 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 33 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 34 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 36 | */ |
| 37 | |
| 38 | #ifdef __KERNEL__ |
| 39 | |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 40 | #if __linux__ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 41 | # include <linux/unistd.h> |
| 42 | # include <linux/signal.h> |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 43 | #endif |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 44 | |
| 45 | #else /* ! __KERNEL__ */ |
| 46 | |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 47 | #ifdef __APPLE__ |
| 48 | #define _XOPEN_SOURCE |
| 49 | #endif |
| 50 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 51 | #define _GNU_SOURCE /* to get REG_* in ucontext.h */ |
| 52 | #include <ucontext.h> |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 53 | #undef __USE_GNU |
| 54 | |
| 55 | #include <unistd.h> |
| 56 | #include <signal.h> |
Damjan Marion | a54230d | 2017-06-21 11:57:07 +0200 | [diff] [blame] | 57 | #include <grp.h> |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 58 | |
| 59 | #include <time.h> |
| 60 | #include <sys/socket.h> |
| 61 | #include <netdb.h> |
| 62 | #include <math.h> |
| 63 | |
| 64 | #include <vppinfra/time.h> |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 65 | #if __linux__ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 66 | #ifdef AF_NETLINK |
| 67 | #include <linux/types.h> |
| 68 | #include <linux/netlink.h> |
| 69 | #endif |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 70 | #endif |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 71 | |
| 72 | #endif /* ! __KERNEL__ */ |
| 73 | |
| 74 | |
| 75 | #ifdef __KERNEL__ |
| 76 | # include <linux/socket.h> |
| 77 | # include <linux/in.h> |
| 78 | # include <linux/ip.h> |
| 79 | # include <linux/tcp.h> |
| 80 | # include <linux/udp.h> |
| 81 | # include <linux/icmp.h> |
| 82 | # include <linux/if_ether.h> |
| 83 | # include <linux/if_arp.h> |
| 84 | #else |
| 85 | # include <net/if.h> /* struct ifnet may live here */ |
| 86 | # include <netinet/in.h> |
| 87 | # include <netinet/ip.h> |
| 88 | # include <netinet/tcp.h> |
| 89 | # include <netinet/udp.h> |
| 90 | # include <netinet/ip_icmp.h> |
| 91 | # include <netinet/if_ether.h> |
| 92 | #endif /* __KERNEL__ */ |
| 93 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 94 | #include <vppinfra/format.h> |
| 95 | #include <vppinfra/error.h> |
| 96 | |
| 97 | /* Format unix network address family (e.g. AF_INET). */ |
| 98 | u8 * format_address_family (u8 * s, va_list * va) |
| 99 | { |
| 100 | uword family = va_arg (*va, uword); |
| 101 | u8 * t = (u8 *) "UNKNOWN"; |
| 102 | switch (family) |
| 103 | { |
| 104 | #define _(x) case PF_##x: t = (u8 *) #x; break |
| 105 | _ (UNSPEC); |
| 106 | _ (UNIX); /* Unix domain sockets */ |
| 107 | _ (INET); /* Internet IP Protocol */ |
| 108 | #ifdef PF_AX25 |
| 109 | _ (AX25); /* Amateur Radio AX.25 */ |
| 110 | #endif |
| 111 | #ifdef PF_IPX |
| 112 | _ (IPX); /* Novell IPX */ |
| 113 | #endif |
| 114 | #ifdef PF_APPLETALK |
| 115 | _ (APPLETALK); /* AppleTalk DDP */ |
| 116 | #endif |
| 117 | #ifdef PF_NETROM |
| 118 | _ (NETROM); /* Amateur Radio NET/ROM */ |
| 119 | #endif |
| 120 | #ifdef PF_BRIDGE |
| 121 | _ (BRIDGE); /* Multiprotocol bridge */ |
| 122 | #endif |
| 123 | #ifdef PF_ATMPVC |
| 124 | _ (ATMPVC); /* ATM PVCs */ |
| 125 | #endif |
| 126 | #ifdef PF_X25 |
| 127 | _ (X25); /* Reserved for X.25 project */ |
| 128 | #endif |
| 129 | #ifdef PF_INET6 |
| 130 | _ (INET6); /* IP version 6 */ |
| 131 | #endif |
| 132 | #ifdef PF_ROSE |
| 133 | _ (ROSE); /* Amateur Radio X.25 PLP */ |
| 134 | #endif |
| 135 | #ifdef PF_DECnet |
| 136 | _ (DECnet); /* Reserved for DECnet project */ |
| 137 | #endif |
| 138 | #ifdef PF_NETBEUI |
| 139 | _ (NETBEUI); /* Reserved for 802.2LLC project*/ |
| 140 | #endif |
| 141 | #ifdef PF_SECURITY |
| 142 | _ (SECURITY); /* Security callback pseudo AF */ |
| 143 | #endif |
| 144 | #ifdef PF_KEY |
| 145 | _ (KEY); /* PF_KEY key management API */ |
| 146 | #endif |
| 147 | #ifdef PF_NETLINK |
| 148 | _ (NETLINK); |
| 149 | #endif |
| 150 | #ifdef PF_PACKET |
| 151 | _ (PACKET); /* Packet family */ |
| 152 | #endif |
| 153 | #ifdef PF_ASH |
| 154 | _ (ASH); /* Ash */ |
| 155 | #endif |
| 156 | #ifdef PF_ECONET |
| 157 | _ (ECONET); /* Acorn Econet */ |
| 158 | #endif |
| 159 | #ifdef PF_ATMSVC |
| 160 | _ (ATMSVC); /* ATM SVCs */ |
| 161 | #endif |
| 162 | #ifdef PF_SNA |
| 163 | _ (SNA); /* Linux SNA Project */ |
| 164 | #endif |
| 165 | #ifdef PF_IRDA |
| 166 | _ (IRDA); /* IRDA sockets */ |
| 167 | #endif |
| 168 | #undef _ |
| 169 | } |
| 170 | vec_add (s, t, strlen ((char *) t)); |
| 171 | return s; |
| 172 | } |
| 173 | |
| 174 | u8 * format_network_protocol (u8 * s, va_list * args) |
| 175 | { |
| 176 | uword family = va_arg (*args, uword); |
| 177 | uword protocol = va_arg (*args, uword); |
| 178 | |
| 179 | #ifndef __KERNEL__ |
| 180 | struct protoent * p = getprotobynumber (protocol); |
| 181 | |
| 182 | ASSERT (family == AF_INET); |
| 183 | if (p) |
| 184 | return format (s, "%s", p->p_name); |
| 185 | else |
| 186 | return format (s, "%d", protocol); |
| 187 | #else |
| 188 | return format (s, "%d/%d", family, protocol); |
| 189 | #endif |
| 190 | } |
| 191 | |
| 192 | u8 * format_network_port (u8 * s, va_list * args) |
| 193 | { |
| 194 | uword proto = va_arg (*args, uword); |
| 195 | uword port = va_arg (*args, uword); |
| 196 | |
| 197 | #ifndef __KERNEL__ |
| 198 | struct servent * p = getservbyport (port, proto == IPPROTO_UDP ? "udp" : "tcp"); |
| 199 | |
| 200 | if (p) |
| 201 | return format (s, "%s", p->s_name); |
| 202 | else |
| 203 | return format (s, "%d", port); |
| 204 | #else |
| 205 | return format (s, "%s/%d", proto == IPPROTO_UDP ? "udp" : "tcp", port); |
| 206 | #endif |
| 207 | } |
| 208 | |
| 209 | /* Format generic network address: takes two arguments family and address. |
| 210 | Assumes network byte order. */ |
| 211 | u8 * format_network_address (u8 * s, va_list * args) |
| 212 | { |
| 213 | uword family = va_arg (*args, uword); |
| 214 | u8 * addr = va_arg (*args, u8 *); |
| 215 | |
| 216 | switch (family) |
| 217 | { |
| 218 | case AF_INET: |
| 219 | s = format (s, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); |
| 220 | break; |
| 221 | |
| 222 | case AF_UNSPEC: |
| 223 | /* We use AF_UNSPEC for ethernet addresses. */ |
| 224 | s = format (s, "%02x:%02x:%02x:%02x:%02x:%02x", |
| 225 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); |
| 226 | break; |
| 227 | |
| 228 | default: |
| 229 | clib_error ("unsupported address family %d", family); |
| 230 | } |
| 231 | |
| 232 | return s; |
| 233 | } |
| 234 | |
| 235 | u8 * format_sockaddr (u8 * s, va_list * args) |
| 236 | { |
| 237 | void * v = va_arg (*args, void *); |
| 238 | struct sockaddr * sa = v; |
Dave Barach | f22f07d | 2017-09-19 14:36:46 -0400 | [diff] [blame] | 239 | static u32 local_counter; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 240 | |
| 241 | switch (sa->sa_family) |
| 242 | { |
| 243 | case AF_INET: |
| 244 | { |
| 245 | struct sockaddr_in * i = v; |
| 246 | s = format (s, "%U:%U", |
| 247 | format_network_address, AF_INET, &i->sin_addr.s_addr, |
| 248 | format_network_port, IPPROTO_TCP, ntohs (i->sin_port)); |
| 249 | } |
| 250 | break; |
| 251 | |
Dave Barach | f22f07d | 2017-09-19 14:36:46 -0400 | [diff] [blame] | 252 | case AF_LOCAL: |
| 253 | { |
| 254 | /* |
| 255 | * There isn't anything useful to print. |
| 256 | * The unix cli world uses the output to make a node name, |
| 257 | * so we need to return a unique name. |
| 258 | */ |
| 259 | s = format (s, "local:%u", local_counter++); |
| 260 | } |
| 261 | break; |
| 262 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 263 | #ifndef __KERNEL__ |
| 264 | #ifdef AF_NETLINK |
| 265 | case AF_NETLINK: |
| 266 | { |
| 267 | struct sockaddr_nl * n = v; |
| 268 | s = format (s, "KERNEL-NETLINK"); |
| 269 | if (n->nl_groups) |
| 270 | s = format (s, " (groups 0x%x)", n->nl_groups); |
| 271 | break; |
| 272 | } |
| 273 | #endif |
| 274 | #endif |
| 275 | |
| 276 | default: |
| 277 | s = format (s, "sockaddr family %d", sa->sa_family); |
| 278 | break; |
| 279 | } |
| 280 | |
| 281 | return s; |
| 282 | } |
| 283 | |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 284 | #ifndef __APPLE__ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 285 | |
| 286 | #ifndef __KERNEL__ |
| 287 | u8 * format_timeval (u8 * s, va_list * args) |
| 288 | { |
| 289 | char * fmt = va_arg (*args, char *); |
| 290 | struct timeval * tv = va_arg (*args, struct timeval *); |
| 291 | struct tm * tm; |
| 292 | word msec; |
| 293 | char * f, c; |
| 294 | |
| 295 | if (! fmt) |
| 296 | fmt = "y/m/d H:M:S:F"; |
| 297 | |
| 298 | if (! tv) |
| 299 | { |
| 300 | static struct timeval now; |
| 301 | gettimeofday (&now, 0); |
| 302 | tv = &now; |
| 303 | } |
| 304 | |
| 305 | msec = flt_round_nearest (1e-3 * tv->tv_usec); |
| 306 | if (msec >= 1000) |
| 307 | { msec = 0; tv->tv_sec++; } |
| 308 | |
| 309 | { |
| 310 | time_t t = tv->tv_sec; |
| 311 | tm = localtime (&t); |
| 312 | } |
| 313 | |
| 314 | for (f = fmt; *f; f++) |
| 315 | { |
| 316 | uword what; |
| 317 | char * what_fmt = "%d"; |
| 318 | |
| 319 | switch (c = *f) |
| 320 | { |
| 321 | default: |
| 322 | vec_add1 (s, c); |
| 323 | continue; |
| 324 | |
| 325 | case 'y': |
| 326 | what = 1900 + tm->tm_year; |
| 327 | what_fmt = "%4d"; |
| 328 | break; |
| 329 | case 'm': |
| 330 | what = tm->tm_mon + 1; |
Paul Vinciguerra | 2782630 | 2019-05-09 19:12:18 -0400 | [diff] [blame] | 331 | what_fmt = "%02d"; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 332 | break; |
| 333 | case 'd': |
| 334 | what = tm->tm_mday; |
Paul Vinciguerra | 2782630 | 2019-05-09 19:12:18 -0400 | [diff] [blame] | 335 | what_fmt = "%02d"; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 336 | break; |
| 337 | case 'H': |
| 338 | what = tm->tm_hour; |
| 339 | what_fmt = "%02d"; |
| 340 | break; |
| 341 | case 'M': |
| 342 | what = tm->tm_min; |
| 343 | what_fmt = "%02d"; |
| 344 | break; |
| 345 | case 'S': |
| 346 | what = tm->tm_sec; |
| 347 | what_fmt = "%02d"; |
| 348 | break; |
| 349 | case 'F': |
| 350 | what = msec; |
| 351 | what_fmt = "%03d"; |
| 352 | break; |
| 353 | } |
| 354 | |
| 355 | s = format (s, what_fmt, what); |
| 356 | } |
| 357 | |
| 358 | return s; |
| 359 | } |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 360 | #endif |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 361 | |
| 362 | u8 * format_time_float (u8 * s, va_list * args) |
| 363 | { |
| 364 | u8 * fmt = va_arg (*args, u8 *); |
| 365 | f64 t = va_arg (*args, f64); |
| 366 | struct timeval tv; |
| 367 | if (t <= 0) |
| 368 | t = unix_time_now (); |
| 369 | tv.tv_sec = t; |
| 370 | tv.tv_usec = 1e6*(t - tv.tv_sec); |
| 371 | return format (s, "%U", format_timeval, fmt, &tv); |
| 372 | } |
| 373 | |
| 374 | u8 * format_signal (u8 * s, va_list * args) |
| 375 | { |
| 376 | uword signum = va_arg (*args, uword); |
| 377 | char * t = 0; |
| 378 | switch (signum) |
| 379 | { |
| 380 | #define _(x) case x: t = #x; break; |
| 381 | _ (SIGHUP); |
| 382 | _ (SIGINT); |
| 383 | _ (SIGQUIT); |
| 384 | _ (SIGILL); |
| 385 | _ (SIGTRAP); |
| 386 | _ (SIGABRT); |
| 387 | _ (SIGBUS); |
| 388 | _ (SIGFPE); |
| 389 | _ (SIGKILL); |
| 390 | _ (SIGUSR1); |
| 391 | _ (SIGSEGV); |
| 392 | _ (SIGUSR2); |
| 393 | _ (SIGPIPE); |
| 394 | _ (SIGALRM); |
| 395 | _ (SIGTERM); |
| 396 | #ifdef SIGSTKFLT |
| 397 | _ (SIGSTKFLT); |
| 398 | #endif |
| 399 | _ (SIGCHLD); |
| 400 | _ (SIGCONT); |
| 401 | _ (SIGSTOP); |
| 402 | _ (SIGTSTP); |
| 403 | _ (SIGTTIN); |
| 404 | _ (SIGTTOU); |
| 405 | _ (SIGURG); |
| 406 | _ (SIGXCPU); |
| 407 | _ (SIGXFSZ); |
| 408 | _ (SIGVTALRM); |
| 409 | _ (SIGPROF); |
| 410 | _ (SIGWINCH); |
| 411 | _ (SIGIO); |
| 412 | _ (SIGPWR); |
| 413 | #ifdef SIGSYS |
| 414 | _ (SIGSYS); |
| 415 | #endif |
| 416 | #undef _ |
| 417 | default: |
| 418 | return format (s, "unknown %d", signum); |
| 419 | } |
| 420 | |
| 421 | vec_add (s, t, strlen (t)); |
| 422 | return s; |
| 423 | } |
| 424 | |
| 425 | u8 * format_ucontext_pc (u8 * s, va_list * args) |
| 426 | { |
Dave Barach | bfdedbd | 2016-01-20 09:11:55 -0500 | [diff] [blame] | 427 | ucontext_t * uc __attribute__((unused)); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 428 | unsigned long * regs = 0; |
| 429 | uword reg_no = 0; |
| 430 | |
Dave Barach | bfdedbd | 2016-01-20 09:11:55 -0500 | [diff] [blame] | 431 | uc = va_arg (*args, ucontext_t *); |
| 432 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 433 | #if defined (powerpc) |
| 434 | regs = &uc->uc_mcontext.uc_regs->gregs[0]; |
| 435 | #elif defined (powerpc64) |
| 436 | regs = &uc->uc_mcontext.uc_regs->gp_regs[0]; |
| 437 | #elif defined (i386) || defined (__x86_64__) |
| 438 | regs = (void *) &uc->uc_mcontext.gregs[0]; |
| 439 | #endif |
| 440 | |
| 441 | #if defined (powerpc) || defined (powerpc64) |
| 442 | reg_no = PT_NIP; |
| 443 | #elif defined (i386) |
| 444 | reg_no = REG_EIP; |
| 445 | #elif defined (__x86_64__) |
| 446 | reg_no = REG_RIP; |
| 447 | #else |
| 448 | reg_no = 0; |
| 449 | regs = 0; |
| 450 | #endif |
| 451 | |
| 452 | if (! regs) |
| 453 | return format (s, "unsupported"); |
| 454 | else |
| 455 | return format (s, "%p", regs[reg_no]); |
| 456 | } |
| 457 | |
Damjan Marion | dae1c7e | 2020-10-17 13:32:25 +0200 | [diff] [blame] | 458 | __clib_export uword |
Damjan Marion | a54230d | 2017-06-21 11:57:07 +0200 | [diff] [blame] | 459 | unformat_unix_gid (unformat_input_t * input, va_list * args) |
| 460 | { |
| 461 | gid_t *gid = va_arg (*args, gid_t *); |
| 462 | struct group *grp = 0; |
| 463 | int r; |
| 464 | u8 *s; |
| 465 | |
| 466 | if (unformat (input, "%d", &r)) |
| 467 | { |
| 468 | grp = getgrgid (r); |
| 469 | } |
| 470 | else if (unformat (input, "%s", &s)) |
| 471 | { |
| 472 | grp = getgrnam ((char *) s); |
| 473 | vec_free (s); |
| 474 | } |
| 475 | if (grp) |
| 476 | { |
| 477 | *gid = grp->gr_gid; |
| 478 | return 1; |
| 479 | } |
| 480 | return 0; |
| 481 | } |
| 482 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 483 | #endif /* __KERNEL__ */ |