1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #include "socket.h" 3 4 #include <errno.h> 5 #include <limits.h> 6 #include <stddef.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <sys/socket.h> 10 11 int pldm_socket_sndbuf_init(struct pldm_socket_sndbuf *ctx, int socket) 12 { 13 FILE *fp; 14 long max_buf_size; 15 char line[128]; 16 char *endptr; 17 18 if (socket == -1) { 19 return -1; 20 } 21 ctx->socket = socket; 22 23 fp = fopen("/proc/sys/net/core/wmem_max", "r"); 24 if (fp == NULL) { 25 return -1; 26 } 27 28 if (fgets(line, sizeof(line), fp) == NULL) { 29 fclose(fp); 30 return -1; 31 } 32 33 errno = 0; 34 max_buf_size = strtol(line, &endptr, 10); 35 if (errno != 0 || endptr == line) { 36 fclose(fp); 37 return -1; 38 } 39 40 fclose(fp); 41 42 if (max_buf_size > INT_MAX) { 43 max_buf_size = INT_MAX; 44 } 45 ctx->max_size = (int)max_buf_size; 46 47 if (pldm_socket_sndbuf_get(ctx)) { 48 return -1; 49 } 50 51 return 0; 52 } 53 54 int pldm_socket_sndbuf_accomodate(struct pldm_socket_sndbuf *ctx, int msg_len) 55 { 56 if (msg_len < ctx->size) { 57 return 0; 58 } 59 /* If message is bigger than the max size, don't return a failure. Set 60 * the buffer to the max size and see what happens. We don't know how 61 * much of the extra space the kernel actually uses so let it tell us if 62 * there wasn't enough space */ 63 if (msg_len > ctx->max_size) { 64 msg_len = ctx->max_size; 65 } 66 if (ctx->size == ctx->max_size) { 67 return 0; 68 } 69 int rc = setsockopt(ctx->socket, SOL_SOCKET, SO_SNDBUF, &(msg_len), 70 sizeof(msg_len)); 71 if (rc == -1) { 72 return -1; 73 } 74 ctx->size = msg_len; 75 return 0; 76 } 77 78 int pldm_socket_sndbuf_get(struct pldm_socket_sndbuf *ctx) 79 { 80 /* size returned by getsockopt is the actual size of the buffer - twice 81 * the size of the value used by setsockopt. So for consistency, return 82 * half of the buffer size */ 83 int buf_size; 84 socklen_t optlen = sizeof(buf_size); 85 int rc = getsockopt(ctx->socket, SOL_SOCKET, SO_SNDBUF, &(buf_size), 86 &optlen); 87 if (rc == -1) { 88 return -1; 89 } 90 ctx->size = buf_size / 2; 91 return 0; 92 } 93