1 // SPDX-License-Identifier: GPL-2.0
2 #include <config.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <syslog.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9
10 #include "cliserv.h"
11 #include "nbd-debug.h"
12
13 const u64 cliserv_magic = 0x00420281861253LL;
14 const u64 opts_magic = 0x49484156454F5054LL;
15 const u64 rep_magic = 0x3e889045565a9LL;
16
17 /**
18 * Set a socket to blocking or non-blocking
19 *
20 * @param fd The socket's FD
21 * @param nb nonzero to set to non-blocking, else 0 to set to blocking
22 * @return 0 - OK, -1 failed
23 */
set_nonblocking(int fd,int nb)24 int set_nonblocking(int fd, int nb) {
25 int sf = fcntl (fd, F_GETFL, 0);
26 if (sf == -1)
27 return -1;
28 return fcntl (fd, F_SETFL, nb ? (sf | O_NONBLOCK) : (sf & ~O_NONBLOCK));
29 }
30
31
setmysockopt(int sock)32 void setmysockopt(int sock) {
33 int size = 1;
34 #if 0
35 if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int)) < 0)
36 INFO("(no sockopt/1: %m)");
37 #endif
38 #ifdef IPPROTO_TCP
39 size = 1;
40 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &size, sizeof(int)) < 0)
41 INFO("(no sockopt/2: %m)");
42 #endif
43 #if 0
44 size = 1024;
45 if (setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &size, sizeof(int)) < 0)
46 INFO("(no sockopt/3: %m)");
47 #endif
48 }
49
err_nonfatal(const char * s)50 void err_nonfatal(const char *s) {
51 char s1[150], *s2;
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wstringop-truncation"
54 strncpy(s1, s, sizeof(s1));
55 #pragma GCC diagnostic pop
56 if ((s2 = strstr(s, "%m"))) {
57 strncpy(s1 + (s2 - s), strerror(errno), sizeof(s1) - (s2 - s));
58 s2 += 2;
59 strncpy(s1 + strlen(s1), s2, sizeof(s1) - strlen(s1));
60 }
61 #ifndef sun
62 /* Solaris doesn't have %h in syslog */
63 else if ((s2 = strstr(s, "%h"))) {
64 strncpy(s1 + (s2 - s), hstrerror(h_errno), sizeof(s1) - (s2 - s));
65 s2 += 2;
66 strncpy(s1 + strlen(s1), s2, sizeof(s1) - strlen(s1));
67 }
68 #endif
69
70 s1[sizeof(s1)-1] = '\0';
71 #ifdef ISSERVER
72 syslog(LOG_ERR, "%s", s1);
73 syslog(LOG_ERR, "Exiting.");
74 #endif
75 fprintf(stderr, "Error: %s\n", s1);
76 }
77
err(const char * s)78 void err(const char *s) {
79 err_nonfatal(s);
80 fprintf(stderr, "Exiting.\n");
81 exit(EXIT_FAILURE);
82 }
83
logging(const char * name)84 void logging(const char* name) {
85 #ifdef ISSERVER
86 openlog(name, LOG_PID, LOG_DAEMON);
87 #endif
88 setvbuf(stdout, NULL, _IONBF, 0);
89 setvbuf(stderr, NULL, _IONBF, 0);
90 }
91
92 #ifndef ntohll
93 #ifdef WORDS_BIGENDIAN
ntohll(uint64_t a)94 uint64_t ntohll(uint64_t a) {
95 return a;
96 }
97 #else
ntohll(uint64_t a)98 uint64_t ntohll(uint64_t a) {
99 u32 lo = a & 0xffffffff;
100 u32 hi = a >> 32U;
101 lo = ntohl(lo);
102 hi = ntohl(hi);
103 return ((uint64_t) lo) << 32U | hi;
104 }
105 #endif
106 #endif
107
108 /**
109 * Read data from a file descriptor into a buffer
110 *
111 * @param f a file descriptor
112 * @param buf a buffer
113 * @param len the number of bytes to be read
114 * @return 0 on completion, or -1 on failure
115 **/
readit(int f,void * buf,size_t len)116 int readit(int f, void *buf, size_t len) {
117 ssize_t res;
118 while (len > 0) {
119 NBD_DEBUG("*");
120 res = read(f, buf, len);
121 if (res > 0) {
122 len -= res;
123 buf += res;
124 } else if (res < 0) {
125 if(errno != EAGAIN) {
126 err_nonfatal("Read failed: %m");
127 return -1;
128 }
129 } else {
130 errno = ECONNRESET;
131 return -1;
132 }
133 }
134 return 0;
135 }
136
137 /**
138 * Write data from a buffer into a filedescriptor
139 *
140 * @param f a file descriptor
141 * @param buf a buffer containing data
142 * @param len the number of bytes to be written
143 * @return 0 on success, or -1 if the socket was closed
144 **/
writeit(int f,void * buf,size_t len)145 int writeit(int f, void *buf, size_t len) {
146 ssize_t res;
147 while (len > 0) {
148 NBD_DEBUG("+");
149 if ((res = write(f, buf, len)) <= 0) {
150 switch(errno) {
151 case EAGAIN:
152 break;
153 default:
154 err_nonfatal("Send failed: %m");
155 return -1;
156 }
157 }
158 len -= res;
159 buf += res;
160 }
161 return 0;
162 }
163