blob: 297a3fdb8c29ed7b496dfd7622511c6070619095 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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 Marion4dffd1c2018-09-03 12:30:36 +020040#if __linux__
Ed Warnickecb9cada2015-12-08 15:45:58 -070041# include <linux/unistd.h>
42# include <linux/signal.h>
Damjan Marion4dffd1c2018-09-03 12:30:36 +020043#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -070044
45#else /* ! __KERNEL__ */
46
Damjan Marion4dffd1c2018-09-03 12:30:36 +020047#ifdef __APPLE__
48#define _XOPEN_SOURCE
49#endif
50
Ed Warnickecb9cada2015-12-08 15:45:58 -070051#define _GNU_SOURCE /* to get REG_* in ucontext.h */
52#include <ucontext.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070053#undef __USE_GNU
54
55#include <unistd.h>
56#include <signal.h>
Damjan Mariona54230d2017-06-21 11:57:07 +020057#include <grp.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070058
59#include <time.h>
60#include <sys/socket.h>
61#include <netdb.h>
62#include <math.h>
63
64#include <vppinfra/time.h>
Damjan Marion4dffd1c2018-09-03 12:30:36 +020065#if __linux__
Ed Warnickecb9cada2015-12-08 15:45:58 -070066#ifdef AF_NETLINK
67#include <linux/types.h>
68#include <linux/netlink.h>
69#endif
Damjan Marion4dffd1c2018-09-03 12:30:36 +020070#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -070071
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 Warnickecb9cada2015-12-08 15:45:58 -070094#include <vppinfra/format.h>
95#include <vppinfra/error.h>
96
97/* Format unix network address family (e.g. AF_INET). */
98u8 * 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
174u8 * 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
192u8 * 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. */
211u8 * 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
235u8 * format_sockaddr (u8 * s, va_list * args)
236{
237 void * v = va_arg (*args, void *);
238 struct sockaddr * sa = v;
Dave Barachf22f07d2017-09-19 14:36:46 -0400239 static u32 local_counter;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240
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 Barachf22f07d2017-09-19 14:36:46 -0400252 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 Warnickecb9cada2015-12-08 15:45:58 -0700263#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 Marion4dffd1c2018-09-03 12:30:36 +0200284#ifndef __APPLE__
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285
286#ifndef __KERNEL__
287u8 * 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 Vinciguerra27826302019-05-09 19:12:18 -0400331 what_fmt = "%02d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700332 break;
333 case 'd':
334 what = tm->tm_mday;
Paul Vinciguerra27826302019-05-09 19:12:18 -0400335 what_fmt = "%02d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700336 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 Marion4dffd1c2018-09-03 12:30:36 +0200360#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -0700361
362u8 * 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
374u8 * 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);
Tom Jonesb2e0ce92024-01-26 15:00:31 +0000412#ifdef __linux__
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413 _ (SIGPWR);
Tom Jonesb2e0ce92024-01-26 15:00:31 +0000414#endif /* __linux */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700415#ifdef SIGSYS
416 _ (SIGSYS);
417#endif
418#undef _
419 default:
420 return format (s, "unknown %d", signum);
421 }
422
423 vec_add (s, t, strlen (t));
424 return s;
425}
426
427u8 * format_ucontext_pc (u8 * s, va_list * args)
428{
Dave Barachbfdedbd2016-01-20 09:11:55 -0500429 ucontext_t * uc __attribute__((unused));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700430 unsigned long * regs = 0;
431 uword reg_no = 0;
432
Dave Barachbfdedbd2016-01-20 09:11:55 -0500433 uc = va_arg (*args, ucontext_t *);
434
Tom Jones7d2978d2024-01-26 15:16:57 +0000435#ifdef __linux__
Ed Warnickecb9cada2015-12-08 15:45:58 -0700436#if defined (powerpc)
437 regs = &uc->uc_mcontext.uc_regs->gregs[0];
438#elif defined (powerpc64)
439 regs = &uc->uc_mcontext.uc_regs->gp_regs[0];
440#elif defined (i386) || defined (__x86_64__)
441 regs = (void *) &uc->uc_mcontext.gregs[0];
Tianyu Lic405f752023-04-17 02:49:22 +0000442#elif defined(__aarch64__)
443 regs = (void *) &uc->uc_mcontext.pc;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700444#endif
445
446#if defined (powerpc) || defined (powerpc64)
447 reg_no = PT_NIP;
448#elif defined (i386)
449 reg_no = REG_EIP;
450#elif defined (__x86_64__)
451 reg_no = REG_RIP;
Tianyu Lic405f752023-04-17 02:49:22 +0000452#elif defined(__aarch64__)
453 reg_no = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700454#else
455 reg_no = 0;
456 regs = 0;
457#endif
Tom Jones7d2978d2024-01-26 15:16:57 +0000458#elif __FreeBSD__
459#if defined(__amd64__)
460 reg_no = 0;
461 regs = (void *) &uc->uc_mcontext.mc_rip;
462#else
463#endif /* __amd64__ */
464#endif /* __linux__ */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465
466 if (! regs)
467 return format (s, "unsupported");
468 else
469 return format (s, "%p", regs[reg_no]);
470}
471
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200472__clib_export uword
Damjan Mariona54230d2017-06-21 11:57:07 +0200473unformat_unix_gid (unformat_input_t * input, va_list * args)
474{
475 gid_t *gid = va_arg (*args, gid_t *);
476 struct group *grp = 0;
477 int r;
478 u8 *s;
479
480 if (unformat (input, "%d", &r))
481 {
482 grp = getgrgid (r);
483 }
484 else if (unformat (input, "%s", &s))
485 {
486 grp = getgrnam ((char *) s);
487 vec_free (s);
488 }
489 if (grp)
490 {
491 *gid = grp->gr_gid;
492 return 1;
493 }
494 return 0;
495}
496
Ed Warnickecb9cada2015-12-08 15:45:58 -0700497#endif /* __KERNEL__ */