| /** |
| * @file util.h |
| * @brief Various little utility functions that do not fit in elsewhere. |
| * @note Copyright (C) 2011 Richard Cochran <richardcochran@gmail.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| */ |
| #ifndef HAVE_UTIL_H |
| #define HAVE_UTIL_H |
| |
| #include <string.h> |
| #include <time.h> |
| #include <stdbool.h> |
| |
| #include "address.h" |
| #include "ddt.h" |
| #include "ether.h" |
| #include "fsm.h" |
| #include "transport.h" |
| #include "unicast_fsm.h" |
| |
| #define MAX_PRINT_BYTES 16 |
| #define BIN_BUF_SIZE (MAX_PRINT_BYTES * 3 + 1) |
| |
| #define NSEC_PER_SEC 1000000000LL |
| |
| /** |
| * Table of human readable strings, one for each port state. |
| */ |
| extern const char *ps_str[]; |
| |
| /** |
| * Table of human readable strings, one for each port event. |
| */ |
| extern const char *ev_str[]; |
| |
| /** |
| * Gets a human-readable string for a given timestamp type. |
| * @param ts Timestamp type. |
| * @return Human-readable rendering if TS is valid, otherwise "???". |
| */ |
| const char *ts_str(enum timestamp_type ts); |
| |
| /** |
| * Compares two binary addresses for equality. |
| * @param type One of the enumerated transport types. |
| * @param a One address to compare. |
| * @param b The second address to compare. |
| * @return One if the addresses are identical, zero otherwise. |
| */ |
| int addreq(enum transport_type type, struct address *a, struct address *b); |
| |
| static inline uint16_t align16(void *p) |
| { |
| uint16_t v; |
| memcpy(&v, p, sizeof(v)); |
| return v; |
| } |
| |
| static inline uint32_t align32(void *p) |
| { |
| uint32_t v; |
| memcpy(&v, p, sizeof(v)); |
| return v; |
| } |
| |
| char *bin2str_impl(Octet *data, int len, char *buf, int buf_len); |
| |
| /** |
| * Convert a clock identity into a human readable string. |
| * |
| * Note that this function uses a static global variable to store the |
| * result and therefore is not reentrant. |
| * |
| * @param id Clock idendtity to show. |
| * @return Pointer to a static global buffer holding the result. |
| */ |
| char *cid2str(struct ClockIdentity *id); |
| |
| /** |
| * Compare two clock identities for equality. |
| * |
| * @param a First clock identity. |
| * @param b Second clock identity. |
| * @return 1 if identities are equal, 0 otherwise. |
| */ |
| static inline int cid_eq(struct ClockIdentity *a, struct ClockIdentity *b) |
| { |
| return memcmp(a, b, sizeof(*a)) == 0; |
| } |
| |
| /** |
| * Counts the number of occurrences of a given character. |
| * @param str String to evaluate. |
| * @param c The character of interest. |
| * @return The number of time 'c' appears in 'str'. |
| */ |
| int count_char(const char *str, char c); |
| |
| /** |
| * Convert a port identity into a human readable string. |
| * |
| * Note that this function uses a static global variable to store the |
| * result and therefore is not reentrant. |
| * |
| * @param id Port idendtity to show. |
| * @return Pointer to a static global buffer holding the result. |
| */ |
| char *pid2str(struct PortIdentity *id); |
| |
| char *portaddr2str(struct PortAddress *addr); |
| |
| const char *ustate2str(enum unicast_state ustate); |
| |
| /** |
| * Reduce all port states for which the sync direction isn't known to |
| * PS_DISABLED, and report the given port state otherwise. This minimizes port |
| * state transitions for PMC agents when nothing interesting happened. |
| */ |
| enum port_state port_state_normalize(enum port_state state); |
| |
| /** |
| * Closes a dynamic posix clock. |
| * @param clock A clock ID obtained via posix_clock_close(). |
| */ |
| void posix_clock_close(clockid_t clock); |
| |
| /** |
| * Opens a dynamic posix clock by name. |
| * @param device The PHC character device or network interface to open. |
| * @param phc_index Returns the PHC index, if any. |
| * @return A valid clock ID on success or CLOCK_INVALID otherwise. |
| */ |
| clockid_t posix_clock_open(const char *device, int *phc_index); |
| |
| /** |
| * Compare two port identities for equality. |
| * |
| * @param a First port identity. |
| * @param b Second port identity. |
| * @return 1 if identities are equal, 0 otherwise. |
| */ |
| static inline int pid_eq(const struct PortIdentity *a, |
| const struct PortIdentity *b) |
| { |
| return memcmp(a, b, sizeof(*a)) == 0; |
| } |
| |
| /** |
| * Convert a string containing a network address into binary form. |
| * @param type The network transport type of the address. |
| * @param s String in human readable form. |
| * @param addr Pointer to a buffer to hold the result. |
| * @return Zero on success, or -1 if the string is incorrectly formatted. |
| */ |
| int str2addr(enum transport_type type, const char *s, struct address *addr); |
| |
| /** |
| * Scan a string containing a MAC address and convert it into binary form. |
| * |
| * @param s String in human readable form. |
| * @param mac Pointer to a buffer to hold the result. |
| * @return Zero on success, or -1 if the string is incorrectly formatted. |
| */ |
| int str2mac(const char *s, unsigned char mac[MAC_LEN]); |
| |
| /** |
| * Scan a string containing a clock identity and convert it into binary form. |
| * |
| * @param s String in human readable form. |
| * @param result Pointer to a buffer to hold the result. |
| * @return Zero on success, or -1 if the string is incorrectly formatted. |
| */ |
| int str2cid(const char *s, struct ClockIdentity *result); |
| |
| /** |
| * Scan a string containing a port identity and convert it into binary form. |
| * |
| * @param s String in human readable form. |
| * @param result Pointer to a buffer to hold the result. |
| * @return Zero on success, or -1 if the string is incorrectly formatted. |
| */ |
| int str2pid(const char *s, struct PortIdentity *result); |
| |
| int generate_clock_identity(struct ClockIdentity *ci, const char *name); |
| |
| /** |
| * Copies a PTPText to a static_ptp_text. This copies the text into |
| * the static_ptp_text. |
| * @param dst The static_ptp_text to copy to |
| * @param src The PTPText to copy from |
| * @return Zero on success, -1 if text in src is too long or not valid |
| * UTF8 |
| */ |
| int static_ptp_text_copy(struct static_ptp_text *dst, const struct PTPText *src); |
| |
| /** |
| * Copies a static_ptp_text to a PTPText. Caller must ensure it's |
| * valid to write to the memory after the PTPText struct. The trailing |
| * \0 is not copied. |
| * @param dst The PTPText to copy to |
| * @param src The static_ptp_text to copy from |
| */ |
| void ptp_text_copy(struct PTPText *dst, const struct static_ptp_text *src); |
| |
| /** |
| * Sets a PTPText from a null-terminated char*. Caller must ensure it's |
| * valid to write to the memory after the PTPText struct. The trailing |
| * \0 is not copied. |
| * @param dst The PTPText to copy to |
| * @param src The text to copy from |
| * @return Zero on success, -1 if src is too long |
| */ |
| int ptp_text_set(struct PTPText *dst, const char *src); |
| |
| /** |
| * Sets a static_ptp_text from a null-terminated char*. |
| * @param dst The static_ptp_text to copy to |
| * @param src The text to copy from |
| * @return Zero on success, -1 if text in src is too long or not valid |
| * UTF8 |
| */ |
| int static_ptp_text_set(struct static_ptp_text *dst, const char *src); |
| |
| /** |
| * Check if UTC time stamp can be both before and after a leap second. |
| * |
| * @param ts UTC time stamp in nanoseconds. |
| * @return 0 if not, 1 if yes. |
| */ |
| int is_utc_ambiguous(uint64_t ts); |
| |
| /** |
| * Get leap second status in given time. |
| * |
| * @param ts UTC time stamp in nanoseconds. |
| * @param leap_set Previous leap second status (+1/0/-1). |
| * @param leap Announced leap second (+1/0/-1), will be corrected if |
| * early/late. |
| * @param utc_offset Announced UTC offset, will be corrected if early/late. |
| * @return 0 if the leap second passed, +1 if leap second will be |
| * inserted, -1 if leap second will be deleted. |
| */ |
| int leap_second_status(uint64_t ts, int leap_set, int *leap, int *utc_offset); |
| |
| /** |
| * Values returned by get_ranged_*(). |
| */ |
| enum parser_result { |
| PARSED_OK, |
| NOT_PARSED, |
| BAD_VALUE, |
| MALFORMED, |
| OUT_OF_RANGE, |
| }; |
| |
| /** |
| * Get an integer value from string with error checking and range |
| * specification. |
| * |
| * @param str_val String which contains an integer value. |
| * @param result Parsed value is stored in here. |
| * @param min Lower limit. Return OUT_OF_RANGE if parsed value |
| * is less than min. |
| * @param max Upper Limit. Return OUT_OF_RANGE if parsed value |
| * is bigger than max. |
| * @return PARSED_OK on success, MALFORMED if str_val is malformed, |
| * OUT_OF_RANGE if str_val is out of range. |
| */ |
| enum parser_result get_ranged_int(const char *str_val, int *result, |
| int min, int max); |
| |
| /** |
| * Get an unsigned integer value from string with error checking and range |
| * specification. |
| * |
| * @param str_val String which contains an unsigned integer value. |
| * @param result Parsed value is stored in here. |
| * @param min Lower limit. Return OUT_OF_RANGE if parsed value |
| * is less than min. |
| * @param max Upper Limit. Return OUT_OF_RANGE if parsed value |
| * is bigger than max. |
| * @return PARSED_OK on success, MALFORMED if str_val is malformed, |
| * OUT_OF_RANGE if str_val is out of range. |
| */ |
| enum parser_result get_ranged_uint(const char *str_val, unsigned int *result, |
| unsigned int min, unsigned int max); |
| |
| /** |
| * Get a double value from string with error checking and range |
| * specification. |
| * |
| * @param str_val String which contains a double value. |
| * @param result Parsed value is stored in here. |
| * @param min Lower limit. Return OUT_OF_RANGE if parsed value |
| * is less than min. |
| * @param max Upper Limit. Return OUT_OF_RANGE if parsed value |
| * is bigger than max. |
| * @return PARSED_OK on success, MALFORMED if str_val is malformed, |
| * OUT_OF_RANGE if str_val is out of range. |
| */ |
| enum parser_result get_ranged_double(const char *str_val, double *result, |
| double min, double max); |
| |
| /** |
| * Common procedure to get an int value from argument for ptp4l and phc2sys. |
| * |
| * @param op Character code of an option. |
| * @param optarg Option argument string. |
| * @param val Parsed value is stored in here. |
| * @param min Lower limit. Return -1 if parsed value is less than min. |
| * @param max Upper limit. Return -1 if parsed value is bigger than max. |
| * @return 0 on success, -1 if some error occurs. |
| */ |
| int get_arg_val_i(int op, const char *optarg, int *val, int min, int max); |
| |
| /** |
| * Common procedure to get an unsigned int value from argument for ptp4l |
| * and phc2sys. |
| * |
| * @param op Character code of an option. |
| * @param optarg Option argument string. |
| * @param val Parsed value is stored in here. |
| * @param min Lower limit. Return -1 if parsed value is less than min. |
| * @param max Upper limit. Return -1 if parsed value is bigger than max. |
| * @return 0 on success, -1 if some error occurs. |
| */ |
| int get_arg_val_ui(int op, const char *optarg, unsigned int *val, |
| unsigned int min, unsigned int max); |
| |
| /** |
| * Common procedure to get a double value from argument for ptp4l and phc2sys. |
| * |
| * @param op Character code of an option. |
| * @param optarg Option argument string. |
| * @param val Parsed value is stored in here. |
| * @param min Lower limit. Return -1 if parsed value is less than min. |
| * @param max Upper limit. Return -1 if parsed value is bigger than max. |
| * @return 0 on success, -1 if some error occurs. |
| */ |
| int get_arg_val_d(int op, const char *optarg, double *val, |
| double min, double max); |
| |
| /** |
| * Setup a handler for terminating signals (SIGINT, SIGQUIT, SIGTERM). |
| * |
| * @return 0 on success, -1 on error. |
| */ |
| int handle_term_signals(void); |
| |
| /** |
| * Check if a terminating signal was received. |
| * |
| * @return 1 if no terminating signal was received, 0 otherwise. |
| */ |
| int is_running(void); |
| |
| /** |
| * Allocate memory. This is a malloc() wrapper that terminates the process when |
| * the allocation fails. |
| * |
| * @param size Size of the block. Must be larger than 0. |
| * @return Pointer to the allocated memory. |
| */ |
| void *xmalloc(size_t size); |
| |
| /** |
| * Allocate and clear an array. This is a calloc() wrapper that terminates the |
| * process when the allocation fails. |
| * |
| * @param nmemb Number of elements. Must be larger than 0. |
| * @param size Size of the element. Must be larger than 0. |
| * @return Pointer to the allocated memory. |
| */ |
| void *xcalloc(size_t nmemb, size_t size); |
| |
| /** |
| * Reallocate memory. This is a realloc() wrapper that terminates the process |
| * when the allocation fails. |
| * |
| * @param size Size of the block. Must be larger than 0. |
| * @return Pointer to the allocated memory. |
| */ |
| void *xrealloc(void *ptr, size_t size); |
| |
| /** |
| * Duplicate a string. This is a strdup() wrapper that terminates the process |
| * when the allocation fails. |
| * |
| * @param s String that should be duplicated. |
| * @return Pointer to the duplicated string. |
| */ |
| char *xstrdup(const char *s); |
| |
| /** |
| * Get an allocated and formatted string. This is a wrapper around asprintf() |
| * that terminates the process on errors. |
| * |
| * @param format printf() format string. |
| * @param ... printf() arguments. |
| * @return Pointer to the allocated string. |
| */ |
| #ifdef __GNUC__ |
| __attribute__ ((format (printf, 1, 2))) |
| #endif |
| char *string_newf(const char *format, ...); |
| |
| /** |
| * Reallocate a string and append another string to it. The process is |
| * terminated when the allocation fails. |
| * |
| * @param s String that should be extended. |
| * @param str String appended to s. |
| */ |
| void string_append(char **s, const char *str); |
| #ifdef __GNUC__ |
| __attribute__ ((format (printf, 2, 3))) |
| #endif |
| /** |
| * Reallocate a string and append a formatted string to it. The process is |
| * terminated when the allocation fails. |
| * |
| * @param s String that should be extended. |
| * @param format printf() format string. |
| * @param ... printf() arguments. |
| */ |
| void string_appendf(char **s, const char *format, ...); |
| |
| /** |
| * Get an empty array of pointers terminated by NULL. The process is terminated |
| * when the allocation fails. |
| * |
| * @return Pointer to the allocated array. |
| */ |
| void **parray_new(void); |
| |
| /** |
| * Append pointer to a NULL-terminated pointer array. The array is reallocated |
| * in exponentially increasing sizes. The process is terminated when the |
| * allocation fails. |
| * |
| * @param a Pointer to pointer array. |
| * @param p Pointer appended to the array. |
| */ |
| void parray_append(void ***a, void *p); |
| |
| |
| /** |
| * Append pointers to a NULL-terminated pointer array. The array is reallocated |
| * in exponentially increasing sizes. The process is terminated when the |
| * allocation fails. |
| * |
| * @param a Pointer to pointer array. |
| * @param ... NULL-terminated list of pointers. |
| */ |
| void parray_extend(void ***a, ...); |
| |
| /** |
| * Check if enough time has passed to implement a simple rate limiting. |
| * |
| * @param interval Minimum interval between two calls returning 0 (in seconds). |
| * @param last Time of the last call that returned 0, input/output. |
| * @return 1 when rate limited, 0 otherwise. |
| */ |
| int rate_limited(int interval, time_t *last); |
| |
| /** |
| * Get decoded length of a Base64 str in octets. Does not check the |
| * validity of the Base64 str, instead only provides the needed buffer |
| * length needed as a result of a valid base64 decoding. |
| * |
| * @param str base64 string |
| * @param len length or zero for null terminated string |
| * @return size for buffer |
| */ |
| size_t base64_len(const char *str, size_t len); |
| |
| /** |
| * Decode Base64 str. The same buffer may be used for input string |
| * and output buffer, as long as the output buffer starts at the |
| * beginning or before the input string. |
| * You can generate with 'openssl rand -base64 <octets>' |
| * Or convert with 'base64 <binary file>' |
| * |
| * @param in_str base64 string to decode |
| * @param len length or zero for null terminated input string |
| * @param out buffer for result |
| * @param out_len length of buffer, update to actual size of result |
| * @return true for success |
| */ |
| bool base64_decode(const char *in_str, size_t in_len, void *out, size_t *out_len); |
| |
| /** |
| * Scan a string containing a profile ID and convert it into binary form. |
| * |
| * @param s String in human readable form. |
| * @param result Pointer to a buffer to hold the result. |
| * @return Zero on success, or -1 if the string is incorrectly formatted. |
| */ |
| int str2prid(const char *s, struct ProfileIdentity *result); |
| |
| /* |
| * Create directory for a UDS address owned by the specified user. |
| * Don't do anything if it already exists, even if it has a different owner. |
| * |
| * @param address UDS address. |
| * @param user Name of the user. |
| */ |
| void create_uds_directory(const char *address, const char *user); |
| |
| /** |
| * Change the user/group ID in order to drop the root privileges. Initialize |
| * supplementary groups of the user. Keep only capabilities needed to set |
| * and adjust clocks, bind to a privileged port, enable and configure HW |
| * timestamping, and open a raw socket. |
| * |
| * @param user Name of the user. |
| * @return 0 on success, -1 on error. |
| */ |
| int drop_root_privileges(const char *user); |
| |
| #endif |