The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/core/utils.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/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 
   35 int net_msg_warn __read_mostly = 1;
   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 {
   44         return __ratelimit(&net_ratelimit_state);
   45 }
   46 EXPORT_SYMBOL(net_ratelimit);
   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 - '';
   68                                 str++;
   69                         }
   70                         l |= val;
   71                         if (*str != '\0')
   72                                 str++;
   73                 }
   74         }
   75         return htonl(l);
   76 }
   77 EXPORT_SYMBOL(in_aton);
   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 
  110 /**
  111  * in4_pton - convert an IPv4 address from literal to binary representation
  112  * @src: the start of the IPv4 address string
  113  * @srclen: the length of the string, -1 means strlen(src)
  114  * @dst: the binary (u8[4] array) representation of the IPv4 address
  115  * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter
  116  * @end: A pointer to the end of the parsed string will be placed here
  117  *
  118  * Return one on success, return zero when any error occurs
  119  * and @end will point to the end of the parsed string.
  120  *
  121  */
  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);
  141                 if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) {
  142                         goto out;
  143                 }
  144                 if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
  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 }
  174 EXPORT_SYMBOL(in4_pton);
  175 
  176 /**
  177  * in6_pton - convert an IPv6 address from literal to binary representation
  178  * @src: the start of the IPv6 address string
  179  * @srclen: the length of the string, -1 means strlen(src)
  180  * @dst: the binary (u8[16] array) representation of the IPv6 address
  181  * @delim: the delimiter of the IPv6 address in @src, -1 means no delimiter
  182  * @end: A pointer to the end of the parsed string will be placed here
  183  *
  184  * Return one on success, return zero when any error occurs
  185  * and @end will point to the end of the parsed string.
  186  *
  187  */
  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;
  197         int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
  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;
  236                         case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
  237                                 state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
  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)) {
  271                         state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
  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)) {
  279                         state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
  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 }
  303 EXPORT_SYMBOL(in6_pton);
  304 
  305 void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
  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 }
  319 EXPORT_SYMBOL(inet_proto_csum_replace4);
  320 
  321 void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
  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 }
  339 EXPORT_SYMBOL(inet_proto_csum_replace16);
  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 }
  363 EXPORT_SYMBOL(mac_pton);

Cache object: 1fc40fec75b59c7fc80fc09b0a96dc9f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.