Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Generic address resultion entity
0004  *
0005  *  Authors:
0006  *  net_random Alan Cox
0007  *  net_ratelimit Andi Kleen
0008  *  in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project
0009  *
0010  *  Created by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
0011  */
0012 
0013 #include <linux/module.h>
0014 #include <linux/jiffies.h>
0015 #include <linux/kernel.h>
0016 #include <linux/ctype.h>
0017 #include <linux/inet.h>
0018 #include <linux/mm.h>
0019 #include <linux/net.h>
0020 #include <linux/string.h>
0021 #include <linux/types.h>
0022 #include <linux/percpu.h>
0023 #include <linux/init.h>
0024 #include <linux/ratelimit.h>
0025 #include <linux/socket.h>
0026 
0027 #include <net/sock.h>
0028 #include <net/net_ratelimit.h>
0029 #include <net/ipv6.h>
0030 
0031 #include <asm/byteorder.h>
0032 #include <linux/uaccess.h>
0033 
0034 DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10);
0035 /*
0036  * All net warning printk()s should be guarded by this function.
0037  */
0038 int net_ratelimit(void)
0039 {
0040     return __ratelimit(&net_ratelimit_state);
0041 }
0042 EXPORT_SYMBOL(net_ratelimit);
0043 
0044 /*
0045  * Convert an ASCII string to binary IP.
0046  * This is outside of net/ipv4/ because various code that uses IP addresses
0047  * is otherwise not dependent on the TCP/IP stack.
0048  */
0049 
0050 __be32 in_aton(const char *str)
0051 {
0052     unsigned int l;
0053     unsigned int val;
0054     int i;
0055 
0056     l = 0;
0057     for (i = 0; i < 4; i++) {
0058         l <<= 8;
0059         if (*str != '\0') {
0060             val = 0;
0061             while (*str != '\0' && *str != '.' && *str != '\n') {
0062                 val *= 10;
0063                 val += *str - '0';
0064                 str++;
0065             }
0066             l |= val;
0067             if (*str != '\0')
0068                 str++;
0069         }
0070     }
0071     return htonl(l);
0072 }
0073 EXPORT_SYMBOL(in_aton);
0074 
0075 #define IN6PTON_XDIGIT      0x00010000
0076 #define IN6PTON_DIGIT       0x00020000
0077 #define IN6PTON_COLON_MASK  0x00700000
0078 #define IN6PTON_COLON_1     0x00100000  /* single : requested */
0079 #define IN6PTON_COLON_2     0x00200000  /* second : requested */
0080 #define IN6PTON_COLON_1_2   0x00400000  /* :: requested */
0081 #define IN6PTON_DOT     0x00800000  /* . */
0082 #define IN6PTON_DELIM       0x10000000
0083 #define IN6PTON_NULL        0x20000000  /* first/tail */
0084 #define IN6PTON_UNKNOWN     0x40000000
0085 
0086 static inline int xdigit2bin(char c, int delim)
0087 {
0088     int val;
0089 
0090     if (c == delim || c == '\0')
0091         return IN6PTON_DELIM;
0092     if (c == ':')
0093         return IN6PTON_COLON_MASK;
0094     if (c == '.')
0095         return IN6PTON_DOT;
0096 
0097     val = hex_to_bin(c);
0098     if (val >= 0)
0099         return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
0100 
0101     if (delim == -1)
0102         return IN6PTON_DELIM;
0103     return IN6PTON_UNKNOWN;
0104 }
0105 
0106 /**
0107  * in4_pton - convert an IPv4 address from literal to binary representation
0108  * @src: the start of the IPv4 address string
0109  * @srclen: the length of the string, -1 means strlen(src)
0110  * @dst: the binary (u8[4] array) representation of the IPv4 address
0111  * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter
0112  * @end: A pointer to the end of the parsed string will be placed here
0113  *
0114  * Return one on success, return zero when any error occurs
0115  * and @end will point to the end of the parsed string.
0116  *
0117  */
0118 int in4_pton(const char *src, int srclen,
0119          u8 *dst,
0120          int delim, const char **end)
0121 {
0122     const char *s;
0123     u8 *d;
0124     u8 dbuf[4];
0125     int ret = 0;
0126     int i;
0127     int w = 0;
0128 
0129     if (srclen < 0)
0130         srclen = strlen(src);
0131     s = src;
0132     d = dbuf;
0133     i = 0;
0134     while (1) {
0135         int c;
0136         c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
0137         if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) {
0138             goto out;
0139         }
0140         if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
0141             if (w == 0)
0142                 goto out;
0143             *d++ = w & 0xff;
0144             w = 0;
0145             i++;
0146             if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
0147                 if (i != 4)
0148                     goto out;
0149                 break;
0150             }
0151             goto cont;
0152         }
0153         w = (w * 10) + c;
0154         if ((w & 0xffff) > 255) {
0155             goto out;
0156         }
0157 cont:
0158         if (i >= 4)
0159             goto out;
0160         s++;
0161         srclen--;
0162     }
0163     ret = 1;
0164     memcpy(dst, dbuf, sizeof(dbuf));
0165 out:
0166     if (end)
0167         *end = s;
0168     return ret;
0169 }
0170 EXPORT_SYMBOL(in4_pton);
0171 
0172 /**
0173  * in6_pton - convert an IPv6 address from literal to binary representation
0174  * @src: the start of the IPv6 address string
0175  * @srclen: the length of the string, -1 means strlen(src)
0176  * @dst: the binary (u8[16] array) representation of the IPv6 address
0177  * @delim: the delimiter of the IPv6 address in @src, -1 means no delimiter
0178  * @end: A pointer to the end of the parsed string will be placed here
0179  *
0180  * Return one on success, return zero when any error occurs
0181  * and @end will point to the end of the parsed string.
0182  *
0183  */
0184 int in6_pton(const char *src, int srclen,
0185          u8 *dst,
0186          int delim, const char **end)
0187 {
0188     const char *s, *tok = NULL;
0189     u8 *d, *dc = NULL;
0190     u8 dbuf[16];
0191     int ret = 0;
0192     int i;
0193     int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
0194     int w = 0;
0195 
0196     memset(dbuf, 0, sizeof(dbuf));
0197 
0198     s = src;
0199     d = dbuf;
0200     if (srclen < 0)
0201         srclen = strlen(src);
0202 
0203     while (1) {
0204         int c;
0205 
0206         c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
0207         if (!(c & state))
0208             goto out;
0209         if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
0210             /* process one 16-bit word */
0211             if (!(state & IN6PTON_NULL)) {
0212                 *d++ = (w >> 8) & 0xff;
0213                 *d++ = w & 0xff;
0214             }
0215             w = 0;
0216             if (c & IN6PTON_DELIM) {
0217                 /* We've processed last word */
0218                 break;
0219             }
0220             /*
0221              * COLON_1 => XDIGIT
0222              * COLON_2 => XDIGIT|DELIM
0223              * COLON_1_2 => COLON_2
0224              */
0225             switch (state & IN6PTON_COLON_MASK) {
0226             case IN6PTON_COLON_2:
0227                 dc = d;
0228                 state = IN6PTON_XDIGIT | IN6PTON_DELIM;
0229                 if (dc - dbuf >= sizeof(dbuf))
0230                     state |= IN6PTON_NULL;
0231                 break;
0232             case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
0233                 state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
0234                 break;
0235             case IN6PTON_COLON_1:
0236                 state = IN6PTON_XDIGIT;
0237                 break;
0238             case IN6PTON_COLON_1_2:
0239                 state = IN6PTON_COLON_2;
0240                 break;
0241             default:
0242                 state = 0;
0243             }
0244             tok = s + 1;
0245             goto cont;
0246         }
0247 
0248         if (c & IN6PTON_DOT) {
0249             ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s);
0250             if (ret > 0) {
0251                 d += 4;
0252                 break;
0253             }
0254             goto out;
0255         }
0256 
0257         w = (w << 4) | (0xff & c);
0258         state = IN6PTON_COLON_1 | IN6PTON_DELIM;
0259         if (!(w & 0xf000)) {
0260             state |= IN6PTON_XDIGIT;
0261         }
0262         if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
0263             state |= IN6PTON_COLON_1_2;
0264             state &= ~IN6PTON_DELIM;
0265         }
0266         if (d + 2 >= dbuf + sizeof(dbuf)) {
0267             state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
0268         }
0269 cont:
0270         if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
0271             d + 4 == dbuf + sizeof(dbuf)) {
0272             state |= IN6PTON_DOT;
0273         }
0274         if (d >= dbuf + sizeof(dbuf)) {
0275             state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
0276         }
0277         s++;
0278         srclen--;
0279     }
0280 
0281     i = 15; d--;
0282 
0283     if (dc) {
0284         while (d >= dc)
0285             dst[i--] = *d--;
0286         while (i >= dc - dbuf)
0287             dst[i--] = 0;
0288         while (i >= 0)
0289             dst[i--] = *d--;
0290     } else
0291         memcpy(dst, dbuf, sizeof(dbuf));
0292 
0293     ret = 1;
0294 out:
0295     if (end)
0296         *end = s;
0297     return ret;
0298 }
0299 EXPORT_SYMBOL(in6_pton);
0300 
0301 static int inet4_pton(const char *src, u16 port_num,
0302         struct sockaddr_storage *addr)
0303 {
0304     struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
0305     int srclen = strlen(src);
0306 
0307     if (srclen > INET_ADDRSTRLEN)
0308         return -EINVAL;
0309 
0310     if (in4_pton(src, srclen, (u8 *)&addr4->sin_addr.s_addr,
0311              '\n', NULL) == 0)
0312         return -EINVAL;
0313 
0314     addr4->sin_family = AF_INET;
0315     addr4->sin_port = htons(port_num);
0316 
0317     return 0;
0318 }
0319 
0320 static int inet6_pton(struct net *net, const char *src, u16 port_num,
0321         struct sockaddr_storage *addr)
0322 {
0323     struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
0324     const char *scope_delim;
0325     int srclen = strlen(src);
0326 
0327     if (srclen > INET6_ADDRSTRLEN)
0328         return -EINVAL;
0329 
0330     if (in6_pton(src, srclen, (u8 *)&addr6->sin6_addr.s6_addr,
0331              '%', &scope_delim) == 0)
0332         return -EINVAL;
0333 
0334     if (ipv6_addr_type(&addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL &&
0335         src + srclen != scope_delim && *scope_delim == '%') {
0336         struct net_device *dev;
0337         char scope_id[16];
0338         size_t scope_len = min_t(size_t, sizeof(scope_id) - 1,
0339                      src + srclen - scope_delim - 1);
0340 
0341         memcpy(scope_id, scope_delim + 1, scope_len);
0342         scope_id[scope_len] = '\0';
0343 
0344         dev = dev_get_by_name(net, scope_id);
0345         if (dev) {
0346             addr6->sin6_scope_id = dev->ifindex;
0347             dev_put(dev);
0348         } else if (kstrtouint(scope_id, 0, &addr6->sin6_scope_id)) {
0349             return -EINVAL;
0350         }
0351     }
0352 
0353     addr6->sin6_family = AF_INET6;
0354     addr6->sin6_port = htons(port_num);
0355 
0356     return 0;
0357 }
0358 
0359 /**
0360  * inet_pton_with_scope - convert an IPv4/IPv6 and port to socket address
0361  * @net: net namespace (used for scope handling)
0362  * @af: address family, AF_INET, AF_INET6 or AF_UNSPEC for either
0363  * @src: the start of the address string
0364  * @port: the start of the port string (or NULL for none)
0365  * @addr: output socket address
0366  *
0367  * Return zero on success, return errno when any error occurs.
0368  */
0369 int inet_pton_with_scope(struct net *net, __kernel_sa_family_t af,
0370         const char *src, const char *port, struct sockaddr_storage *addr)
0371 {
0372     u16 port_num;
0373     int ret = -EINVAL;
0374 
0375     if (port) {
0376         if (kstrtou16(port, 0, &port_num))
0377             return -EINVAL;
0378     } else {
0379         port_num = 0;
0380     }
0381 
0382     switch (af) {
0383     case AF_INET:
0384         ret = inet4_pton(src, port_num, addr);
0385         break;
0386     case AF_INET6:
0387         ret = inet6_pton(net, src, port_num, addr);
0388         break;
0389     case AF_UNSPEC:
0390         ret = inet4_pton(src, port_num, addr);
0391         if (ret)
0392             ret = inet6_pton(net, src, port_num, addr);
0393         break;
0394     default:
0395         pr_err("unexpected address family %d\n", af);
0396     }
0397 
0398     return ret;
0399 }
0400 EXPORT_SYMBOL(inet_pton_with_scope);
0401 
0402 bool inet_addr_is_any(struct sockaddr *addr)
0403 {
0404     if (addr->sa_family == AF_INET6) {
0405         struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
0406         const struct sockaddr_in6 in6_any =
0407             { .sin6_addr = IN6ADDR_ANY_INIT };
0408 
0409         if (!memcmp(in6->sin6_addr.s6_addr,
0410                 in6_any.sin6_addr.s6_addr, 16))
0411             return true;
0412     } else if (addr->sa_family == AF_INET) {
0413         struct sockaddr_in *in = (struct sockaddr_in *)addr;
0414 
0415         if (in->sin_addr.s_addr == htonl(INADDR_ANY))
0416             return true;
0417     } else {
0418         pr_warn("unexpected address family %u\n", addr->sa_family);
0419     }
0420 
0421     return false;
0422 }
0423 EXPORT_SYMBOL(inet_addr_is_any);
0424 
0425 void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
0426                   __be32 from, __be32 to, bool pseudohdr)
0427 {
0428     if (skb->ip_summed != CHECKSUM_PARTIAL) {
0429         csum_replace4(sum, from, to);
0430         if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
0431             skb->csum = ~csum_add(csum_sub(~(skb->csum),
0432                                (__force __wsum)from),
0433                           (__force __wsum)to);
0434     } else if (pseudohdr)
0435         *sum = ~csum_fold(csum_add(csum_sub(csum_unfold(*sum),
0436                             (__force __wsum)from),
0437                        (__force __wsum)to));
0438 }
0439 EXPORT_SYMBOL(inet_proto_csum_replace4);
0440 
0441 /**
0442  * inet_proto_csum_replace16 - update layer 4 header checksum field
0443  * @sum: Layer 4 header checksum field
0444  * @skb: sk_buff for the packet
0445  * @from: old IPv6 address
0446  * @to: new IPv6 address
0447  * @pseudohdr: True if layer 4 header checksum includes pseudoheader
0448  *
0449  * Update layer 4 header as per the update in IPv6 src/dst address.
0450  *
0451  * There is no need to update skb->csum in this function, because update in two
0452  * fields a.) IPv6 src/dst address and b.) L4 header checksum cancels each other
0453  * for skb->csum calculation. Whereas inet_proto_csum_replace4 function needs to
0454  * update skb->csum, because update in 3 fields a.) IPv4 src/dst address,
0455  * b.) IPv4 Header checksum and c.) L4 header checksum results in same diff as
0456  * L4 Header checksum for skb->csum calculation.
0457  */
0458 void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
0459                    const __be32 *from, const __be32 *to,
0460                    bool pseudohdr)
0461 {
0462     __be32 diff[] = {
0463         ~from[0], ~from[1], ~from[2], ~from[3],
0464         to[0], to[1], to[2], to[3],
0465     };
0466     if (skb->ip_summed != CHECKSUM_PARTIAL) {
0467         *sum = csum_fold(csum_partial(diff, sizeof(diff),
0468                  ~csum_unfold(*sum)));
0469     } else if (pseudohdr)
0470         *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
0471                   csum_unfold(*sum)));
0472 }
0473 EXPORT_SYMBOL(inet_proto_csum_replace16);
0474 
0475 void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
0476                      __wsum diff, bool pseudohdr)
0477 {
0478     if (skb->ip_summed != CHECKSUM_PARTIAL) {
0479         csum_replace_by_diff(sum, diff);
0480         if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
0481             skb->csum = ~csum_sub(diff, skb->csum);
0482     } else if (pseudohdr) {
0483         *sum = ~csum_fold(csum_add(diff, csum_unfold(*sum)));
0484     }
0485 }
0486 EXPORT_SYMBOL(inet_proto_csum_replace_by_diff);