vppinfra: toeplitz hash
[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/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__ */