~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/vnet/libxutil/sys_net.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU Lesser General Public License as
 
6
 * published by the Free Software Foundation; either version 2.1 of the
 
7
 * License, or  (at your option) any later version. This library is 
 
8
 * distributed in the  hope that it will be useful, but WITHOUT ANY
 
9
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
10
 * FITNESS FOR A PARTICULAR PURPOSE.
 
11
 * See the GNU Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this library; if not, write to the Free Software Foundation,
 
15
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
16
 */
 
17
 
 
18
#include "sys_net.h"
 
19
#include "sys_string.h"
 
20
 
 
21
#ifdef __KERNEL__
 
22
#  include <linux/errno.h>
 
23
#else
 
24
#  include <errno.h>
 
25
#endif
 
26
 
 
27
/** @file
 
28
 * All network data are kept in network order and only converted to
 
29
 * host order for display. Network data includes IP addresses, port numbers and
 
30
 * network masks.
 
31
 */
 
32
 
 
33
/** Maximum value for a port. */
 
34
#define PORT_MAX 0xffff
 
35
 
 
36
/** Convert a number of bits to a network mask
 
37
 * for IP addresses. The number of bits must
 
38
 * be in the range 1-31.
 
39
 *
 
40
 * @param n number of bits to set in the mask
 
41
 * @return value with n high bits set (in network order)
 
42
 */
 
43
unsigned long bits_to_mask(int n){
 
44
    unsigned long mask = (n ? (1 << 31) : 0);
 
45
    int i;
 
46
    for(i=1; i<n; i++){
 
47
        mask |= (mask >> 1);
 
48
    }
 
49
    return htonl(mask);
 
50
}
 
51
 
 
52
/** Convert a network mask to a number of bits.
 
53
 *
 
54
 * @param mask network mask in network order
 
55
 * @return number of bits in mask
 
56
 */
 
57
int mask_to_bits(unsigned long mask){
 
58
    // Start with n set to the number of bits in the mask. Then reduce n by
 
59
    // the number of low zero bits in the mask.
 
60
    int n = 32;
 
61
    for(mask = ntohl(mask);
 
62
        (mask & 1)==0 && n>0;
 
63
        mask >>= 1){
 
64
        n--;
 
65
    }
 
66
    return n;
 
67
}
 
68
 
 
69
/** Get the index of the first occurrence of a character in a string.
 
70
 * Stops at end of string or after n characters.
 
71
 *
 
72
 * @param s input string
 
73
 * @param n maximum number of charactes to search
 
74
 * @param c character to look for
 
75
 * @return index of first occurrence, -1 if not found
 
76
 */
 
77
inline static int indexof(const char *s, int n, char c){
 
78
    int i;
 
79
    for(i=0; i<n && *s; i++, s++){
 
80
        if(*s == c) return i;
 
81
    }
 
82
    return -1;
 
83
}
 
84
 
 
85
/** Convert an IPv4 address in dot notation into an unsigned long (in network order).
 
86
 *
 
87
 * @param s input string
 
88
 * @param address where to put the address
 
89
 * @return 0 on success, negative on error
 
90
 */
 
91
int get_inet_addr(const char *s, unsigned long *address){
 
92
    // Number of bits in a byte.
 
93
    const int BYTE_BITS = 8;
 
94
    // Number of bytes in a word.
 
95
    const int WORD_BYTES = 4;
 
96
    // Max value for a component of an address.
 
97
    const int ADDR_MAX  = 255;
 
98
    // Separator for components of an address.
 
99
    const char dot = '.';
 
100
 
 
101
    int n;
 
102
    unsigned long addr = 0;
 
103
    unsigned long v;
 
104
    int i;
 
105
    int err = -EINVAL;
 
106
    // Bit shift for the current byte.
 
107
    int shift = BYTE_BITS * (WORD_BYTES - 1);
 
108
    char buf[64];
 
109
 
 
110
    n = strlen(s);
 
111
    if(n >= sizeof(buf)){
 
112
        goto exit;
 
113
    }
 
114
    for(i=0; i < WORD_BYTES; i++){
 
115
        int idx = indexof(s, n, dot);
 
116
        idx = (idx < 0 ? strlen(s) : idx);
 
117
        strncpy(buf, s, idx); buf[idx]='\0';
 
118
        if(convert_atoul(buf, &v)){
 
119
            goto exit;
 
120
        }
 
121
        if(v < 0 || v > ADDR_MAX){
 
122
            goto exit;
 
123
        }
 
124
        addr |= (v << shift);
 
125
        if(idx == n) break;
 
126
        shift -= BYTE_BITS;
 
127
        s += idx+1;
 
128
    }
 
129
    err = 0;
 
130
  exit:
 
131
    addr = htonl(addr);
 
132
    *address = (err ? 0 : addr);
 
133
    return err;
 
134
}
 
135
 
 
136
#ifdef __KERNEL__
 
137
/** Convert an address in network order to IPv4 dot notation.
 
138
 * The return value is a static buffer which is overwritten on each call.
 
139
 *
 
140
 * @param inaddr address (in network order)
 
141
 * @return address in dot notation
 
142
 */
 
143
char *inet_ntoa(struct in_addr inaddr){
 
144
    static char address[16] = {};
 
145
    uint32_t addr = ntohl(inaddr.s_addr);
 
146
    snprintf(address, sizeof(address), "%d.%d.%d.%d",
 
147
            (unsigned)((addr >> 24) & 0xff),
 
148
            (unsigned)((addr >> 16) & 0xff),
 
149
            (unsigned)((addr >>  8) & 0xff),
 
150
            (unsigned)((addr      ) & 0xff));
 
151
    return address;
 
152
}
 
153
 
 
154
 
 
155
/** Convert a string in IPv4 dot notation to an int in network order.
 
156
 *
 
157
 * @param address address in dot notation
 
158
 * @param inp result of conversion (in network order)
 
159
 * @return 0 on success, error code on error
 
160
 */
 
161
int inet_aton(const char *address, struct in_addr *inp){
 
162
    int err = 0; 
 
163
    unsigned long addr;
 
164
    
 
165
    err = get_inet_addr(address, &addr);
 
166
    if(err) goto exit;
 
167
    inp->s_addr = addr;
 
168
  exit:
 
169
    return err;
 
170
}
 
171
#endif
 
172
 
 
173
/** Convert a hostname or IPv4 address string to an address in network order.
 
174
 *
 
175
 * @param name input hostname or address string
 
176
 * @param address where to put the address
 
177
 * @return 0 if address found OK, nonzero otherwise
 
178
 */
 
179
int get_host_address(const char *name, unsigned long *address){
 
180
#ifdef __KERNEL__
 
181
    return get_inet_addr(name, address);
 
182
#else
 
183
    struct hostent *host = gethostbyname(name);
 
184
    if(!host){
 
185
        return -ENOENT;
 
186
    }
 
187
    *address = ((struct in_addr *)(host->h_addr))->s_addr;
 
188
    return 0;
 
189
#endif
 
190
}
 
191
 
 
192
/** Convert a service name to a port (in network order).
 
193
 *
 
194
 * @param name service name
 
195
 * @param port where to put the port
 
196
 * @return 0 if service port found OK, negative otherwise
 
197
 */
 
198
int get_service_port(const char *name, unsigned long *port){
 
199
#ifdef __KERNEL__
 
200
    return -ENOSYS;
 
201
#else
 
202
    struct servent *service;
 
203
    service = getservbyname(name, 0);
 
204
    if(!service){
 
205
        return -EINVAL;
 
206
    }
 
207
    *port = service->s_port;
 
208
    return 0;
 
209
#endif
 
210
}
 
211
 
 
212
/** Convert a port number (in network order) to a service name.
 
213
 *
 
214
 * @param port the port number
 
215
 * @return service name if found OK, NULL otherwise
 
216
 */
 
217
char *get_port_service(unsigned long port){
 
218
#ifdef __KERNEL__
 
219
    return NULL;
 
220
#else
 
221
    struct servent *service = getservbyport(port, 0);
 
222
    return (service ? service->s_name : NULL);
 
223
#endif
 
224
}
 
225
 
 
226
/** Convert a decimal integer or service name to a port (in network order).
 
227
 *
 
228
 * @param s input to convert
 
229
 * @param port where to put the port
 
230
 * @return 0 if port found OK, -1 otherwise
 
231
 */
 
232
int convert_service_to_port(const char *s, unsigned long *port){
 
233
    int err = 0;
 
234
    unsigned long value;
 
235
    if(convert_atoul(s, &value) == 0){
 
236
        int ok = (0 <= value) && (value <= PORT_MAX);
 
237
        if(ok){
 
238
            value = htons((unsigned short)value);
 
239
        } else {
 
240
            err = -EINVAL;
 
241
        }
 
242
    } else {
 
243
        err = get_service_port(s, &value);
 
244
    }
 
245
    *port = (err ? 0: value);
 
246
    return err;
 
247
}
 
248
 
 
249
#define MAC_ELEMENT_N  6 // Number of elements in a MAC address.
 
250
#define MAC_DIGIT_N    2 // Number of digits in an element in a MAC address.
 
251
#define MAC_LENGTH    17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1)
 
252
 
 
253
/** Convert a mac address from a string of the form
 
254
 * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
 
255
 * Each X denotes a hex digit: 0..9, a..f, A..F.
 
256
 * Also supports using '-' as the separator instead of ':'.
 
257
 *
 
258
 * @param mac_in string to convert
 
259
 * @param mac destination for the value
 
260
 * @return 0 on success, -1 on error
 
261
 */
 
262
int mac_aton(const char *mac_in, unsigned char *mac){
 
263
    int err = 0;
 
264
    int i, j;
 
265
    const char *p;
 
266
    char sep = 0;
 
267
    unsigned char d;
 
268
    if(!mac_in || strlen(mac_in) != MAC_LENGTH){
 
269
        err = -1;
 
270
        goto exit;
 
271
    }
 
272
    for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){
 
273
        d = 0;
 
274
        if(i){
 
275
            if(!sep){
 
276
                if(*p == ':' || *p == '-') sep = *p;
 
277
            }
 
278
            if(sep && *p == sep){
 
279
                p++;
 
280
            } else {
 
281
                err = -1;
 
282
                goto exit;
 
283
            }
 
284
        }
 
285
        for(j = 0; j < MAC_DIGIT_N; j++, p++){
 
286
            if(j) d <<= 4;
 
287
            if(*p >= '0' && *p <= '9'){
 
288
                d += (*p - '0');
 
289
            } else if(*p >= 'A' && *p <= 'F'){
 
290
                d += (*p - 'A') + 10;
 
291
            } else if(*p >= 'a' && *p <= 'f'){
 
292
                d += (*p - 'a') + 10;
 
293
            } else {
 
294
                err = -1;
 
295
                goto exit;
 
296
            }
 
297
        }
 
298
        mac[i] = d;
 
299
    }
 
300
  exit:
 
301
    return err;
 
302
}
 
303
 
 
304
/** Convert a MAC address from numerical form to a string.
 
305
 *
 
306
 * @param mac address to convert
 
307
 * @return static string value
 
308
 */
 
309
char *mac_ntoa(const unsigned char *mac){
 
310
    static char buf[MAC_LENGTH + 1];
 
311
    int buf_n = sizeof(buf);
 
312
 
 
313
    memset(buf, 0, buf_n);
 
314
    snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
 
315
             mac[0], mac[1], mac[2],
 
316
             mac[3], mac[4], mac[5]);
 
317
    buf[buf_n - 1] = '\0';
 
318
    return buf;
 
319
}