1*231f6b58Splunky /* $NetBSD: sdp_service.c,v 1.4 2010/11/20 12:12:21 plunky Exp $ */
2dfbf818aSplunky
3dfbf818aSplunky /*-
4dfbf818aSplunky * Copyright (c) 2009 The NetBSD Foundation, Inc.
5dfbf818aSplunky * All rights reserved.
6dfbf818aSplunky *
7dfbf818aSplunky * This code is derived from software contributed to The NetBSD Foundation
8dfbf818aSplunky * by Iain Hibbert.
9dfbf818aSplunky *
10dfbf818aSplunky * Redistribution and use in source and binary forms, with or without
11dfbf818aSplunky * modification, are permitted provided that the following conditions
12dfbf818aSplunky * are met:
13dfbf818aSplunky * 1. Redistributions of source code must retain the above copyright
14dfbf818aSplunky * notice, this list of conditions and the following disclaimer.
15dfbf818aSplunky * 2. Redistributions in binary form must reproduce the above copyright
16dfbf818aSplunky * notice, this list of conditions and the following disclaimer in the
17dfbf818aSplunky * documentation and/or other materials provided with the distribution.
18dfbf818aSplunky *
19dfbf818aSplunky * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20dfbf818aSplunky * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21dfbf818aSplunky * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22dfbf818aSplunky * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23dfbf818aSplunky * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24dfbf818aSplunky * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25dfbf818aSplunky * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26dfbf818aSplunky * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27dfbf818aSplunky * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28dfbf818aSplunky * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29dfbf818aSplunky * POSSIBILITY OF SUCH DAMAGE.
30dfbf818aSplunky */
31dfbf818aSplunky
32dfbf818aSplunky #include <sys/cdefs.h>
33*231f6b58Splunky __RCSID("$NetBSD: sdp_service.c,v 1.4 2010/11/20 12:12:21 plunky Exp $");
34*231f6b58Splunky
35*231f6b58Splunky #include <sys/atomic.h>
36dfbf818aSplunky
37dfbf818aSplunky #include <errno.h>
38dfbf818aSplunky #include <limits.h>
39dfbf818aSplunky #include <sdp.h>
40dfbf818aSplunky #include <stdlib.h>
41dfbf818aSplunky #include <string.h>
42dfbf818aSplunky #include <unistd.h>
43dfbf818aSplunky
44dfbf818aSplunky #include "sdp-int.h"
45dfbf818aSplunky
46dfbf818aSplunky /*
47dfbf818aSplunky * If AttributeIDList is given as NULL, request all attributes.
48*231f6b58Splunky * (this is actually const data but we can't declare it const)
49dfbf818aSplunky */
50dfbf818aSplunky static uint8_t ail_default[] = { 0x0a, 0x00, 0x00, 0xff, 0xff };
51dfbf818aSplunky
52dfbf818aSplunky /*
53dfbf818aSplunky * This provides the maximum size that the response buffer will be
54dfbf818aSplunky * allowed to grow to.
55dfbf818aSplunky *
56dfbf818aSplunky * Default is UINT16_MAX but it can be overridden at runtime.
57dfbf818aSplunky */
58dfbf818aSplunky static size_t
sdp_response_max(void)59dfbf818aSplunky sdp_response_max(void)
60dfbf818aSplunky {
61dfbf818aSplunky static size_t max = UINT16_MAX;
62*231f6b58Splunky static unsigned int check = 1;
63dfbf818aSplunky char *env, *ep;
64dfbf818aSplunky unsigned long v;
65dfbf818aSplunky
66*231f6b58Splunky while (atomic_swap_uint(&check, 0)) { /* only check env once */
67dfbf818aSplunky env = getenv("SDP_RESPONSE_MAX");
68dfbf818aSplunky if (env == NULL)
69dfbf818aSplunky break;
70dfbf818aSplunky
71dfbf818aSplunky errno = 0;
72dfbf818aSplunky v = strtoul(env, &ep, 0);
73dfbf818aSplunky if (env[0] == '\0' || *ep != '\0')
74dfbf818aSplunky break;
75dfbf818aSplunky
76dfbf818aSplunky if (errno == ERANGE && v == ULONG_MAX)
77dfbf818aSplunky break;
78dfbf818aSplunky
79dfbf818aSplunky /* lower limit is arbitrary */
80dfbf818aSplunky if (v < UINT8_MAX || v > UINT32_MAX)
81dfbf818aSplunky break;
82dfbf818aSplunky
83dfbf818aSplunky max = v;
84dfbf818aSplunky }
85dfbf818aSplunky
86dfbf818aSplunky return max;
87dfbf818aSplunky }
88dfbf818aSplunky
89dfbf818aSplunky bool
sdp_service_search(struct sdp_session * ss,const sdp_data_t * ssp,uint32_t * id,int * num)90dfbf818aSplunky sdp_service_search(struct sdp_session *ss, const sdp_data_t *ssp,
91dfbf818aSplunky uint32_t *id, int *num)
92dfbf818aSplunky {
93dfbf818aSplunky struct iovec req[5];
94dfbf818aSplunky sdp_data_t hdr;
95dfbf818aSplunky uint8_t sdata[5], max[2];
96dfbf818aSplunky uint8_t *ptr, *end;
97dfbf818aSplunky ssize_t len;
98dfbf818aSplunky uint16_t total, count, got;
99dfbf818aSplunky
100dfbf818aSplunky /*
101dfbf818aSplunky * setup ServiceSearchPattern
102dfbf818aSplunky */
103dfbf818aSplunky len = ssp->end - ssp->next;
104dfbf818aSplunky if (len < 0 || len > UINT16_MAX) {
105dfbf818aSplunky errno = EINVAL;
106dfbf818aSplunky return false;
107dfbf818aSplunky }
108dfbf818aSplunky
109dfbf818aSplunky hdr.next = sdata;
110dfbf818aSplunky hdr.end = sdata + sizeof(sdata) + len;
111dfbf818aSplunky sdp_put_seq(&hdr, len);
112dfbf818aSplunky req[1].iov_base = sdata;
113dfbf818aSplunky req[1].iov_len = hdr.next - sdata;
114dfbf818aSplunky
115dfbf818aSplunky req[2].iov_base = ssp->next;
116dfbf818aSplunky req[2].iov_len = len;
117dfbf818aSplunky
118dfbf818aSplunky /*
119dfbf818aSplunky * setup MaximumServiceRecordCount
120dfbf818aSplunky */
121dfbf818aSplunky if (*num < 0 || *num > UINT16_MAX) {
122dfbf818aSplunky errno = EINVAL;
123dfbf818aSplunky return false;
124dfbf818aSplunky }
125dfbf818aSplunky be16enc(max, *num);
126dfbf818aSplunky req[3].iov_base = max;
127dfbf818aSplunky req[3].iov_len = sizeof(uint16_t);
128dfbf818aSplunky
129dfbf818aSplunky /*
130dfbf818aSplunky * clear ContinuationState
131dfbf818aSplunky */
132dfbf818aSplunky ss->cs[0] = 0;
133dfbf818aSplunky
134dfbf818aSplunky /*
135dfbf818aSplunky * ServiceSearch Transaction
136dfbf818aSplunky */
137dfbf818aSplunky got = 0;
138dfbf818aSplunky for (;;) {
139dfbf818aSplunky /*
140dfbf818aSplunky * setup ContinuationState
141dfbf818aSplunky */
142dfbf818aSplunky req[4].iov_base = ss->cs;
143dfbf818aSplunky req[4].iov_len = ss->cs[0] + 1;
144dfbf818aSplunky
145dfbf818aSplunky if (!_sdp_send_pdu(ss, SDP_PDU_SERVICE_SEARCH_REQUEST,
146dfbf818aSplunky req, __arraycount(req)))
147dfbf818aSplunky return false;
148dfbf818aSplunky
149dfbf818aSplunky len = _sdp_recv_pdu(ss, SDP_PDU_SERVICE_SEARCH_RESPONSE);
150dfbf818aSplunky if (len == -1)
151dfbf818aSplunky return false;
152dfbf818aSplunky
153dfbf818aSplunky ptr = ss->ibuf;
154dfbf818aSplunky end = ss->ibuf + len;
155dfbf818aSplunky
156dfbf818aSplunky /*
157dfbf818aSplunky * extract TotalServiceRecordCount
158dfbf818aSplunky */
159dfbf818aSplunky if (ptr + sizeof(uint16_t) > end)
160dfbf818aSplunky break;
161dfbf818aSplunky
162dfbf818aSplunky total = be16dec(ptr);
163dfbf818aSplunky ptr += sizeof(uint16_t);
164dfbf818aSplunky if (total > *num)
165dfbf818aSplunky break;
166dfbf818aSplunky
167dfbf818aSplunky /*
168dfbf818aSplunky * extract CurrentServiceRecordCount
169dfbf818aSplunky */
170dfbf818aSplunky if (ptr + sizeof(uint16_t) > end)
171dfbf818aSplunky break;
172dfbf818aSplunky
173dfbf818aSplunky count = be16dec(ptr);
174dfbf818aSplunky ptr += sizeof(uint16_t);
175dfbf818aSplunky if (got + count > total)
176dfbf818aSplunky break;
177dfbf818aSplunky
178dfbf818aSplunky /*
179dfbf818aSplunky * extract ServiceRecordHandleList
180dfbf818aSplunky */
181dfbf818aSplunky if (ptr + count * sizeof(uint32_t) > end)
182dfbf818aSplunky break;
183dfbf818aSplunky
184dfbf818aSplunky while (count-- > 0) {
185dfbf818aSplunky id[got++] = be32dec(ptr);
186dfbf818aSplunky ptr += sizeof(uint32_t);
187dfbf818aSplunky }
188dfbf818aSplunky
189dfbf818aSplunky /*
190dfbf818aSplunky * extract ContinuationState
191dfbf818aSplunky */
192dfbf818aSplunky if (ptr + 1 > end
193dfbf818aSplunky || ptr[0] > 16
194dfbf818aSplunky || ptr + ptr[0] + 1 != end)
195dfbf818aSplunky break;
196dfbf818aSplunky
1979dc6fb5cSplunky memcpy(ss->cs, ptr, (size_t)(ptr[0] + 1));
198dfbf818aSplunky
199dfbf818aSplunky /*
200dfbf818aSplunky * Complete?
201dfbf818aSplunky */
202dfbf818aSplunky if (ss->cs[0] == 0) {
203dfbf818aSplunky *num = got;
204dfbf818aSplunky return true;
205dfbf818aSplunky }
206dfbf818aSplunky }
207dfbf818aSplunky
208dfbf818aSplunky errno = EIO;
209dfbf818aSplunky return false;
210dfbf818aSplunky }
211dfbf818aSplunky
212dfbf818aSplunky bool
sdp_service_attribute(struct sdp_session * ss,uint32_t id,const sdp_data_t * ail,sdp_data_t * rsp)213dfbf818aSplunky sdp_service_attribute(struct sdp_session *ss, uint32_t id,
214dfbf818aSplunky const sdp_data_t *ail, sdp_data_t *rsp)
215dfbf818aSplunky {
216dfbf818aSplunky struct iovec req[6];
217dfbf818aSplunky sdp_data_t hdr;
218dfbf818aSplunky uint8_t adata[5], handle[4], max[2];
219dfbf818aSplunky uint8_t *ptr, *end, *rbuf;
220dfbf818aSplunky ssize_t len;
221dfbf818aSplunky size_t rlen, count;
222dfbf818aSplunky
223dfbf818aSplunky /*
224dfbf818aSplunky * setup ServiceRecordHandle
225dfbf818aSplunky */
226dfbf818aSplunky be32enc(handle, id);
227dfbf818aSplunky req[1].iov_base = handle;
228dfbf818aSplunky req[1].iov_len = sizeof(uint32_t);
229dfbf818aSplunky
230dfbf818aSplunky /*
231dfbf818aSplunky * setup MaximumAttributeByteCount
232dfbf818aSplunky */
233dfbf818aSplunky be16enc(max, ss->imtu - sizeof(uint16_t) - sizeof(ss->cs));
234dfbf818aSplunky req[2].iov_base = max;
235dfbf818aSplunky req[2].iov_len = sizeof(uint16_t);
236dfbf818aSplunky
237dfbf818aSplunky /*
238dfbf818aSplunky * setup AttributeIDList
239dfbf818aSplunky */
2408ebedbbbSplunky len = (ail == NULL ? (ssize_t)sizeof(ail_default) : (ail->end - ail->next));
241dfbf818aSplunky if (len < 0 || len > UINT16_MAX) {
242dfbf818aSplunky errno = EINVAL;
243dfbf818aSplunky return false;
244dfbf818aSplunky }
245dfbf818aSplunky
246dfbf818aSplunky hdr.next = adata;
247dfbf818aSplunky hdr.end = adata + sizeof(adata) + len;
248dfbf818aSplunky sdp_put_seq(&hdr, len);
249dfbf818aSplunky req[3].iov_base = adata;
250dfbf818aSplunky req[3].iov_len = hdr.next - adata;
251dfbf818aSplunky
252dfbf818aSplunky req[4].iov_base = (ail == NULL ? ail_default : ail->next);
253dfbf818aSplunky req[4].iov_len = len;
254dfbf818aSplunky
255dfbf818aSplunky /*
256dfbf818aSplunky * clear ContinuationState
257dfbf818aSplunky */
258dfbf818aSplunky ss->cs[0] = 0;
259dfbf818aSplunky
260dfbf818aSplunky /*
261dfbf818aSplunky * ServiceAttribute Transaction
262dfbf818aSplunky */
263dfbf818aSplunky rlen = 0;
264dfbf818aSplunky for (;;) {
265dfbf818aSplunky /*
266dfbf818aSplunky * setup ContinuationState
267dfbf818aSplunky */
268dfbf818aSplunky req[5].iov_base = ss->cs;
269dfbf818aSplunky req[5].iov_len = ss->cs[0] + 1;
270dfbf818aSplunky
271dfbf818aSplunky if (!_sdp_send_pdu(ss, SDP_PDU_SERVICE_ATTRIBUTE_REQUEST,
272dfbf818aSplunky req, __arraycount(req)))
273dfbf818aSplunky return false;
274dfbf818aSplunky
275dfbf818aSplunky len = _sdp_recv_pdu(ss, SDP_PDU_SERVICE_ATTRIBUTE_RESPONSE);
276dfbf818aSplunky if (len == -1)
277dfbf818aSplunky return false;
278dfbf818aSplunky
279dfbf818aSplunky ptr = ss->ibuf;
280dfbf818aSplunky end = ss->ibuf + len;
281dfbf818aSplunky
282dfbf818aSplunky /*
283dfbf818aSplunky * extract AttributeListByteCount
284dfbf818aSplunky */
285dfbf818aSplunky if (ptr + sizeof(uint16_t) > end)
286dfbf818aSplunky break;
287dfbf818aSplunky
288dfbf818aSplunky count = be16dec(ptr);
289dfbf818aSplunky ptr += sizeof(uint16_t);
290dfbf818aSplunky if (count == 0 || ptr + count > end)
291dfbf818aSplunky break;
292dfbf818aSplunky
293dfbf818aSplunky /*
294dfbf818aSplunky * extract AttributeList
295dfbf818aSplunky */
296dfbf818aSplunky if (rlen + count > sdp_response_max())
297dfbf818aSplunky break;
298dfbf818aSplunky
299dfbf818aSplunky rbuf = realloc(ss->rbuf, rlen + count);
300dfbf818aSplunky if (rbuf == NULL)
301dfbf818aSplunky return false;
302dfbf818aSplunky
303dfbf818aSplunky ss->rbuf = rbuf;
304dfbf818aSplunky memcpy(rbuf + rlen, ptr, count);
305dfbf818aSplunky rlen += count;
306dfbf818aSplunky ptr += count;
307dfbf818aSplunky
308dfbf818aSplunky /*
309dfbf818aSplunky * extract ContinuationState
310dfbf818aSplunky */
311dfbf818aSplunky if (ptr + 1 > end
312dfbf818aSplunky || ptr[0] > 16
313dfbf818aSplunky || ptr + ptr[0] + 1 != end)
314dfbf818aSplunky break;
315dfbf818aSplunky
3169dc6fb5cSplunky memcpy(ss->cs, ptr, (size_t)(ptr[0] + 1));
317dfbf818aSplunky
318dfbf818aSplunky /*
319dfbf818aSplunky * Complete?
320dfbf818aSplunky */
321dfbf818aSplunky if (ss->cs[0] == 0) {
322dfbf818aSplunky rsp->next = rbuf;
323dfbf818aSplunky rsp->end = rbuf + rlen;
3248ebedbbbSplunky if (sdp_data_size(rsp) != (ssize_t)rlen
325dfbf818aSplunky || !sdp_data_valid(rsp)
326dfbf818aSplunky || !sdp_get_seq(rsp, rsp))
327dfbf818aSplunky break;
328dfbf818aSplunky
329dfbf818aSplunky return true;
330dfbf818aSplunky }
331dfbf818aSplunky }
332dfbf818aSplunky
333dfbf818aSplunky errno = EIO;
334dfbf818aSplunky return false;
335dfbf818aSplunky }
336dfbf818aSplunky
337dfbf818aSplunky bool
sdp_service_search_attribute(struct sdp_session * ss,const sdp_data_t * ssp,const sdp_data_t * ail,sdp_data_t * rsp)338dfbf818aSplunky sdp_service_search_attribute(struct sdp_session *ss, const sdp_data_t *ssp,
339dfbf818aSplunky const sdp_data_t *ail, sdp_data_t *rsp)
340dfbf818aSplunky {
341dfbf818aSplunky struct iovec req[7];
342dfbf818aSplunky sdp_data_t hdr;
343dfbf818aSplunky uint8_t sdata[5], adata[5], max[2];
344dfbf818aSplunky uint8_t *ptr, *end, *rbuf;
345dfbf818aSplunky ssize_t len;
346dfbf818aSplunky size_t rlen, count;
347dfbf818aSplunky
348dfbf818aSplunky /*
349dfbf818aSplunky * setup ServiceSearchPattern
350dfbf818aSplunky */
351dfbf818aSplunky len = ssp->end - ssp->next;
352dfbf818aSplunky if (len < 0 || len > UINT16_MAX) {
353dfbf818aSplunky errno = EINVAL;
354dfbf818aSplunky return false;
355dfbf818aSplunky }
356dfbf818aSplunky
357dfbf818aSplunky hdr.next = sdata;
358dfbf818aSplunky hdr.end = sdata + sizeof(sdata) + len;
359dfbf818aSplunky sdp_put_seq(&hdr, len);
360dfbf818aSplunky req[1].iov_base = sdata;
361dfbf818aSplunky req[1].iov_len = hdr.next - sdata;
362dfbf818aSplunky
363dfbf818aSplunky req[2].iov_base = ssp->next;
364dfbf818aSplunky req[2].iov_len = len;
365dfbf818aSplunky
366dfbf818aSplunky /*
367dfbf818aSplunky * setup MaximumAttributeByteCount
368dfbf818aSplunky */
369dfbf818aSplunky be16enc(max, ss->imtu - sizeof(uint16_t) - sizeof(ss->cs));
370dfbf818aSplunky req[3].iov_base = max;
371dfbf818aSplunky req[3].iov_len = sizeof(uint16_t);
372dfbf818aSplunky
373dfbf818aSplunky /*
374dfbf818aSplunky * setup AttributeIDList
375dfbf818aSplunky */
3768ebedbbbSplunky len = (ail == NULL ? (ssize_t)sizeof(ail_default) : (ail->end - ail->next));
377dfbf818aSplunky if (len < 0 || len > UINT16_MAX) {
378dfbf818aSplunky errno = EINVAL;
379dfbf818aSplunky return false;
380dfbf818aSplunky }
381dfbf818aSplunky
382dfbf818aSplunky hdr.next = adata;
383dfbf818aSplunky hdr.end = adata + sizeof(adata) + len;
384dfbf818aSplunky sdp_put_seq(&hdr, len);
385dfbf818aSplunky req[4].iov_base = adata;
386dfbf818aSplunky req[4].iov_len = hdr.next - adata;
387dfbf818aSplunky
388dfbf818aSplunky req[5].iov_base = (ail == NULL ? ail_default : ail->next);
389dfbf818aSplunky req[5].iov_len = len;
390dfbf818aSplunky
391dfbf818aSplunky /*
392dfbf818aSplunky * clear ContinuationState
393dfbf818aSplunky */
394dfbf818aSplunky ss->cs[0] = 0;
395dfbf818aSplunky
396dfbf818aSplunky /*
397dfbf818aSplunky * ServiceSearchAttribute Transaction
398dfbf818aSplunky */
399dfbf818aSplunky rlen = 0;
400dfbf818aSplunky for (;;) {
401dfbf818aSplunky /*
402dfbf818aSplunky * setup ContinuationState
403dfbf818aSplunky */
404dfbf818aSplunky req[6].iov_base = ss->cs;
405dfbf818aSplunky req[6].iov_len = ss->cs[0] + 1;
406dfbf818aSplunky
407dfbf818aSplunky if (!_sdp_send_pdu(ss, SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST,
408dfbf818aSplunky req, __arraycount(req)))
409dfbf818aSplunky return false;
410dfbf818aSplunky
411dfbf818aSplunky len = _sdp_recv_pdu(ss, SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_RESPONSE);
412dfbf818aSplunky if (len == -1)
413dfbf818aSplunky return false;
414dfbf818aSplunky
415dfbf818aSplunky ptr = ss->ibuf;
416dfbf818aSplunky end = ss->ibuf + len;
417dfbf818aSplunky
418dfbf818aSplunky /*
419dfbf818aSplunky * extract AttributeListsByteCount
420dfbf818aSplunky */
421dfbf818aSplunky if (ptr + sizeof(uint16_t) > end)
422dfbf818aSplunky break;
423dfbf818aSplunky
424dfbf818aSplunky count = be16dec(ptr);
425dfbf818aSplunky ptr += sizeof(uint16_t);
426dfbf818aSplunky if (count == 0 || ptr + count > end)
427dfbf818aSplunky break;
428dfbf818aSplunky
429dfbf818aSplunky /*
430dfbf818aSplunky * extract AttributeLists
431dfbf818aSplunky */
432dfbf818aSplunky if (rlen + count > sdp_response_max())
433dfbf818aSplunky break;
434dfbf818aSplunky
435dfbf818aSplunky rbuf = realloc(ss->rbuf, rlen + count);
436dfbf818aSplunky if (rbuf == NULL)
437dfbf818aSplunky return false;
438dfbf818aSplunky
439dfbf818aSplunky ss->rbuf = rbuf;
440dfbf818aSplunky memcpy(rbuf + rlen, ptr, count);
441dfbf818aSplunky rlen += count;
442dfbf818aSplunky ptr += count;
443dfbf818aSplunky
444dfbf818aSplunky /*
445dfbf818aSplunky * extract ContinuationState
446dfbf818aSplunky */
447dfbf818aSplunky if (ptr + 1 > end
448dfbf818aSplunky || ptr[0] > 16
449dfbf818aSplunky || ptr + ptr[0] + 1 != end)
450dfbf818aSplunky break;
451dfbf818aSplunky
4529dc6fb5cSplunky memcpy(ss->cs, ptr, (size_t)(ptr[0] + 1));
453dfbf818aSplunky
454dfbf818aSplunky /*
455dfbf818aSplunky * Complete?
456dfbf818aSplunky */
457dfbf818aSplunky if (ss->cs[0] == 0) {
458dfbf818aSplunky rsp->next = rbuf;
459dfbf818aSplunky rsp->end = rbuf + rlen;
4608ebedbbbSplunky if (sdp_data_size(rsp) != (ssize_t)rlen
461dfbf818aSplunky || !sdp_data_valid(rsp)
462dfbf818aSplunky || !sdp_get_seq(rsp, rsp))
463dfbf818aSplunky break;
464dfbf818aSplunky
465dfbf818aSplunky return true;
466dfbf818aSplunky }
467dfbf818aSplunky }
468dfbf818aSplunky
469dfbf818aSplunky errno = EIO;
470dfbf818aSplunky return false;
471dfbf818aSplunky }
472