vppinfra: bitops cleanup
[vpp.git] / src / vppinfra / unix-formats.c
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/format.h>
95 #include <vppinfra/error.h>
96
97 /* Format unix network address family (e.g. AF_INET). */
98 u8 * 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
174 u8 * 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
192 u8 * 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. */
211 u8 * 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
235 u8 * format_sockaddr (u8 * s, va_list * args)
236 {
237   void * v = va_arg (*args, void *);
238   struct sockaddr * sa = v;
239   static u32 local_counter;
240
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
252     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
263 #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
284 #ifndef __APPLE__
285
286 #ifndef __KERNEL__
287 u8 * 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;
331           what_fmt = "%02d";
332           break;
333         case 'd':
334           what = tm->tm_mday;
335           what_fmt = "%02d";
336           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 }
360 #endif
361
362 u8 * 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
374 u8 * 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);
412       _ (SIGPWR);
413 #ifdef SIGSYS
414       _ (SIGSYS);
415 #endif
416 #undef _
417     default:
418       return format (s, "unknown %d", signum);
419     }
420
421   vec_add (s, t, strlen (t));
422   return s;
423 }
424
425 u8 * format_ucontext_pc (u8 * s, va_list * args)
426 {
427   ucontext_t * uc __attribute__((unused));
428   unsigned long * regs = 0;
429   uword reg_no = 0;
430
431   uc = va_arg (*args, ucontext_t *);
432
433 #if defined (powerpc)
434   regs = &uc->uc_mcontext.uc_regs->gregs[0];
435 #elif defined (powerpc64)
436   regs = &uc->uc_mcontext.uc_regs->gp_regs[0];
437 #elif defined (i386) || defined (__x86_64__)
438   regs = (void *) &uc->uc_mcontext.gregs[0];
439 #endif
440
441 #if defined (powerpc) || defined (powerpc64)
442   reg_no = PT_NIP;
443 #elif defined (i386)
444   reg_no = REG_EIP;
445 #elif defined (__x86_64__)
446   reg_no = REG_RIP;
447 #else
448   reg_no = 0;
449   regs = 0;
450 #endif
451
452   if (! regs)
453     return format (s, "unsupported");
454   else
455     return format (s, "%p", regs[reg_no]);
456 }
457
458 __clib_export uword
459 unformat_unix_gid (unformat_input_t * input, va_list * args)
460 {
461   gid_t *gid = va_arg (*args, gid_t *);
462   struct group *grp = 0;
463   int r;
464   u8 *s;
465
466   if (unformat (input, "%d", &r))
467     {
468       grp = getgrgid (r);
469     }
470   else if (unformat (input, "%s", &s))
471     {
472       grp = getgrnam ((char *) s);
473       vec_free (s);
474     }
475   if (grp)
476     {
477       *gid = grp->gr_gid;
478       return 1;
479     }
480   return 0;
481 }
482
483 #endif /* __KERNEL__ */