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