diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -693,7 +693,8 @@ if (*lowat > *hiwat) *lowat = *hiwat; } else { - if (!sbreserve_locked(sb, cc, so, curthread)) + u_long limit = sogetmaxbuf(so); + if (!sbreserve_locked_limit(sb, cc, so, limit, curthread)) error = ENOBUFS; } if (error == 0) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -128,6 +128,7 @@ #include #include #include +#include #include #include #include @@ -2975,6 +2976,15 @@ return (0); } +u_long +sogetmaxbuf(struct socket *so) +{ + if (so->so_proto->pr_domain->dom_family != PF_NETLINK) + return (sb_max); + u_long nl_maxsockbuf = 512 * 1024 * 1024; /* 512M, XXX: init based on physmem */ + return ((priv_check(curthread, PRIV_NET_ROUTE) == 0) ? nl_maxsockbuf : sb_max); +} + /* * Kernel version of setsockopt(2). * diff --git a/sys/sys/sockopt.h b/sys/sys/sockopt.h --- a/sys/sys/sockopt.h +++ b/sys/sys/sockopt.h @@ -68,5 +68,6 @@ int accept_filt_setopt(struct socket *, struct sockopt *); int so_setsockopt(struct socket *so, int level, int optname, void *optval, size_t optlen); +u_long sogetmaxbuf(struct socket *so); #endif /* _SYS_SOCKOPT_H_ */