FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
unix-formats.c
Go to the documentation of this file.
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 
40 #if __linux__
41 # include <linux/unistd.h>
42 # include <linux/signal.h>
43 #endif
44 
45 #else /* ! __KERNEL__ */
46 
47 #ifdef __APPLE__
48 #define _XOPEN_SOURCE
49 #endif
50 
51 #define _GNU_SOURCE /* to get REG_* in ucontext.h */
52 #include <ucontext.h>
53 #undef __USE_GNU
54 
55 #include <unistd.h>
56 #include <signal.h>
57 #include <grp.h>
58 
59 #include <time.h>
60 #include <sys/socket.h>
61 #include <netdb.h>
62 #include <math.h>
63 
64 #include <vppinfra/time.h>
65 #if __linux__
66 #ifdef AF_NETLINK
67 #include <linux/types.h>
68 #include <linux/netlink.h>
69 #endif
70 #endif
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;
240  static u32 local_counter;
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 
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 
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 
285 #ifndef __APPLE__
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;
332  what_fmt = "%02d";
333  break;
334  case 'd':
335  what = tm->tm_mday;
336  what_fmt = "%02d";
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 }
361 #endif
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 {
428  ucontext_t * uc __attribute__((unused));
429  unsigned long * regs = 0;
430  uword reg_no = 0;
431 
432  uc = va_arg (*args, ucontext_t *);
433 
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 
459 __clib_export uword
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 
484 #endif /* __KERNEL__ */
format_timeval
u8 * format_timeval(u8 *s, va_list *args)
Definition: unix-formats.c:288
vec_add
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:688
unix_time_now
static f64 unix_time_now(void)
Definition: time.h:255
ntohs
#define ntohs(x)
Definition: af_xdp.bpf.c:29
format_signal
u8 * format_signal(u8 *s, va_list *args)
Definition: unix-formats.c:375
f
vlib_frame_t * f
Definition: interface_output.c:1098
format_network_address
u8 * format_network_address(u8 *s, va_list *args)
Definition: unix-formats.c:212
port
u16 port
Definition: lb_types.api:73
unformat_input_t
struct _unformat_input_t unformat_input_t
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
format_ucontext_pc
u8 * format_ucontext_pc(u8 *s, va_list *args)
Definition: unix-formats.c:426
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
regs
static vnet_feature_upd_registration_t * regs
Definition: feature.c:26
math.h
error.h
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
bitops.h
c
svmdb_client_t * c
Definition: vpp_get_metrics.c:48
uword
u64 uword
Definition: types.h:112
time.h
f64
double f64
Definition: types.h:142
format.h
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
format_address_family
u8 * format_address_family(u8 *s, va_list *va)
Definition: unix-formats.c:99
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
unformat_unix_gid
__clib_export uword unformat_unix_gid(unformat_input_t *input, va_list *args)
Definition: unix-formats.c:460
u32
unsigned int u32
Definition: types.h:88
protocol
vl_api_ip_proto_t protocol
Definition: lb_types.api:72
flt_round_nearest
static word flt_round_nearest(f64 x)
Definition: clib.h:315
now
f64 now
Definition: nat44_ei_out2in.c:710
format_time_float
u8 * format_time_float(u8 *s, va_list *args)
Definition: unix-formats.c:363
u8
unsigned char u8
Definition: types.h:56
clib_error
#define clib_error(format, args...)
Definition: error.h:62
i
int i
Definition: flowhash_template.h:376
word
i64 word
Definition: types.h:111
format_network_port
u8 * format_network_port(u8 *s, va_list *args)
Definition: unix-formats.c:193
proto
vl_api_ip_proto_t proto
Definition: acl_types.api:51
format_sockaddr
u8 * format_sockaddr(u8 *s, va_list *args)
Definition: unix-formats.c:236
format_network_protocol
u8 * format_network_protocol(u8 *s, va_list *args)
Definition: unix-formats.c:175