Blame


1 f024663d 2021-09-05 stsp /*
2 f024663d 2021-09-05 stsp * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
3 f024663d 2021-09-05 stsp * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
4 f024663d 2021-09-05 stsp *
5 f024663d 2021-09-05 stsp * Permission to use, copy, modify, and distribute this software for any
6 f024663d 2021-09-05 stsp * purpose with or without fee is hereby granted, provided that the above
7 f024663d 2021-09-05 stsp * copyright notice and this permission notice appear in all copies.
8 f024663d 2021-09-05 stsp *
9 f024663d 2021-09-05 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 f024663d 2021-09-05 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 f024663d 2021-09-05 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 f024663d 2021-09-05 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 f024663d 2021-09-05 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 f024663d 2021-09-05 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 f024663d 2021-09-05 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 f024663d 2021-09-05 stsp */
17 f024663d 2021-09-05 stsp
18 f024663d 2021-09-05 stsp #include <ctype.h>
19 f024663d 2021-09-05 stsp #include <errno.h>
20 f024663d 2021-09-05 stsp #include <limits.h>
21 f024663d 2021-09-05 stsp #include <stdio.h>
22 f024663d 2021-09-05 stsp #include <stdlib.h>
23 f024663d 2021-09-05 stsp #include <unistd.h>
24 f024663d 2021-09-05 stsp
25 f024663d 2021-09-05 stsp #include "got_error.h"
26 f024663d 2021-09-05 stsp
27 f024663d 2021-09-05 stsp const struct got_error *
28 f024663d 2021-09-05 stsp got_pkt_readn(ssize_t *off, int fd, void *buf, size_t n)
29 f024663d 2021-09-05 stsp {
30 f024663d 2021-09-05 stsp ssize_t r;
31 f024663d 2021-09-05 stsp
32 f024663d 2021-09-05 stsp *off = 0;
33 f024663d 2021-09-05 stsp while (*off != n) {
34 f024663d 2021-09-05 stsp r = read(fd, buf + *off, n - *off);
35 f024663d 2021-09-05 stsp if (r == -1)
36 f024663d 2021-09-05 stsp return got_error_from_errno("read");
37 f024663d 2021-09-05 stsp if (r == 0)
38 f024663d 2021-09-05 stsp return NULL;
39 f024663d 2021-09-05 stsp *off += r;
40 f024663d 2021-09-05 stsp }
41 f024663d 2021-09-05 stsp return NULL;
42 f024663d 2021-09-05 stsp }
43 f024663d 2021-09-05 stsp
44 f024663d 2021-09-05 stsp const struct got_error *
45 f024663d 2021-09-05 stsp got_pkt_flushpkt(int fd, int chattygot)
46 f024663d 2021-09-05 stsp {
47 f024663d 2021-09-05 stsp ssize_t w;
48 f024663d 2021-09-05 stsp
49 f024663d 2021-09-05 stsp if (chattygot > 1)
50 f024663d 2021-09-05 stsp fprintf(stderr, "%s: writepkt: 0000\n", getprogname());
51 f024663d 2021-09-05 stsp
52 f024663d 2021-09-05 stsp w = write(fd, "0000", 4);
53 f024663d 2021-09-05 stsp if (w == -1)
54 f024663d 2021-09-05 stsp return got_error_from_errno("write");
55 f024663d 2021-09-05 stsp if (w != 4)
56 f024663d 2021-09-05 stsp return got_error(GOT_ERR_IO);
57 f024663d 2021-09-05 stsp return NULL;
58 f024663d 2021-09-05 stsp }
59 f024663d 2021-09-05 stsp
60 f024663d 2021-09-05 stsp /*
61 f024663d 2021-09-05 stsp * Packet header contains a 4-byte hexstring which specifies the length
62 f024663d 2021-09-05 stsp * of data which follows.
63 f024663d 2021-09-05 stsp */
64 f024663d 2021-09-05 stsp const struct got_error *
65 f024663d 2021-09-05 stsp got_pkt_readhdr(int *datalen, int fd, int chattygot)
66 f024663d 2021-09-05 stsp {
67 f024663d 2021-09-05 stsp static const struct got_error *err = NULL;
68 f024663d 2021-09-05 stsp char lenstr[5];
69 f024663d 2021-09-05 stsp long len;
70 f024663d 2021-09-05 stsp char *e;
71 f024663d 2021-09-05 stsp int n, i;
72 f024663d 2021-09-05 stsp ssize_t r;
73 f024663d 2021-09-05 stsp
74 f024663d 2021-09-05 stsp *datalen = 0;
75 f024663d 2021-09-05 stsp
76 f024663d 2021-09-05 stsp err = got_pkt_readn(&r, fd, lenstr, 4);
77 f024663d 2021-09-05 stsp if (err)
78 f024663d 2021-09-05 stsp return err;
79 f024663d 2021-09-05 stsp if (r == 0) {
80 f024663d 2021-09-05 stsp /* implicit "0000" */
81 f024663d 2021-09-05 stsp if (chattygot > 1)
82 f024663d 2021-09-05 stsp fprintf(stderr, "%s: readpkt: 0000\n", getprogname());
83 f024663d 2021-09-05 stsp return NULL;
84 f024663d 2021-09-05 stsp }
85 f024663d 2021-09-05 stsp if (r != 4)
86 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET,
87 f024663d 2021-09-05 stsp "wrong packet header length");
88 f024663d 2021-09-05 stsp
89 f024663d 2021-09-05 stsp lenstr[4] = '\0';
90 f024663d 2021-09-05 stsp for (i = 0; i < 4; i++) {
91 f024663d 2021-09-05 stsp if (!isprint((unsigned char)lenstr[i]))
92 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET,
93 f024663d 2021-09-05 stsp "unprintable character in packet length field");
94 f024663d 2021-09-05 stsp }
95 f024663d 2021-09-05 stsp for (i = 0; i < 4; i++) {
96 f024663d 2021-09-05 stsp if (!isxdigit((unsigned char)lenstr[i])) {
97 f024663d 2021-09-05 stsp if (chattygot)
98 f024663d 2021-09-05 stsp fprintf(stderr, "%s: bad length: '%s'\n",
99 f024663d 2021-09-05 stsp getprogname(), lenstr);
100 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET,
101 f024663d 2021-09-05 stsp "packet length not specified in hex");
102 f024663d 2021-09-05 stsp }
103 f024663d 2021-09-05 stsp }
104 f024663d 2021-09-05 stsp errno = 0;
105 f024663d 2021-09-05 stsp len = strtol(lenstr, &e, 16);
106 f024663d 2021-09-05 stsp if (lenstr[0] == '\0' || *e != '\0')
107 f024663d 2021-09-05 stsp return got_error(GOT_ERR_BAD_PACKET);
108 f024663d 2021-09-05 stsp if (errno == ERANGE && (len == LONG_MAX || len == LONG_MIN))
109 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET, "bad packet length");
110 f024663d 2021-09-05 stsp if (len > INT_MAX || len < INT_MIN)
111 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET, "bad packet length");
112 f024663d 2021-09-05 stsp n = len;
113 f024663d 2021-09-05 stsp if (n == 0)
114 f024663d 2021-09-05 stsp return NULL;
115 f024663d 2021-09-05 stsp if (n <= 4)
116 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET, "packet too short");
117 f024663d 2021-09-05 stsp n -= 4;
118 f024663d 2021-09-05 stsp
119 f024663d 2021-09-05 stsp *datalen = n;
120 f024663d 2021-09-05 stsp return NULL;
121 f024663d 2021-09-05 stsp }
122 f024663d 2021-09-05 stsp
123 f024663d 2021-09-05 stsp const struct got_error *
124 f024663d 2021-09-05 stsp got_pkt_readpkt(int *outlen, int fd, char *buf, int buflen, int chattygot)
125 f024663d 2021-09-05 stsp {
126 f024663d 2021-09-05 stsp const struct got_error *err = NULL;
127 f024663d 2021-09-05 stsp int datalen, i;
128 f024663d 2021-09-05 stsp ssize_t n;
129 f024663d 2021-09-05 stsp
130 f024663d 2021-09-05 stsp err = got_pkt_readhdr(&datalen, fd, chattygot);
131 f024663d 2021-09-05 stsp if (err)
132 f024663d 2021-09-05 stsp return err;
133 f024663d 2021-09-05 stsp
134 f024663d 2021-09-05 stsp if (datalen > buflen)
135 f024663d 2021-09-05 stsp return got_error(GOT_ERR_NO_SPACE);
136 f024663d 2021-09-05 stsp
137 f024663d 2021-09-05 stsp err = got_pkt_readn(&n, fd, buf, datalen);
138 f024663d 2021-09-05 stsp if (err)
139 f024663d 2021-09-05 stsp return err;
140 f024663d 2021-09-05 stsp if (n != datalen)
141 f024663d 2021-09-05 stsp return got_error_msg(GOT_ERR_BAD_PACKET, "short packet");
142 f024663d 2021-09-05 stsp
143 f024663d 2021-09-05 stsp if (chattygot > 1) {
144 f024663d 2021-09-05 stsp fprintf(stderr, "%s: readpkt: %zd:\t", getprogname(), n);
145 f024663d 2021-09-05 stsp for (i = 0; i < n; i++) {
146 f024663d 2021-09-05 stsp if (isprint(buf[i]))
147 f024663d 2021-09-05 stsp fputc(buf[i], stderr);
148 f024663d 2021-09-05 stsp else
149 f024663d 2021-09-05 stsp fprintf(stderr, "[0x%.2x]", buf[i]);
150 f024663d 2021-09-05 stsp }
151 f024663d 2021-09-05 stsp fputc('\n', stderr);
152 f024663d 2021-09-05 stsp }
153 f024663d 2021-09-05 stsp
154 f024663d 2021-09-05 stsp *outlen = n;
155 f024663d 2021-09-05 stsp return NULL;
156 f024663d 2021-09-05 stsp }
157 f024663d 2021-09-05 stsp
158 f024663d 2021-09-05 stsp const struct got_error *
159 f024663d 2021-09-05 stsp got_pkt_writepkt(int fd, char *buf, int nbuf, int chattygot)
160 f024663d 2021-09-05 stsp {
161 f024663d 2021-09-05 stsp char len[5];
162 f024663d 2021-09-05 stsp int i;
163 f024663d 2021-09-05 stsp ssize_t w;
164 f024663d 2021-09-05 stsp
165 f024663d 2021-09-05 stsp if (snprintf(len, sizeof(len), "%04x", nbuf + 4) >= sizeof(len))
166 f024663d 2021-09-05 stsp return got_error(GOT_ERR_NO_SPACE);
167 f024663d 2021-09-05 stsp w = write(fd, len, 4);
168 f024663d 2021-09-05 stsp if (w == -1)
169 f024663d 2021-09-05 stsp return got_error_from_errno("write");
170 f024663d 2021-09-05 stsp if (w != 4)
171 f024663d 2021-09-05 stsp return got_error(GOT_ERR_IO);
172 f024663d 2021-09-05 stsp w = write(fd, buf, nbuf);
173 f024663d 2021-09-05 stsp if (w == -1)
174 f024663d 2021-09-05 stsp return got_error_from_errno("write");
175 f024663d 2021-09-05 stsp if (w != nbuf)
176 f024663d 2021-09-05 stsp return got_error(GOT_ERR_IO);
177 f024663d 2021-09-05 stsp if (chattygot > 1) {
178 f024663d 2021-09-05 stsp fprintf(stderr, "%s: writepkt: %s:\t", getprogname(), len);
179 f024663d 2021-09-05 stsp for (i = 0; i < nbuf; i++) {
180 f024663d 2021-09-05 stsp if (isprint(buf[i]))
181 f024663d 2021-09-05 stsp fputc(buf[i], stderr);
182 f024663d 2021-09-05 stsp else
183 f024663d 2021-09-05 stsp fprintf(stderr, "[0x%.2x]", buf[i]);
184 f024663d 2021-09-05 stsp }
185 f024663d 2021-09-05 stsp fputc('\n', stderr);
186 f024663d 2021-09-05 stsp }
187 f024663d 2021-09-05 stsp return NULL;
188 f024663d 2021-09-05 stsp }