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