DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10); /* * All net warning printk()s should be guarded by this function.
*/ int net_ratelimit(void)
{ return __ratelimit(&net_ratelimit_state);
}
EXPORT_SYMBOL(net_ratelimit);
/* * Convert an ASCII string to binary IP. * This is outside of net/ipv4/ because various code that uses IP addresses * is otherwise not dependent on the TCP/IP stack.
*/
__be32 in_aton(constchar *str)
{ unsignedint l; unsignedint val; int i;
l = 0; for (i = 0; i < 4; i++) {
l <<= 8; if (*str != '\0') {
val = 0; while (*str != '\0' && *str != '.' && *str != '\n') {
val *= 10;
val += *str - '0';
str++;
}
l |= val; if (*str != '\0')
str++;
}
} return htonl(l);
}
EXPORT_SYMBOL(in_aton);
staticinlineint xdigit2bin(char c, int delim)
{ int val;
if (c == delim || c == '\0') return IN6PTON_DELIM; if (c == ':') return IN6PTON_COLON_MASK; if (c == '.') return IN6PTON_DOT;
val = hex_to_bin(c); if (val >= 0) return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
if (delim == -1) return IN6PTON_DELIM; return IN6PTON_UNKNOWN;
}
/** * in4_pton - convert an IPv4 address from literal to binary representation * @src: the start of the IPv4 address string * @srclen: the length of the string, -1 means strlen(src) * @dst: the binary (u8[4] array) representation of the IPv4 address * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter * @end: A pointer to the end of the parsed string will be placed here * * Return one on success, return zero when any error occurs * and @end will point to the end of the parsed string. *
*/ int in4_pton(constchar *src, int srclen,
u8 *dst, int delim, constchar **end)
{ constchar *s;
u8 *d;
u8 dbuf[4]; int ret = 0; int i; int w = 0;
if (srclen < 0)
srclen = strlen(src);
s = src;
d = dbuf;
i = 0; while (1) { int c;
c = xdigit2bin(srclen > 0 ? *s : '\0', delim); if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) { goto out;
} if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) { if (w == 0) goto out;
*d++ = w & 0xff;
w = 0;
i++; if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { if (i != 4) goto out; break;
} goto cont;
}
w = (w * 10) + c; if ((w & 0xffff) > 255) { goto out;
}
cont: if (i >= 4) goto out;
s++;
srclen--;
}
ret = 1;
memcpy(dst, dbuf, sizeof(dbuf));
out: if (end)
*end = s; return ret;
}
EXPORT_SYMBOL(in4_pton);
/** * in6_pton - convert an IPv6 address from literal to binary representation * @src: the start of the IPv6 address string * @srclen: the length of the string, -1 means strlen(src) * @dst: the binary (u8[16] array) representation of the IPv6 address * @delim: the delimiter of the IPv6 address in @src, -1 means no delimiter * @end: A pointer to the end of the parsed string will be placed here * * Return one on success, return zero when any error occurs * and @end will point to the end of the parsed string. *
*/ int in6_pton(constchar *src, int srclen,
u8 *dst, int delim, constchar **end)
{ constchar *s, *tok = NULL;
u8 *d, *dc = NULL;
u8 dbuf[16]; int ret = 0; int i; int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL; int w = 0;
memset(dbuf, 0, sizeof(dbuf));
s = src;
d = dbuf; if (srclen < 0)
srclen = strlen(src);
while (1) { int c;
c = xdigit2bin(srclen > 0 ? *s : '\0', delim); if (!(c & state)) goto out; if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { /* process one 16-bit word */ if (!(state & IN6PTON_NULL)) {
*d++ = (w >> 8) & 0xff;
*d++ = w & 0xff;
}
w = 0; if (c & IN6PTON_DELIM) { /* We've processed last word */ break;
} /* * COLON_1 => XDIGIT * COLON_2 => XDIGIT|DELIM * COLON_1_2 => COLON_2
*/ switch (state & IN6PTON_COLON_MASK) { case IN6PTON_COLON_2:
dc = d;
state = IN6PTON_XDIGIT | IN6PTON_DELIM; if (dc - dbuf >= sizeof(dbuf))
state |= IN6PTON_NULL; break; case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
state = IN6PTON_XDIGIT | IN6PTON_COLON_2; break; case IN6PTON_COLON_1:
state = IN6PTON_XDIGIT; break; case IN6PTON_COLON_1_2:
state = IN6PTON_COLON_2; break; default:
state = 0;
}
tok = s + 1; goto cont;
}
if (c & IN6PTON_DOT) {
ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s); if (ret > 0) {
d += 4; break;
} goto out;
}
w = (w << 4) | (0xff & c);
state = IN6PTON_COLON_1 | IN6PTON_DELIM; if (!(w & 0xf000)) {
state |= IN6PTON_XDIGIT;
} if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
state |= IN6PTON_COLON_1_2;
state &= ~IN6PTON_DELIM;
} if (d + 2 >= dbuf + sizeof(dbuf)) {
state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
}
cont: if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
d + 4 == dbuf + sizeof(dbuf)) {
state |= IN6PTON_DOT;
} if (d >= dbuf + sizeof(dbuf)) {
state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
}
s++;
srclen--;
}
i = 15; d--;
if (dc) { while (d >= dc)
dst[i--] = *d--; while (i >= dc - dbuf)
dst[i--] = 0; while (i >= 0)
dst[i--] = *d--;
} else
memcpy(dst, dbuf, sizeof(dbuf));
ret = 1;
out: if (end)
*end = s; return ret;
}
EXPORT_SYMBOL(in6_pton);
/** * inet_pton_with_scope - convert an IPv4/IPv6 and port to socket address * @net: net namespace (used for scope handling) * @af: address family, AF_INET, AF_INET6 or AF_UNSPEC for either * @src: the start of the address string * @port: the start of the port string (or NULL for none) * @addr: output socket address * * Return zero on success, return errno when any error occurs.
*/ int inet_pton_with_scope(struct net *net, __kernel_sa_family_t af, constchar *src, constchar *port, struct sockaddr_storage *addr)
{
u16 port_num; int ret = -EINVAL;
if (port) { if (kstrtou16(port, 0, &port_num)) return -EINVAL;
} else {
port_num = 0;
}
switch (af) { case AF_INET:
ret = inet4_pton(src, port_num, addr); break; case AF_INET6:
ret = inet6_pton(net, src, port_num, addr); break; case AF_UNSPEC:
ret = inet4_pton(src, port_num, addr); if (ret)
ret = inet6_pton(net, src, port_num, addr); break; default:
pr_err("unexpected address family %d\n", af);
}
/** * inet_proto_csum_replace16 - update layer 4 header checksum field * @sum: Layer 4 header checksum field * @skb: sk_buff for the packet * @from: old IPv6 address * @to: new IPv6 address * @pseudohdr: True if layer 4 header checksum includes pseudoheader * * Update layer 4 header as per the update in IPv6 src/dst address. * * There is no need to update skb->csum in this function, because update in two * fields a.) IPv6 src/dst address and b.) L4 header checksum cancels each other * for skb->csum calculation. Whereas inet_proto_csum_replace4 function needs to * update skb->csum, because update in 3 fields a.) IPv4 src/dst address, * b.) IPv4 Header checksum and c.) L4 header checksum results in same diff as * L4 Header checksum for skb->csum calculation.
*/ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, const __be32 *from, const __be32 *to, bool pseudohdr)
{
__be32 diff[] = {
~from[0], ~from[1], ~from[2], ~from[3],
to[0], to[1], to[2], to[3],
}; if (skb->ip_summed != CHECKSUM_PARTIAL) {
*sum = csum_fold(csum_partial(diff, sizeof(diff),
~csum_unfold(*sum)));
} elseif (pseudohdr)
*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
csum_unfold(*sum)));
}
EXPORT_SYMBOL(inet_proto_csum_replace16);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.