Merged revisions 162413 via svnmerge from
[asterisk/asterisk.git] / include / asterisk / utils.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  * \brief Utility functions
21  */
22
23 #ifndef _ASTERISK_UTILS_H
24 #define _ASTERISK_UTILS_H
25
26 #include "asterisk/network.h"
27
28 #include <time.h>       /* we want to override localtime_r */
29 #include <unistd.h>
30
31 #include "asterisk/lock.h"
32 #include "asterisk/time.h"
33 #include "asterisk/logger.h"
34 #include "asterisk/localtime.h"
35
36 /*! 
37 \note \verbatim
38    Note:
39    It is very important to use only unsigned variables to hold
40    bit flags, as otherwise you can fall prey to the compiler's
41    sign-extension antics if you try to use the top two bits in
42    your variable.
43
44    The flag macros below use a set of compiler tricks to verify
45    that the caller is using an "unsigned int" variable to hold
46    the flags, and nothing else. If the caller uses any other
47    type of variable, a warning message similar to this:
48
49    warning: comparison of distinct pointer types lacks cast
50    will be generated.
51
52    The "dummy" variable below is used to make these comparisons.
53
54    Also note that at -O2 or above, this type-safety checking
55    does _not_ produce any additional object code at all.
56  \endverbatim
57 */
58
59 extern unsigned int __unsigned_int_flags_dummy;
60
61 #define ast_test_flag(p,flag)           ({ \
62                                         typeof ((p)->flags) __p = (p)->flags; \
63                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
64                                         (void) (&__p == &__x); \
65                                         ((p)->flags & (flag)); \
66                                         })
67
68 #define ast_set_flag(p,flag)            do { \
69                                         typeof ((p)->flags) __p = (p)->flags; \
70                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
71                                         (void) (&__p == &__x); \
72                                         ((p)->flags |= (flag)); \
73                                         } while(0)
74
75 #define ast_clear_flag(p,flag)          do { \
76                                         typeof ((p)->flags) __p = (p)->flags; \
77                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
78                                         (void) (&__p == &__x); \
79                                         ((p)->flags &= ~(flag)); \
80                                         } while(0)
81
82 #define ast_copy_flags(dest,src,flagz)  do { \
83                                         typeof ((dest)->flags) __d = (dest)->flags; \
84                                         typeof ((src)->flags) __s = (src)->flags; \
85                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
86                                         (void) (&__d == &__x); \
87                                         (void) (&__s == &__x); \
88                                         (dest)->flags &= ~(flagz); \
89                                         (dest)->flags |= ((src)->flags & (flagz)); \
90                                         } while (0)
91
92 #define ast_set2_flag(p,value,flag)     do { \
93                                         typeof ((p)->flags) __p = (p)->flags; \
94                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
95                                         (void) (&__p == &__x); \
96                                         if (value) \
97                                                 (p)->flags |= (flag); \
98                                         else \
99                                                 (p)->flags &= ~(flag); \
100                                         } while (0)
101
102 #define ast_set_flags_to(p,flag,value)  do { \
103                                         typeof ((p)->flags) __p = (p)->flags; \
104                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
105                                         (void) (&__p == &__x); \
106                                         (p)->flags &= ~(flag); \
107                                         (p)->flags |= (value); \
108                                         } while (0)
109
110
111 /* The following 64-bit flag code can most likely be erased after app_dial
112    is reorganized to either reduce the large number of options, or handle
113    them in some other way. At the time of this writing, app_dial would be
114    the only user of 64-bit option flags */
115
116 extern uint64_t __unsigned_int_flags_dummy64;
117
118 #define ast_test_flag64(p,flag)                 ({ \
119                                         typeof ((p)->flags) __p = (p)->flags; \
120                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
121                                         (void) (&__p == &__x); \
122                                         ((p)->flags & (flag)); \
123                                         })
124
125 #define ast_set_flag64(p,flag)          do { \
126                                         typeof ((p)->flags) __p = (p)->flags; \
127                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
128                                         (void) (&__p == &__x); \
129                                         ((p)->flags |= (flag)); \
130                                         } while(0)
131
132 #define ast_clear_flag64(p,flag)                do { \
133                                         typeof ((p)->flags) __p = (p)->flags; \
134                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
135                                         (void) (&__p == &__x); \
136                                         ((p)->flags &= ~(flag)); \
137                                         } while(0)
138
139 #define ast_copy_flags64(dest,src,flagz)        do { \
140                                         typeof ((dest)->flags) __d = (dest)->flags; \
141                                         typeof ((src)->flags) __s = (src)->flags; \
142                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
143                                         (void) (&__d == &__x); \
144                                         (void) (&__s == &__x); \
145                                         (dest)->flags &= ~(flagz); \
146                                         (dest)->flags |= ((src)->flags & (flagz)); \
147                                         } while (0)
148
149 #define ast_set2_flag64(p,value,flag)   do { \
150                                         typeof ((p)->flags) __p = (p)->flags; \
151                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
152                                         (void) (&__p == &__x); \
153                                         if (value) \
154                                                 (p)->flags |= (flag); \
155                                         else \
156                                                 (p)->flags &= ~(flag); \
157                                         } while (0)
158
159 #define ast_set_flags_to64(p,flag,value)        do { \
160                                         typeof ((p)->flags) __p = (p)->flags; \
161                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
162                                         (void) (&__p == &__x); \
163                                         (p)->flags &= ~(flag); \
164                                         (p)->flags |= (value); \
165                                         } while (0)
166
167
168 /* Non-type checking variations for non-unsigned int flags.  You
169    should only use non-unsigned int flags where required by 
170    protocol etc and if you know what you're doing :)  */
171 #define ast_test_flag_nonstd(p,flag) \
172                                         ((p)->flags & (flag))
173
174 #define ast_set_flag_nonstd(p,flag)             do { \
175                                         ((p)->flags |= (flag)); \
176                                         } while(0)
177
178 #define ast_clear_flag_nonstd(p,flag)           do { \
179                                         ((p)->flags &= ~(flag)); \
180                                         } while(0)
181
182 #define ast_copy_flags_nonstd(dest,src,flagz)   do { \
183                                         (dest)->flags &= ~(flagz); \
184                                         (dest)->flags |= ((src)->flags & (flagz)); \
185                                         } while (0)
186
187 #define ast_set2_flag_nonstd(p,value,flag)      do { \
188                                         if (value) \
189                                                 (p)->flags |= (flag); \
190                                         else \
191                                                 (p)->flags &= ~(flag); \
192                                         } while (0)
193
194 #define AST_FLAGS_ALL UINT_MAX
195
196 /*! \brief Structure used to handle boolean flags 
197 */
198 struct ast_flags {
199         unsigned int flags;
200 };
201
202 /*! \brief Structure used to handle a large number of boolean flags == used only in app_dial?
203 */
204 struct ast_flags64 {
205         uint64_t flags;
206 };
207
208 struct ast_hostent {
209         struct hostent hp;
210         char buf[1024];
211 };
212
213 /*! \brief Thread-safe gethostbyname function to use in Asterisk */
214 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
215
216 /*!  \brief Produces MD5 hash based on input string */
217 void ast_md5_hash(char *output, char *input);
218 /*! \brief Produces SHA1 hash based on input string */
219 void ast_sha1_hash(char *output, char *input);
220
221 int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks);
222
223 /*!
224  * \brief Encode data in base64
225  * \param dst the destination buffer
226  * \param src the source data to be encoded
227  * \param srclen the number of bytes present in the source buffer
228  * \param max the maximum number of bytes to write into the destination
229  *        buffer, *including* the terminating NULL character.
230  */
231 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max);
232
233 /*!
234  * \brief Decode data from base64
235  * \param dst the destination buffer
236  * \param src the source buffer
237  * \param max The maximum number of bytes to write into the destination
238  *            buffer.  Note that this function will not ensure that the
239  *            destination buffer is NULL terminated.  So, in general,
240  *            this parameter should be sizeof(dst) - 1.
241  */
242 int ast_base64decode(unsigned char *dst, const char *src, int max);
243
244 /*!  \brief Turn text string to URI-encoded %XX version 
245
246 \note   At this point, we're converting from ISO-8859-x (8-bit), not UTF8
247         as in the SIP protocol spec 
248         If doreserved == 1 we will convert reserved characters also.
249         RFC 2396, section 2.4
250         outbuf needs to have more memory allocated than the instring
251         to have room for the expansion. Every char that is converted
252         is replaced by three ASCII characters.
253         \param string   String to be converted
254         \param outbuf   Resulting encoded string
255         \param buflen   Size of output buffer
256         \param doreserved       Convert reserved characters
257 */
258
259 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved);
260
261 /*!     \brief Decode URI, URN, URL (overwrite string)
262         \param s        String to be decoded 
263  */
264 void ast_uri_decode(char *s);
265
266 static force_inline void ast_slinear_saturated_add(short *input, short *value)
267 {
268         int res;
269
270         res = (int) *input + *value;
271         if (res > 32767)
272                 *input = 32767;
273         else if (res < -32767)
274                 *input = -32767;
275         else
276                 *input = (short) res;
277 }
278
279 static force_inline void ast_slinear_saturated_subtract(short *input, short *value)
280 {
281         int res;
282
283         res = (int) *input - *value;
284         if (res > 32767)
285                 *input = 32767;
286         else if (res < -32767)
287                 *input = -32767;
288         else
289                 *input = (short) res;
290 }
291         
292 static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
293 {
294         int res;
295
296         res = (int) *input * *value;
297         if (res > 32767)
298                 *input = 32767;
299         else if (res < -32767)
300                 *input = -32767;
301         else
302                 *input = (short) res;
303 }
304
305 static force_inline void ast_slinear_saturated_divide(short *input, short *value)
306 {
307         *input /= *value;
308 }
309
310 #ifdef localtime_r
311 #undef localtime_r
312 #endif
313 #define localtime_r __dont_use_localtime_r_use_ast_localtime_instead__
314
315 int ast_utils_init(void);
316 int ast_wait_for_input(int fd, int ms);
317
318 /*!
319         \brief Try to write string, but wait no more than ms milliseconds
320         before timing out.
321
322         \note If you are calling ast_carefulwrite, it is assumed that you are calling
323         it on a file descriptor that _DOES_ have NONBLOCK set.  This way,
324         there is only one system call made to do a write, unless we actually
325         have a need to wait.  This way, we get better performance.
326 */
327 int ast_carefulwrite(int fd, char *s, int len, int timeoutms);
328
329 /*
330  * Thread management support (should be moved to lock.h or a different header)
331  */
332  
333 #define AST_STACKSIZE 240 * 1024
334
335 #if defined(LOW_MEMORY)
336 #define AST_BACKGROUND_STACKSIZE 48 * 1024
337 #else
338 #define AST_BACKGROUND_STACKSIZE 240 * 1024
339 #endif
340
341 void ast_register_thread(char *name);
342 void ast_unregister_thread(void *id);
343
344 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
345                              void *data, size_t stacksize, const char *file, const char *caller,
346                              int line, const char *start_fn);
347
348 int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void *),
349                                  void *data, size_t stacksize, const char *file, const char *caller,
350                                  int line, const char *start_fn);
351
352 #define ast_pthread_create(a, b, c, d)                          \
353         ast_pthread_create_stack(a, b, c, d,                    \
354                 0, __FILE__, __FUNCTION__, __LINE__, #c)
355
356 #define ast_pthread_create_detached(a, b, c, d)                 \
357         ast_pthread_create_detached_stack(a, b, c, d,           \
358                 0, __FILE__, __FUNCTION__, __LINE__, #c)
359
360 #define ast_pthread_create_background(a, b, c, d)               \
361         ast_pthread_create_stack(a, b, c, d,                    \
362                 AST_BACKGROUND_STACKSIZE,                       \
363                 __FILE__, __FUNCTION__, __LINE__, #c)
364
365 #define ast_pthread_create_detached_background(a, b, c, d)      \
366         ast_pthread_create_detached_stack(a, b, c, d,           \
367                 AST_BACKGROUND_STACKSIZE,                       \
368                 __FILE__, __FUNCTION__, __LINE__, #c)
369
370 /* End of thread management support */
371
372 /*!
373         \brief Process a string to find and replace characters
374         \param start The string to analyze
375         \param find The character to find
376         \param replace_with The character that will replace the one we are looking for
377 */
378 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
379
380 long int ast_random(void);
381
382 #define ast_free free
383
384 /*! 
385  * \brief free() wrapper
386  *
387  * ast_free_ptr should be used when a function pointer for free() needs to be passed
388  * as the argument to a function. Otherwise, astmm will cause seg faults.
389  */
390 #ifdef __AST_DEBUG_MALLOC
391 static void ast_free_ptr(void *ptr) attribute_unused;
392 static void ast_free_ptr(void *ptr)
393 {
394         ast_free(ptr);
395 }
396 #else
397 #define ast_free_ptr ast_free
398 #endif
399
400 #ifndef __AST_DEBUG_MALLOC
401
402 #define MALLOC_FAILURE_MSG \
403         ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
404 /*!
405  * \brief A wrapper for malloc()
406  *
407  * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
408  * message in the case that the allocation fails.
409  *
410  * The argument and return value are the same as malloc()
411  */
412 #define ast_malloc(len) \
413         _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
414
415 AST_INLINE_API(
416 void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
417 {
418         void *p;
419
420         if (!(p = malloc(len)))
421                 MALLOC_FAILURE_MSG;
422
423         return p;
424 }
425 )
426
427 /*!
428  * \brief A wrapper for calloc()
429  *
430  * ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
431  * message in the case that the allocation fails.
432  *
433  * The arguments and return value are the same as calloc()
434  */
435 #define ast_calloc(num, len) \
436         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
437
438 AST_INLINE_API(
439 void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
440 {
441         void *p;
442
443         if (!(p = calloc(num, len)))
444                 MALLOC_FAILURE_MSG;
445
446         return p;
447 }
448 )
449
450 /*!
451  * \brief A wrapper for calloc() for use in cache pools
452  *
453  * ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
454  * message in the case that the allocation fails. When memory debugging is in use,
455  * the memory allocated by this function will be marked as 'cache' so it can be
456  * distinguished from normal memory allocations.
457  *
458  * The arguments and return value are the same as calloc()
459  */
460 #define ast_calloc_cache(num, len) \
461         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
462
463 /*!
464  * \brief A wrapper for realloc()
465  *
466  * ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
467  * message in the case that the allocation fails.
468  *
469  * The arguments and return value are the same as realloc()
470  */
471 #define ast_realloc(p, len) \
472         _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
473
474 AST_INLINE_API(
475 void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
476 {
477         void *newp;
478
479         if (!(newp = realloc(p, len)))
480                 MALLOC_FAILURE_MSG;
481
482         return newp;
483 }
484 )
485
486 /*!
487  * \brief A wrapper for strdup()
488  *
489  * ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
490  * message in the case that the allocation fails.
491  *
492  * ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
493  * argument is provided, ast_strdup will return NULL without generating any
494  * kind of error log message.
495  *
496  * The argument and return value are the same as strdup()
497  */
498 #define ast_strdup(str) \
499         _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
500
501 AST_INLINE_API(
502 char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
503 {
504         char *newstr = NULL;
505
506         if (str) {
507                 if (!(newstr = strdup(str)))
508                         MALLOC_FAILURE_MSG;
509         }
510
511         return newstr;
512 }
513 )
514
515 /*!
516  * \brief A wrapper for strndup()
517  *
518  * ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
519  * message in the case that the allocation fails.
520  *
521  * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
522  * string to duplicate. If a NULL argument is provided, ast_strdup will return  
523  * NULL without generating any kind of error log message.
524  *
525  * The arguments and return value are the same as strndup()
526  */
527 #define ast_strndup(str, len) \
528         _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
529
530 AST_INLINE_API(
531 char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
532 {
533         char *newstr = NULL;
534
535         if (str) {
536                 if (!(newstr = strndup(str, len)))
537                         MALLOC_FAILURE_MSG;
538         }
539
540         return newstr;
541 }
542 )
543
544 /*!
545  * \brief A wrapper for asprintf()
546  *
547  * ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
548  * message in the case that the allocation fails.
549  *
550  * The arguments and return value are the same as asprintf()
551  */
552 #define ast_asprintf(ret, fmt, ...) \
553         _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
554
555 int __attribute__((format(printf, 5, 6)))
556         _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...);
557
558 /*!
559  * \brief A wrapper for vasprintf()
560  *
561  * ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
562  * message in the case that the allocation fails.
563  *
564  * The arguments and return value are the same as vasprintf()
565  */
566 #define ast_vasprintf(ret, fmt, ap) \
567         _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
568
569 AST_INLINE_API(
570 __attribute__((format(printf, 5, 0)))
571 int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
572 {
573         int res;
574
575         if ((res = vasprintf(ret, fmt, ap)) == -1)
576                 MALLOC_FAILURE_MSG;
577
578         return res;
579 }
580 )
581
582 #else
583
584 /* If astmm is in use, let it handle these.  Otherwise, it will report that
585    all allocations are coming from this header file */
586
587 #define ast_malloc(a)           malloc(a)
588 #define ast_calloc(a,b)         calloc(a,b)
589 #define ast_realloc(a,b)        realloc(a,b)
590 #define ast_strdup(a)           strdup(a)
591 #define ast_strndup(a,b)        strndup(a,b)
592 #define ast_asprintf(a,b,...)   asprintf(a,b,__VA_ARGS__)
593 #define ast_vasprintf(a,b,c)    vasprintf(a,b,c)
594
595 #endif /* AST_DEBUG_MALLOC */
596
597 #if !defined(ast_strdupa) && defined(__GNUC__)
598 /*!
599   \brief duplicate a string in memory from the stack
600   \param s The string to duplicate
601
602   This macro will duplicate the given string.  It returns a pointer to the stack
603   allocatted memory for the new string.
604 */
605 #define ast_strdupa(s)                                                    \
606         (__extension__                                                    \
607         ({                                                                \
608                 const char *__old = (s);                                  \
609                 size_t __len = strlen(__old) + 1;                         \
610                 char *__new = __builtin_alloca(__len);                    \
611                 memcpy (__new, __old, __len);                             \
612                 __new;                                                    \
613         }))
614 #endif
615
616 /*!
617   \brief Disable PMTU discovery on a socket
618   \param sock The socket to manipulate
619   \return Nothing
620
621   On Linux, UDP sockets default to sending packets with the Dont Fragment (DF)
622   bit set. This is supposedly done to allow the application to do PMTU
623   discovery, but Asterisk does not do this.
624
625   Because of this, UDP packets sent by Asterisk that are larger than the MTU
626   of any hop in the path will be lost. This function can be called on a socket
627   to ensure that the DF bit will not be set.
628  */
629 void ast_enable_packet_fragmentation(int sock);
630
631 /*!
632   \brief Recursively create directory path
633   \param path The directory path to create
634   \param mode The permissions with which to try to create the directory
635   \return 0 on success or an error code otherwise
636
637   Creates a directory path, creating parent directories as needed.
638  */
639 int ast_mkdir(const char *path, int mode);
640
641 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
642
643 #ifdef AST_DEVMODE
644 #define ast_assert(a) _ast_assert(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
645 static void force_inline _ast_assert(int condition, const char *condition_str, 
646         const char *file, int line, const char *function)
647 {
648         if (__builtin_expect(!condition, 1)) {
649                 /* Attempt to put it into the logger, but hope that at least someone saw the
650                  * message on stderr ... */
651                 ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
652                         condition_str, condition);
653                 fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
654                         condition_str, condition, line, function, file);
655                 /* Give the logger a chance to get the message out, just in case we abort(), or
656                  * Asterisk crashes due to whatever problem just happened after we exit ast_assert(). */
657                 usleep(1);
658 #ifdef DO_CRASH
659                 abort();
660                 /* Just in case abort() doesn't work or something else super silly,
661                  * and for Qwell's amusement. */
662                 *((int*)0)=0;
663 #endif
664         }
665 }
666 #else
667 #define ast_assert(a)
668 #endif
669
670 #include "asterisk/strings.h"
671
672 /*!
673  * \brief An Entity ID is essentially a MAC address, brief and unique 
674  */
675 struct ast_eid {
676         unsigned char eid[6];
677 } __attribute__((__packed__));
678
679 /*!
680  * \brief Global EID
681  *
682  * This is set in asterisk.conf, or determined automatically by taking the mac
683  * address of an Ethernet interface on the system.
684  */
685 extern struct ast_eid g_eid;
686
687 /*!
688  * \brief Fill in an ast_eid with the default eid of this machine
689  */
690 void ast_set_default_eid(struct ast_eid *eid);
691
692 /*!
693  * /brief Convert an EID to a string
694  */
695 char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid);
696
697 /*!
698  * \brief Convert a string into an EID
699  *
700  * This function expects an EID in the format:
701  *    00:11:22:33:44:55
702  *
703  * \return 0 success, non-zero failure
704  */
705 int ast_str_to_eid(struct ast_eid *eid, const char *s);
706
707 /*!
708  * \brief Compare two EIDs
709  *
710  * \return 0 if the two are the same, non-zero otherwise
711  */
712 int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2);
713
714 #endif /* _ASTERISK_UTILS_H */