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 <kuznet@ms2.inr.ac.ru> 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/ctype.h> 21 #include <linux/inet.h> 22 #include <linux/mm.h> 23 #include <linux/net.h> 24 #include <linux/string.h> 25 #include <linux/types.h> 26 #include <linux/percpu.h> 27 #include <linux/init.h> 28 #include <linux/ratelimit.h> 29 30 #include <net/sock.h> 31 #include <net/net_ratelimit.h> 32 33 #include <asm/byteorder.h> 34 #include <asm/uaccess.h> 35 36 int net_msg_warn __read_mostly = 1; 37 EXPORT_SYMBOL(net_msg_warn); 38 39 DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10); 40 /* 41 * All net warning printk()s should be guarded by this function. 42 */ 43 int net_ratelimit(void) 44 { 45 return __ratelimit(&net_ratelimit_state); 46 } 47 EXPORT_SYMBOL(net_ratelimit); 48 49 /* 50 * Convert an ASCII string to binary IP. 51 * This is outside of net/ipv4/ because various code that uses IP addresses 52 * is otherwise not dependent on the TCP/IP stack. 53 */ 54 55 __be32 in_aton(const char *str) 56 { 57 unsigned long l; 58 unsigned int val; 59 int i; 60 61 l = 0; 62 for (i = 0; i < 4; i++) { 63 l <<= 8; 64 if (*str != '\0') { 65 val = 0; 66 while (*str != '\0' && *str != '.' && *str != '\n') { 67 val *= 10; 68 val += *str - '0'; 69 str++; 70 } 71 l |= val; 72 if (*str != '\0') 73 str++; 74 } 75 } 76 return htonl(l); 77 } 78 EXPORT_SYMBOL(in_aton); 79 80 #define IN6PTON_XDIGIT 0x00010000 81 #define IN6PTON_DIGIT 0x00020000 82 #define IN6PTON_COLON_MASK 0x00700000 83 #define IN6PTON_COLON_1 0x00100000 /* single : requested */ 84 #define IN6PTON_COLON_2 0x00200000 /* second : requested */ 85 #define IN6PTON_COLON_1_2 0x00400000 /* :: requested */ 86 #define IN6PTON_DOT 0x00800000 /* . */ 87 #define IN6PTON_DELIM 0x10000000 88 #define IN6PTON_NULL 0x20000000 /* first/tail */ 89 #define IN6PTON_UNKNOWN 0x40000000 90 91 static inline int xdigit2bin(char c, int delim) 92 { 93 int val; 94 95 if (c == delim || c == '\0') 96 return IN6PTON_DELIM; 97 if (c == ':') 98 return IN6PTON_COLON_MASK; 99 if (c == '.') 100 return IN6PTON_DOT; 101 102 val = hex_to_bin(c); 103 if (val >= 0) 104 return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0); 105 106 if (delim == -1) 107 return IN6PTON_DELIM; 108 return IN6PTON_UNKNOWN; 109 } 110 111 /** 112 * in4_pton - convert an IPv4 address from literal to binary representation 113 * @src: the start of the IPv4 address string 114 * @srclen: the length of the string, -1 means strlen(src) 115 * @dst: the binary (u8[4] array) representation of the IPv4 address 116 * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter 117 * @end: A pointer to the end of the parsed string will be placed here 118 * 119 * Return one on success, return zero when any error occurs 120 * and @end will point to the end of the parsed string. 121 * 122 */ 123 int in4_pton(const char *src, int srclen, 124 u8 *dst, 125 int delim, const char **end) 126 { 127 const char *s; 128 u8 *d; 129 u8 dbuf[4]; 130 int ret = 0; 131 int i; 132 int w = 0; 133 134 if (srclen < 0) 135 srclen = strlen(src); 136 s = src; 137 d = dbuf; 138 i = 0; 139 while(1) { 140 int c; 141 c = xdigit2bin(srclen > 0 ? *s : '\0', delim); 142 if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) { 143 goto out; 144 } 145 if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) { 146 if (w == 0) 147 goto out; 148 *d++ = w & 0xff; 149 w = 0; 150 i++; 151 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { 152 if (i != 4) 153 goto out; 154 break; 155 } 156 goto cont; 157 } 158 w = (w * 10) + c; 159 if ((w & 0xffff) > 255) { 160 goto out; 161 } 162 cont: 163 if (i >= 4) 164 goto out; 165 s++; 166 srclen--; 167 } 168 ret = 1; 169 memcpy(dst, dbuf, sizeof(dbuf)); 170 out: 171 if (end) 172 *end = s; 173 return ret; 174 } 175 EXPORT_SYMBOL(in4_pton); 176 177 /** 178 * in6_pton - convert an IPv6 address from literal to binary representation 179 * @src: the start of the IPv6 address string 180 * @srclen: the length of the string, -1 means strlen(src) 181 * @dst: the binary (u8[16] array) representation of the IPv6 address 182 * @delim: the delimiter of the IPv6 address in @src, -1 means no delimiter 183 * @end: A pointer to the end of the parsed string will be placed here 184 * 185 * Return one on success, return zero when any error occurs 186 * and @end will point to the end of the parsed string. 187 * 188 */ 189 int in6_pton(const char *src, int srclen, 190 u8 *dst, 191 int delim, const char **end) 192 { 193 const char *s, *tok = NULL; 194 u8 *d, *dc = NULL; 195 u8 dbuf[16]; 196 int ret = 0; 197 int i; 198 int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL; 199 int w = 0; 200 201 memset(dbuf, 0, sizeof(dbuf)); 202 203 s = src; 204 d = dbuf; 205 if (srclen < 0) 206 srclen = strlen(src); 207 208 while (1) { 209 int c; 210 211 c = xdigit2bin(srclen > 0 ? *s : '\0', delim); 212 if (!(c & state)) 213 goto out; 214 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { 215 /* process one 16-bit word */ 216 if (!(state & IN6PTON_NULL)) { 217 *d++ = (w >> 8) & 0xff; 218 *d++ = w & 0xff; 219 } 220 w = 0; 221 if (c & IN6PTON_DELIM) { 222 /* We've processed last word */ 223 break; 224 } 225 /* 226 * COLON_1 => XDIGIT 227 * COLON_2 => XDIGIT|DELIM 228 * COLON_1_2 => COLON_2 229 */ 230 switch (state & IN6PTON_COLON_MASK) { 231 case IN6PTON_COLON_2: 232 dc = d; 233 state = IN6PTON_XDIGIT | IN6PTON_DELIM; 234 if (dc - dbuf >= sizeof(dbuf)) 235 state |= IN6PTON_NULL; 236 break; 237 case IN6PTON_COLON_1|IN6PTON_COLON_1_2: 238 state = IN6PTON_XDIGIT | IN6PTON_COLON_2; 239 break; 240 case IN6PTON_COLON_1: 241 state = IN6PTON_XDIGIT; 242 break; 243 case IN6PTON_COLON_1_2: 244 state = IN6PTON_COLON_2; 245 break; 246 default: 247 state = 0; 248 } 249 tok = s + 1; 250 goto cont; 251 } 252 253 if (c & IN6PTON_DOT) { 254 ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s); 255 if (ret > 0) { 256 d += 4; 257 break; 258 } 259 goto out; 260 } 261 262 w = (w << 4) | (0xff & c); 263 state = IN6PTON_COLON_1 | IN6PTON_DELIM; 264 if (!(w & 0xf000)) { 265 state |= IN6PTON_XDIGIT; 266 } 267 if (!dc && d + 2 < dbuf + sizeof(dbuf)) { 268 state |= IN6PTON_COLON_1_2; 269 state &= ~IN6PTON_DELIM; 270 } 271 if (d + 2 >= dbuf + sizeof(dbuf)) { 272 state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2); 273 } 274 cont: 275 if ((dc && d + 4 < dbuf + sizeof(dbuf)) || 276 d + 4 == dbuf + sizeof(dbuf)) { 277 state |= IN6PTON_DOT; 278 } 279 if (d >= dbuf + sizeof(dbuf)) { 280 state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK); 281 } 282 s++; 283 srclen--; 284 } 285 286 i = 15; d--; 287 288 if (dc) { 289 while(d >= dc) 290 dst[i--] = *d--; 291 while(i >= dc - dbuf) 292 dst[i--] = 0; 293 while(i >= 0) 294 dst[i--] = *d--; 295 } else 296 memcpy(dst, dbuf, sizeof(dbuf)); 297 298 ret = 1; 299 out: 300 if (end) 301 *end = s; 302 return ret; 303 } 304 EXPORT_SYMBOL(in6_pton); 305 306 void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, 307 __be32 from, __be32 to, int pseudohdr) 308 { 309 if (skb->ip_summed != CHECKSUM_PARTIAL) { 310 *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), from), 311 to)); 312 if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) 313 skb->csum = ~csum_add(csum_sub(~(skb->csum), from), to); 314 } else if (pseudohdr) 315 *sum = ~csum_fold(csum_add(csum_sub(csum_unfold(*sum), from), 316 to)); 317 } 318 EXPORT_SYMBOL(inet_proto_csum_replace4); 319 320 void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, 321 const __be32 *from, const __be32 *to, 322 int pseudohdr) 323 { 324 __be32 diff[] = { 325 ~from[0], ~from[1], ~from[2], ~from[3], 326 to[0], to[1], to[2], to[3], 327 }; 328 if (skb->ip_summed != CHECKSUM_PARTIAL) { 329 *sum = csum_fold(csum_partial(diff, sizeof(diff), 330 ~csum_unfold(*sum))); 331 if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) 332 skb->csum = ~csum_partial(diff, sizeof(diff), 333 ~skb->csum); 334 } else if (pseudohdr) 335 *sum = ~csum_fold(csum_partial(diff, sizeof(diff), 336 csum_unfold(*sum))); 337 } 338 EXPORT_SYMBOL(inet_proto_csum_replace16); 339 340 struct __net_random_once_work { 341 struct work_struct work; 342 struct static_key *key; 343 }; 344 345 static void __net_random_once_deferred(struct work_struct *w) 346 { 347 struct __net_random_once_work *work = 348 container_of(w, struct __net_random_once_work, work); 349 BUG_ON(!static_key_enabled(work->key)); 350 static_key_slow_dec(work->key); 351 kfree(work); 352 } 353 354 static void __net_random_once_disable_jump(struct static_key *key) 355 { 356 struct __net_random_once_work *w; 357 358 w = kmalloc(sizeof(*w), GFP_ATOMIC); 359 if (!w) 360 return; 361 362 INIT_WORK(&w->work, __net_random_once_deferred); 363 w->key = key; 364 schedule_work(&w->work); 365 } 366 367 bool __net_get_random_once(void *buf, int nbytes, bool *done, 368 struct static_key *once_key) 369 { 370 static DEFINE_SPINLOCK(lock); 371 unsigned long flags; 372 373 spin_lock_irqsave(&lock, flags); 374 if (*done) { 375 spin_unlock_irqrestore(&lock, flags); 376 return false; 377 } 378 379 get_random_bytes(buf, nbytes); 380 *done = true; 381 spin_unlock_irqrestore(&lock, flags); 382 383 __net_random_once_disable_jump(once_key); 384 385 return true; 386 } 387 EXPORT_SYMBOL(__net_get_random_once); 388