blob: fd112675fa72e5eb9670c6517f8efab5d0f02e09 [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
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). */
99u8 * 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
175u8 * 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
193u8 * 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. */
212u8 * 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
236u8 * format_sockaddr (u8 * s, va_list * args)
237{
238 void * v = va_arg (*args, void *);
239 struct sockaddr * sa = v;
Dave Barachf22f07d2017-09-19 14:36:46 -0400240 static u32 local_counter;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
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 Barachf22f07d2017-09-19 14:36:46 -0400253 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 Warnickecb9cada2015-12-08 15:45:58 -0700264#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 Marion4dffd1c2018-09-03 12:30:36 +0200285#ifndef __APPLE__
Ed Warnickecb9cada2015-12-08 15:45:58 -0700286
287#ifndef __KERNEL__
288u8 * 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 Vinciguerra27826302019-05-09 19:12:18 -0400332 what_fmt = "%02d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333 break;
334 case 'd':
335 what = tm->tm_mday;
Paul Vinciguerra27826302019-05-09 19:12:18 -0400336 what_fmt = "%02d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700337 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 Marion4dffd1c2018-09-03 12:30:36 +0200361#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -0700362
363u8 * 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
375u8 * 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
426u8 * format_ucontext_pc (u8 * s, va_list * args)
427{
Dave Barachbfdedbd2016-01-20 09:11:55 -0500428 ucontext_t * uc __attribute__((unused));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429 unsigned long * regs = 0;
430 uword reg_no = 0;
431
Dave Barachbfdedbd2016-01-20 09:11:55 -0500432 uc = va_arg (*args, ucontext_t *);
433
Ed Warnickecb9cada2015-12-08 15:45:58 -0700434#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 Mariondae1c7e2020-10-17 13:32:25 +0200459__clib_export uword
Damjan Mariona54230d2017-06-21 11:57:07 +0200460unformat_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 Warnickecb9cada2015-12-08 15:45:58 -0700484#endif /* __KERNEL__ */