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 | |
| 94 | #include <vppinfra/bitops.h> /* foreach_set_bit */ |
| 95 | #include <vppinfra/format.h> |
| 96 | #include <vppinfra/error.h> |
| 97 | |
| 98 | /* Format unix network address family (e.g. AF_INET). */ |
| 99 | u8 * format_address_family (u8 * s, va_list * va) |
| 100 | { |
| 101 | uword family = va_arg (*va, uword); |
| 102 | u8 * t = (u8 *) "UNKNOWN"; |
| 103 | switch (family) |
| 104 | { |
| 105 | #define _(x) case PF_##x: t = (u8 *) #x; break |
| 106 | _ (UNSPEC); |
| 107 | _ (UNIX); /* Unix domain sockets */ |
| 108 | _ (INET); /* Internet IP Protocol */ |
| 109 | #ifdef PF_AX25 |
| 110 | _ (AX25); /* Amateur Radio AX.25 */ |
| 111 | #endif |
| 112 | #ifdef PF_IPX |
| 113 | _ (IPX); /* Novell IPX */ |
| 114 | #endif |
| 115 | #ifdef PF_APPLETALK |
| 116 | _ (APPLETALK); /* AppleTalk DDP */ |
| 117 | #endif |
| 118 | #ifdef PF_NETROM |
| 119 | _ (NETROM); /* Amateur Radio NET/ROM */ |
| 120 | #endif |
| 121 | #ifdef PF_BRIDGE |
| 122 | _ (BRIDGE); /* Multiprotocol bridge */ |
| 123 | #endif |
| 124 | #ifdef PF_ATMPVC |
| 125 | _ (ATMPVC); /* ATM PVCs */ |
| 126 | #endif |
| 127 | #ifdef PF_X25 |
| 128 | _ (X25); /* Reserved for X.25 project */ |
| 129 | #endif |
| 130 | #ifdef PF_INET6 |
| 131 | _ (INET6); /* IP version 6 */ |
| 132 | #endif |
| 133 | #ifdef PF_ROSE |
| 134 | _ (ROSE); /* Amateur Radio X.25 PLP */ |
| 135 | #endif |
| 136 | #ifdef PF_DECnet |
| 137 | _ (DECnet); /* Reserved for DECnet project */ |
| 138 | #endif |
| 139 | #ifdef PF_NETBEUI |
| 140 | _ (NETBEUI); /* Reserved for 802.2LLC project*/ |
| 141 | #endif |
| 142 | #ifdef PF_SECURITY |
| 143 | _ (SECURITY); /* Security callback pseudo AF */ |
| 144 | #endif |
| 145 | #ifdef PF_KEY |
| 146 | _ (KEY); /* PF_KEY key management API */ |
| 147 | #endif |
| 148 | #ifdef PF_NETLINK |
| 149 | _ (NETLINK); |
| 150 | #endif |
| 151 | #ifdef PF_PACKET |
| 152 | _ (PACKET); /* Packet family */ |
| 153 | #endif |
| 154 | #ifdef PF_ASH |
| 155 | _ (ASH); /* Ash */ |
| 156 | #endif |
| 157 | #ifdef PF_ECONET |
| 158 | _ (ECONET); /* Acorn Econet */ |
| 159 | #endif |
| 160 | #ifdef PF_ATMSVC |
| 161 | _ (ATMSVC); /* ATM SVCs */ |
| 162 | #endif |
| 163 | #ifdef PF_SNA |
| 164 | _ (SNA); /* Linux SNA Project */ |
| 165 | #endif |
| 166 | #ifdef PF_IRDA |
| 167 | _ (IRDA); /* IRDA sockets */ |
| 168 | #endif |
| 169 | #undef _ |
| 170 | } |
| 171 | vec_add (s, t, strlen ((char *) t)); |
| 172 | return s; |
| 173 | } |
| 174 | |
| 175 | u8 * format_network_protocol (u8 * s, va_list * args) |
| 176 | { |
| 177 | uword family = va_arg (*args, uword); |
| 178 | uword protocol = va_arg (*args, uword); |
| 179 | |
| 180 | #ifndef __KERNEL__ |
| 181 | struct protoent * p = getprotobynumber (protocol); |
| 182 | |
| 183 | ASSERT (family == AF_INET); |
| 184 | if (p) |
| 185 | return format (s, "%s", p->p_name); |
| 186 | else |
| 187 | return format (s, "%d", protocol); |
| 188 | #else |
| 189 | return format (s, "%d/%d", family, protocol); |
| 190 | #endif |
| 191 | } |
| 192 | |
| 193 | u8 * format_network_port (u8 * s, va_list * args) |
| 194 | { |
| 195 | uword proto = va_arg (*args, uword); |
| 196 | uword port = va_arg (*args, uword); |
| 197 | |
| 198 | #ifndef __KERNEL__ |
| 199 | struct servent * p = getservbyport (port, proto == IPPROTO_UDP ? "udp" : "tcp"); |
| 200 | |
| 201 | if (p) |
| 202 | return format (s, "%s", p->s_name); |
| 203 | else |
| 204 | return format (s, "%d", port); |
| 205 | #else |
| 206 | return format (s, "%s/%d", proto == IPPROTO_UDP ? "udp" : "tcp", port); |
| 207 | #endif |
| 208 | } |
| 209 | |
| 210 | /* Format generic network address: takes two arguments family and address. |
| 211 | Assumes network byte order. */ |
| 212 | u8 * format_network_address (u8 * s, va_list * args) |
| 213 | { |
| 214 | uword family = va_arg (*args, uword); |
| 215 | u8 * addr = va_arg (*args, u8 *); |
| 216 | |
| 217 | switch (family) |
| 218 | { |
| 219 | case AF_INET: |
| 220 | s = format (s, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); |
| 221 | break; |
| 222 | |
| 223 | case AF_UNSPEC: |
| 224 | /* We use AF_UNSPEC for ethernet addresses. */ |
| 225 | s = format (s, "%02x:%02x:%02x:%02x:%02x:%02x", |
| 226 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); |
| 227 | break; |
| 228 | |
| 229 | default: |
| 230 | clib_error ("unsupported address family %d", family); |
| 231 | } |
| 232 | |
| 233 | return s; |
| 234 | } |
| 235 | |
| 236 | u8 * format_sockaddr (u8 * s, va_list * args) |
| 237 | { |
| 238 | void * v = va_arg (*args, void *); |
| 239 | struct sockaddr * sa = v; |
Dave Barach | f22f07d | 2017-09-19 14:36:46 -0400 | [diff] [blame] | 240 | static u32 local_counter; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 241 | |
| 242 | switch (sa->sa_family) |
| 243 | { |
| 244 | case AF_INET: |
| 245 | { |
| 246 | struct sockaddr_in * i = v; |
| 247 | s = format (s, "%U:%U", |
| 248 | format_network_address, AF_INET, &i->sin_addr.s_addr, |
| 249 | format_network_port, IPPROTO_TCP, ntohs (i->sin_port)); |
| 250 | } |
| 251 | break; |
| 252 | |
Dave Barach | f22f07d | 2017-09-19 14:36:46 -0400 | [diff] [blame] | 253 | case AF_LOCAL: |
| 254 | { |
| 255 | /* |
| 256 | * There isn't anything useful to print. |
| 257 | * The unix cli world uses the output to make a node name, |
| 258 | * so we need to return a unique name. |
| 259 | */ |
| 260 | s = format (s, "local:%u", local_counter++); |
| 261 | } |
| 262 | break; |
| 263 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 264 | #ifndef __KERNEL__ |
| 265 | #ifdef AF_NETLINK |
| 266 | case AF_NETLINK: |
| 267 | { |
| 268 | struct sockaddr_nl * n = v; |
| 269 | s = format (s, "KERNEL-NETLINK"); |
| 270 | if (n->nl_groups) |
| 271 | s = format (s, " (groups 0x%x)", n->nl_groups); |
| 272 | break; |
| 273 | } |
| 274 | #endif |
| 275 | #endif |
| 276 | |
| 277 | default: |
| 278 | s = format (s, "sockaddr family %d", sa->sa_family); |
| 279 | break; |
| 280 | } |
| 281 | |
| 282 | return s; |
| 283 | } |
| 284 | |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 285 | #ifndef __APPLE__ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 286 | |
| 287 | #ifndef __KERNEL__ |
| 288 | u8 * format_timeval (u8 * s, va_list * args) |
| 289 | { |
| 290 | char * fmt = va_arg (*args, char *); |
| 291 | struct timeval * tv = va_arg (*args, struct timeval *); |
| 292 | struct tm * tm; |
| 293 | word msec; |
| 294 | char * f, c; |
| 295 | |
| 296 | if (! fmt) |
| 297 | fmt = "y/m/d H:M:S:F"; |
| 298 | |
| 299 | if (! tv) |
| 300 | { |
| 301 | static struct timeval now; |
| 302 | gettimeofday (&now, 0); |
| 303 | tv = &now; |
| 304 | } |
| 305 | |
| 306 | msec = flt_round_nearest (1e-3 * tv->tv_usec); |
| 307 | if (msec >= 1000) |
| 308 | { msec = 0; tv->tv_sec++; } |
| 309 | |
| 310 | { |
| 311 | time_t t = tv->tv_sec; |
| 312 | tm = localtime (&t); |
| 313 | } |
| 314 | |
| 315 | for (f = fmt; *f; f++) |
| 316 | { |
| 317 | uword what; |
| 318 | char * what_fmt = "%d"; |
| 319 | |
| 320 | switch (c = *f) |
| 321 | { |
| 322 | default: |
| 323 | vec_add1 (s, c); |
| 324 | continue; |
| 325 | |
| 326 | case 'y': |
| 327 | what = 1900 + tm->tm_year; |
| 328 | what_fmt = "%4d"; |
| 329 | break; |
| 330 | case 'm': |
| 331 | what = tm->tm_mon + 1; |
Paul Vinciguerra | 2782630 | 2019-05-09 19:12:18 -0400 | [diff] [blame] | 332 | what_fmt = "%02d"; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 333 | break; |
| 334 | case 'd': |
| 335 | what = tm->tm_mday; |
Paul Vinciguerra | 2782630 | 2019-05-09 19:12:18 -0400 | [diff] [blame] | 336 | what_fmt = "%02d"; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 337 | break; |
| 338 | case 'H': |
| 339 | what = tm->tm_hour; |
| 340 | what_fmt = "%02d"; |
| 341 | break; |
| 342 | case 'M': |
| 343 | what = tm->tm_min; |
| 344 | what_fmt = "%02d"; |
| 345 | break; |
| 346 | case 'S': |
| 347 | what = tm->tm_sec; |
| 348 | what_fmt = "%02d"; |
| 349 | break; |
| 350 | case 'F': |
| 351 | what = msec; |
| 352 | what_fmt = "%03d"; |
| 353 | break; |
| 354 | } |
| 355 | |
| 356 | s = format (s, what_fmt, what); |
| 357 | } |
| 358 | |
| 359 | return s; |
| 360 | } |
Damjan Marion | 4dffd1c | 2018-09-03 12:30:36 +0200 | [diff] [blame] | 361 | #endif |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 362 | |
| 363 | u8 * format_time_float (u8 * s, va_list * args) |
| 364 | { |
| 365 | u8 * fmt = va_arg (*args, u8 *); |
| 366 | f64 t = va_arg (*args, f64); |
| 367 | struct timeval tv; |
| 368 | if (t <= 0) |
| 369 | t = unix_time_now (); |
| 370 | tv.tv_sec = t; |
| 371 | tv.tv_usec = 1e6*(t - tv.tv_sec); |
| 372 | return format (s, "%U", format_timeval, fmt, &tv); |
| 373 | } |
| 374 | |
| 375 | u8 * format_signal (u8 * s, va_list * args) |
| 376 | { |
| 377 | uword signum = va_arg (*args, uword); |
| 378 | char * t = 0; |
| 379 | switch (signum) |
| 380 | { |
| 381 | #define _(x) case x: t = #x; break; |
| 382 | _ (SIGHUP); |
| 383 | _ (SIGINT); |
| 384 | _ (SIGQUIT); |
| 385 | _ (SIGILL); |
| 386 | _ (SIGTRAP); |
| 387 | _ (SIGABRT); |
| 388 | _ (SIGBUS); |
| 389 | _ (SIGFPE); |
| 390 | _ (SIGKILL); |
| 391 | _ (SIGUSR1); |
| 392 | _ (SIGSEGV); |
| 393 | _ (SIGUSR2); |
| 394 | _ (SIGPIPE); |
| 395 | _ (SIGALRM); |
| 396 | _ (SIGTERM); |
| 397 | #ifdef SIGSTKFLT |
| 398 | _ (SIGSTKFLT); |
| 399 | #endif |
| 400 | _ (SIGCHLD); |
| 401 | _ (SIGCONT); |
| 402 | _ (SIGSTOP); |
| 403 | _ (SIGTSTP); |
| 404 | _ (SIGTTIN); |
| 405 | _ (SIGTTOU); |
| 406 | _ (SIGURG); |
| 407 | _ (SIGXCPU); |
| 408 | _ (SIGXFSZ); |
| 409 | _ (SIGVTALRM); |
| 410 | _ (SIGPROF); |
| 411 | _ (SIGWINCH); |
| 412 | _ (SIGIO); |
| 413 | _ (SIGPWR); |
| 414 | #ifdef SIGSYS |
| 415 | _ (SIGSYS); |
| 416 | #endif |
| 417 | #undef _ |
| 418 | default: |
| 419 | return format (s, "unknown %d", signum); |
| 420 | } |
| 421 | |
| 422 | vec_add (s, t, strlen (t)); |
| 423 | return s; |
| 424 | } |
| 425 | |
| 426 | u8 * format_ucontext_pc (u8 * s, va_list * args) |
| 427 | { |
Dave Barach | bfdedbd | 2016-01-20 09:11:55 -0500 | [diff] [blame] | 428 | ucontext_t * uc __attribute__((unused)); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 429 | unsigned long * regs = 0; |
| 430 | uword reg_no = 0; |
| 431 | |
Dave Barach | bfdedbd | 2016-01-20 09:11:55 -0500 | [diff] [blame] | 432 | uc = va_arg (*args, ucontext_t *); |
| 433 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 434 | #if defined (powerpc) |
| 435 | regs = &uc->uc_mcontext.uc_regs->gregs[0]; |
| 436 | #elif defined (powerpc64) |
| 437 | regs = &uc->uc_mcontext.uc_regs->gp_regs[0]; |
| 438 | #elif defined (i386) || defined (__x86_64__) |
| 439 | regs = (void *) &uc->uc_mcontext.gregs[0]; |
| 440 | #endif |
| 441 | |
| 442 | #if defined (powerpc) || defined (powerpc64) |
| 443 | reg_no = PT_NIP; |
| 444 | #elif defined (i386) |
| 445 | reg_no = REG_EIP; |
| 446 | #elif defined (__x86_64__) |
| 447 | reg_no = REG_RIP; |
| 448 | #else |
| 449 | reg_no = 0; |
| 450 | regs = 0; |
| 451 | #endif |
| 452 | |
| 453 | if (! regs) |
| 454 | return format (s, "unsupported"); |
| 455 | else |
| 456 | return format (s, "%p", regs[reg_no]); |
| 457 | } |
| 458 | |
Damjan Marion | dae1c7e | 2020-10-17 13:32:25 +0200 | [diff] [blame] | 459 | __clib_export uword |
Damjan Marion | a54230d | 2017-06-21 11:57:07 +0200 | [diff] [blame] | 460 | unformat_unix_gid (unformat_input_t * input, va_list * args) |
| 461 | { |
| 462 | gid_t *gid = va_arg (*args, gid_t *); |
| 463 | struct group *grp = 0; |
| 464 | int r; |
| 465 | u8 *s; |
| 466 | |
| 467 | if (unformat (input, "%d", &r)) |
| 468 | { |
| 469 | grp = getgrgid (r); |
| 470 | } |
| 471 | else if (unformat (input, "%s", &s)) |
| 472 | { |
| 473 | grp = getgrnam ((char *) s); |
| 474 | vec_free (s); |
| 475 | } |
| 476 | if (grp) |
| 477 | { |
| 478 | *gid = grp->gr_gid; |
| 479 | return 1; |
| 480 | } |
| 481 | return 0; |
| 482 | } |
| 483 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 484 | #endif /* __KERNEL__ */ |