Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
utils.c
Go to the documentation of this file.
1 /*
2  * Generic address resultion entity
3  *
4  * Authors:
5  * net_random Alan Cox
6  * net_ratelimit Andi Kleen
7  * in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project
8  *
9  * Created by Alexey Kuznetsov <[email protected]>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version
14  * 2 of the License, or (at your option) any later version.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/jiffies.h>
19 #include <linux/kernel.h>
20 #include <linux/inet.h>
21 #include <linux/mm.h>
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/types.h>
25 #include <linux/percpu.h>
26 #include <linux/init.h>
27 #include <linux/ratelimit.h>
28 
29 #include <net/sock.h>
30 #include <net/net_ratelimit.h>
31 
32 #include <asm/byteorder.h>
33 #include <asm/uaccess.h>
34 
36 EXPORT_SYMBOL(net_msg_warn);
37 
38 DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10);
39 /*
40  * All net warning printk()s should be guarded by this function.
41  */
42 int net_ratelimit(void)
43 {
45 }
47 
48 /*
49  * Convert an ASCII string to binary IP.
50  * This is outside of net/ipv4/ because various code that uses IP addresses
51  * is otherwise not dependent on the TCP/IP stack.
52  */
53 
54 __be32 in_aton(const char *str)
55 {
56  unsigned long l;
57  unsigned int val;
58  int i;
59 
60  l = 0;
61  for (i = 0; i < 4; i++) {
62  l <<= 8;
63  if (*str != '\0') {
64  val = 0;
65  while (*str != '\0' && *str != '.' && *str != '\n') {
66  val *= 10;
67  val += *str - '0';
68  str++;
69  }
70  l |= val;
71  if (*str != '\0')
72  str++;
73  }
74  }
75  return htonl(l);
76 }
78 
79 #define IN6PTON_XDIGIT 0x00010000
80 #define IN6PTON_DIGIT 0x00020000
81 #define IN6PTON_COLON_MASK 0x00700000
82 #define IN6PTON_COLON_1 0x00100000 /* single : requested */
83 #define IN6PTON_COLON_2 0x00200000 /* second : requested */
84 #define IN6PTON_COLON_1_2 0x00400000 /* :: requested */
85 #define IN6PTON_DOT 0x00800000 /* . */
86 #define IN6PTON_DELIM 0x10000000
87 #define IN6PTON_NULL 0x20000000 /* first/tail */
88 #define IN6PTON_UNKNOWN 0x40000000
89 
90 static inline int xdigit2bin(char c, int delim)
91 {
92  int val;
93 
94  if (c == delim || c == '\0')
95  return IN6PTON_DELIM;
96  if (c == ':')
97  return IN6PTON_COLON_MASK;
98  if (c == '.')
99  return IN6PTON_DOT;
100 
101  val = hex_to_bin(c);
102  if (val >= 0)
103  return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
104 
105  if (delim == -1)
106  return IN6PTON_DELIM;
107  return IN6PTON_UNKNOWN;
108 }
109 
122 int in4_pton(const char *src, int srclen,
123  u8 *dst,
124  int delim, const char **end)
125 {
126  const char *s;
127  u8 *d;
128  u8 dbuf[4];
129  int ret = 0;
130  int i;
131  int w = 0;
132 
133  if (srclen < 0)
134  srclen = strlen(src);
135  s = src;
136  d = dbuf;
137  i = 0;
138  while(1) {
139  int c;
140  c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
142  goto out;
143  }
145  if (w == 0)
146  goto out;
147  *d++ = w & 0xff;
148  w = 0;
149  i++;
150  if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
151  if (i != 4)
152  goto out;
153  break;
154  }
155  goto cont;
156  }
157  w = (w * 10) + c;
158  if ((w & 0xffff) > 255) {
159  goto out;
160  }
161 cont:
162  if (i >= 4)
163  goto out;
164  s++;
165  srclen--;
166  }
167  ret = 1;
168  memcpy(dst, dbuf, sizeof(dbuf));
169 out:
170  if (end)
171  *end = s;
172  return ret;
173 }
175 
188 int in6_pton(const char *src, int srclen,
189  u8 *dst,
190  int delim, const char **end)
191 {
192  const char *s, *tok = NULL;
193  u8 *d, *dc = NULL;
194  u8 dbuf[16];
195  int ret = 0;
196  int i;
198  int w = 0;
199 
200  memset(dbuf, 0, sizeof(dbuf));
201 
202  s = src;
203  d = dbuf;
204  if (srclen < 0)
205  srclen = strlen(src);
206 
207  while (1) {
208  int c;
209 
210  c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
211  if (!(c & state))
212  goto out;
213  if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
214  /* process one 16-bit word */
215  if (!(state & IN6PTON_NULL)) {
216  *d++ = (w >> 8) & 0xff;
217  *d++ = w & 0xff;
218  }
219  w = 0;
220  if (c & IN6PTON_DELIM) {
221  /* We've processed last word */
222  break;
223  }
224  /*
225  * COLON_1 => XDIGIT
226  * COLON_2 => XDIGIT|DELIM
227  * COLON_1_2 => COLON_2
228  */
229  switch (state & IN6PTON_COLON_MASK) {
230  case IN6PTON_COLON_2:
231  dc = d;
232  state = IN6PTON_XDIGIT | IN6PTON_DELIM;
233  if (dc - dbuf >= sizeof(dbuf))
234  state |= IN6PTON_NULL;
235  break;
238  break;
239  case IN6PTON_COLON_1:
240  state = IN6PTON_XDIGIT;
241  break;
242  case IN6PTON_COLON_1_2:
243  state = IN6PTON_COLON_2;
244  break;
245  default:
246  state = 0;
247  }
248  tok = s + 1;
249  goto cont;
250  }
251 
252  if (c & IN6PTON_DOT) {
253  ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s);
254  if (ret > 0) {
255  d += 4;
256  break;
257  }
258  goto out;
259  }
260 
261  w = (w << 4) | (0xff & c);
262  state = IN6PTON_COLON_1 | IN6PTON_DELIM;
263  if (!(w & 0xf000)) {
264  state |= IN6PTON_XDIGIT;
265  }
266  if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
267  state |= IN6PTON_COLON_1_2;
268  state &= ~IN6PTON_DELIM;
269  }
270  if (d + 2 >= dbuf + sizeof(dbuf)) {
272  }
273 cont:
274  if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
275  d + 4 == dbuf + sizeof(dbuf)) {
276  state |= IN6PTON_DOT;
277  }
278  if (d >= dbuf + sizeof(dbuf)) {
280  }
281  s++;
282  srclen--;
283  }
284 
285  i = 15; d--;
286 
287  if (dc) {
288  while(d >= dc)
289  dst[i--] = *d--;
290  while(i >= dc - dbuf)
291  dst[i--] = 0;
292  while(i >= 0)
293  dst[i--] = *d--;
294  } else
295  memcpy(dst, dbuf, sizeof(dbuf));
296 
297  ret = 1;
298 out:
299  if (end)
300  *end = s;
301  return ret;
302 }
304 
306  __be32 from, __be32 to, int pseudohdr)
307 {
308  __be32 diff[] = { ~from, to };
309  if (skb->ip_summed != CHECKSUM_PARTIAL) {
310  *sum = csum_fold(csum_partial(diff, sizeof(diff),
311  ~csum_unfold(*sum)));
312  if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
313  skb->csum = ~csum_partial(diff, sizeof(diff),
314  ~skb->csum);
315  } else if (pseudohdr)
316  *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
317  csum_unfold(*sum)));
318 }
320 
322  const __be32 *from, const __be32 *to,
323  int pseudohdr)
324 {
325  __be32 diff[] = {
326  ~from[0], ~from[1], ~from[2], ~from[3],
327  to[0], to[1], to[2], to[3],
328  };
329  if (skb->ip_summed != CHECKSUM_PARTIAL) {
330  *sum = csum_fold(csum_partial(diff, sizeof(diff),
331  ~csum_unfold(*sum)));
332  if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
333  skb->csum = ~csum_partial(diff, sizeof(diff),
334  ~skb->csum);
335  } else if (pseudohdr)
336  *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
337  csum_unfold(*sum)));
338 }
340 
341 int mac_pton(const char *s, u8 *mac)
342 {
343  int i;
344 
345  /* XX:XX:XX:XX:XX:XX */
346  if (strlen(s) < 3 * ETH_ALEN - 1)
347  return 0;
348 
349  /* Don't dirty result unless string is valid MAC. */
350  for (i = 0; i < ETH_ALEN; i++) {
351  if (!strchr("0123456789abcdefABCDEF", s[i * 3]))
352  return 0;
353  if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1]))
354  return 0;
355  if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
356  return 0;
357  }
358  for (i = 0; i < ETH_ALEN; i++) {
359  mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
360  }
361  return 1;
362 }