aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxutil/sys_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxutil/sys_net.c')
-rw-r--r--tools/libxutil/sys_net.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/tools/libxutil/sys_net.c b/tools/libxutil/sys_net.c
new file mode 100644
index 0000000000..0e7ac5d638
--- /dev/null
+++ b/tools/libxutil/sys_net.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version. This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "sys_net.h"
+#include "sys_string.h"
+
+/** @file
+ * All network data are kept in network order and only converted to
+ * host order for display. Network data includes IP addresses, port numbers and
+ * network masks.
+ */
+
+/** Maximum value for a port. */
+#define PORT_MAX 0xffff
+
+/** Convert a number of bits to a network mask
+ * for IP addresses. The number of bits must
+ * be in the range 1-31.
+ *
+ * @param n number of bits to set in the mask
+ * @return value with n high bits set (in network order)
+ */
+unsigned long bits_to_mask(int n){
+ unsigned long mask = (n ? (1 << 31) : 0);
+ int i;
+ for(i=1; i<n; i++){
+ mask |= (mask >> 1);
+ }
+ return htonl(mask);
+}
+
+/** Convert a network mask to a number of bits.
+ *
+ * @param mask network mask in network order
+ * @return number of bits in mask
+ */
+int mask_to_bits(unsigned long mask){
+ // Start with n set to the number of bits in the mask. Then reduce n by
+ // the number of low zero bits in the mask.
+ int n = 32;
+ for(mask = ntohl(mask);
+ (mask & 1)==0 && n>0;
+ mask >>= 1){
+ n--;
+ }
+ return n;
+}
+
+/** Get the index of the first occurrence of a character in a string.
+ * Stops at end of string or after n characters.
+ *
+ * @param s input string
+ * @param n maximum number of charactes to search
+ * @param c character to look for
+ * @return index of first occurrence, -1 if not found
+ */
+inline static int indexof(const char *s, int n, char c){
+ int i;
+ for(i=0; i<n && *s; i++, s++){
+ if(*s == c) return i;
+ }
+ return -1;
+}
+
+/** Convert an IPv4 address in dot notation into an unsigned long (in network order).
+ *
+ * @param s input string
+ * @param address where to put the address
+ * @return 0 on success, -1 on error
+ */
+int get_inet_addr(const char *s, unsigned long *address){
+ // Number of bits in a byte.
+ const int BYTE_BITS = 8;
+ // Number of bytes in a word.
+ const int WORD_BYTES = 4;
+ // Max value for a component of an address.
+ const int ADDR_MAX = 255;
+ // Separator for components of an address.
+ const char dot = '.';
+
+ int n;
+ unsigned long addr = 0;
+ unsigned long v;
+ int i;
+ int err = -1;
+ // Bit shift for the current byte.
+ int shift = BYTE_BITS * (WORD_BYTES - 1);
+ char buf[64];
+
+ n = strlen(s);
+ if(n >= sizeof(buf)){
+ goto exit;
+ }
+ for(i=0; i < WORD_BYTES; i++){
+ int idx = indexof(s, n, dot);
+ idx = (idx < 0 ? strlen(s) : idx);
+ strncpy(buf, s, idx); buf[idx]='\0';
+ if(convert_atoul(buf, &v)){
+ goto exit;
+ }
+ if(v < 0 || v > ADDR_MAX){
+ goto exit;
+ }
+ addr |= (v << shift);
+ if(idx == n) break;
+ shift -= BYTE_BITS;
+ s += idx+1;
+ }
+ err = 0;
+ exit:
+ addr = htonl(addr);
+ *address = (err ? 0 : addr);
+ return err;
+}
+
+#ifdef __KERNEL__
+/** Convert an address in network order to IPv4 dot notation.
+ * The return value is a static buffer which is overwritten on each call.
+ *
+ * @param inaddr address (in network order)
+ * @return address in dot notation
+ */
+char *inet_ntoa(struct in_addr inaddr){
+ static char address[16] = {};
+ uint32_t addr = ntohl(inaddr.s_addr);
+ snprintf(address, sizeof(address), "%d.%d.%d.%d",
+ (unsigned)((addr >> 24) & 0xff),
+ (unsigned)((addr >> 16) & 0xff),
+ (unsigned)((addr >> 8) & 0xff),
+ (unsigned)((addr ) & 0xff));
+ return address;
+}
+
+
+/** Convert a string in IPv4 dot notation to an int in network order.
+ *
+ * @param address address in dot notation
+ * @param inp result of conversion (in network order)
+ * @return 0 on success, error code on error
+ */
+int inet_aton(const char *address, struct in_addr *inp){
+ int err = 0;
+ unsigned long addr;
+
+ err = get_inet_addr(address, &addr);
+ if(err) goto exit;
+ inp->s_addr = addr;
+ exit:
+ return err;
+}
+#endif
+
+/** Convert a hostname or IPv4 address string to an address in network order.
+ *
+ * @param name input hostname or address string
+ * @param address where to put the address
+ * @return 1 if address found OK, 0 otherwise
+ */
+int get_host_address(const char *name, unsigned long *address){
+#ifdef __KERNEL__
+ return get_inet_addr(name, address) == 0;
+#else
+ struct hostent *host = gethostbyname(name);
+ if(!host){
+ return 0;
+ }
+ *address = ((struct in_addr *)(host->h_addr))->s_addr;
+ return 1;
+#endif
+}
+
+/** Convert a service name to a port (in network order).
+ *
+ * @param name service name
+ * @param port where to put the port
+ * @return 1 if service port found OK, 0 otherwise
+ */
+int get_service_port(const char *name, unsigned long *port){
+#ifdef __KERNEL__
+ return 0;
+#else
+ struct servent *service;
+ service = getservbyname(name, 0);
+ if(!service){
+ return 0;
+ }
+ *port = service->s_port;
+ return 1;
+#endif
+}
+
+/** Convert a port number (in network order) to a service name.
+ *
+ * @param port the port number
+ * @return service name if found OK, 0 otherwise
+ */
+char *get_port_service(unsigned long port){
+#ifdef __KERNEL__
+ return 0;
+#else
+ struct servent *service = getservbyport(port, 0);
+ return (service ? service->s_name : 0);
+#endif
+}
+
+/** Convert a decimal integer or service name to a port (in network order).
+ *
+ * @param s input to convert
+ * @param port where to put the port
+ * @return 1 if port found OK, 0 otherwise
+ */
+int convert_service_to_port(const char *s, unsigned long *port){
+ int ok = 0;
+ unsigned long value;
+ if(convert_atoul(s, &value)){
+ ok = get_service_port(s, &value);
+ } else {
+ ok = (0 <= value) && (value <= PORT_MAX);
+ value = htons((unsigned short)value);
+ }
+ *port = (ok ? value : 0);
+ return ok;
+}
+
+#define MAC_ELEMENT_N 6 // Number of elements in a MAC address.
+#define MAC_DIGIT_N 2 // Number of digits in an element in a MAC address.
+#define MAC_LENGTH 17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1)
+
+/** Convert a mac address from a string of the form
+ * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
+ * Each X denotes a hex digit: 0..9, a..f, A..F.
+ * Also supports using '-' as the separator instead of ':'.
+ *
+ * @param mac_in string to convert
+ * @param mac destination for the value
+ * @return 0 on success, -1 on error
+ */
+int mac_aton(const char *mac_in, unsigned char *mac){
+ int err = 0;
+ int i, j;
+ const char *p;
+ char sep = 0;
+ unsigned char d;
+ if(!mac_in || strlen(mac_in) != MAC_LENGTH){
+ err = -1;
+ goto exit;
+ }
+ for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){
+ d = 0;
+ if(i){
+ if(!sep){
+ if(*p == ':' || *p == '-') sep = *p;
+ }
+ if(sep && *p == sep){
+ p++;
+ } else {
+ err = -1;
+ goto exit;
+ }
+ }
+ for(j = 0; j < MAC_DIGIT_N; j++, p++){
+ if(j) d <<= 4;
+ if(*p >= '0' && *p <= '9'){
+ d += (*p - '0');
+ } else if(*p >= 'A' && *p <= 'F'){
+ d += (*p - 'A') + 10;
+ } else if(*p >= 'a' && *p <= 'f'){
+ d += (*p - 'a') + 10;
+ } else {
+ err = -1;
+ goto exit;
+ }
+ }
+ mac[i] = d;
+ }
+ exit:
+ return err;
+}
+
+/** Convert a MAC address from numerical form to a string.
+ *
+ * @param mac address to convert
+ * @return static string value
+ */
+char *mac_ntoa(const unsigned char *mac){
+ static char buf[MAC_LENGTH + 1];
+ int buf_n = sizeof(buf);
+
+ memset(buf, buf_n, 0);
+ snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+ buf[buf_n - 1] = '\0';
+ return buf;
+}