source: roaraudio/libroar/nnode.c @ 5353:de96f27919bf

Last change on this file since 5353:de96f27919bf was 5028:bda7085a07b8, checked in by phi, 13 years ago

fixed some ckport warnings about poissible buffer overflows which are not possible because buffer length is ensured before the call

File size: 8.9 KB
Line 
1//nnode.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2011
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#define _CHECK(x) if ( (x) == NULL ) return -1
39
40int roar_nnode_new        (struct roar_nnode * nnode, int socktype) {
41 _CHECK(nnode);
42
43 memset(nnode, 0, sizeof(struct roar_nnode));
44
45 nnode->socktype = socktype;
46
47 return 0;
48}
49
50int roar_nnode_new_from_af(struct roar_nnode * nnode, int af) {
51 int socktype;
52
53 _CHECK(nnode);
54
55 switch (af) {
56#ifdef ROAR_HAVE_IPV4
57  case AF_INET:   socktype = ROAR_SOCKET_TYPE_INET;   break;
58#endif
59#ifdef ROAR_HAVE_IPV6
60  case AF_INET6:  socktype = ROAR_SOCKET_TYPE_INET6;  break;
61#endif
62#ifdef ROAR_HAVE_UNIX
63  case AF_UNIX:   socktype = ROAR_SOCKET_TYPE_UNIX;   break;
64#endif
65#ifdef ROAR_HAVE_LIBDNET
66  case AF_DECnet: socktype = ROAR_SOCKET_TYPE_DECNET; break;
67#endif
68#ifdef ROAR_HAVE_IPX
69  case AF_IPX:    socktype = ROAR_SOCKET_TYPE_IPX;    break;
70#endif
71  default:
72    return -1;
73   break;
74 }
75
76 if ( roar_nnode_new(nnode, socktype) == -1 )
77  return -1;
78
79 return 0;
80}
81
82int roar_nnode_new_from_sockaddr(struct roar_nnode * nnode, struct sockaddr * addr, socklen_t len) {
83 _CHECK(nnode);
84 _CHECK(addr);
85
86 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = ?", nnode, addr, (unsigned long)len);
87
88 if ( len < sizeof(addr->sa_family) )
89  return -1;
90
91 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = ?", nnode, addr, (unsigned long)len);
92
93 if ( roar_nnode_new_from_af(nnode, addr->sa_family) == -1 )
94  return -1;
95
96 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = ?", nnode, addr, (unsigned long)len);
97
98 switch (addr->sa_family) {
99#ifdef ROAR_HAVE_IPV4
100  case AF_INET:
101    if ( len < sizeof(struct sockaddr_in) )
102     return -1;
103
104    memcpy(nnode->addr.inet4, &(((struct sockaddr_in*)addr)->sin_addr), sizeof(nnode->addr.inet4));
105   break;
106#endif
107#ifdef ROAR_HAVE_IPV6
108  case AF_INET6:
109    if ( len < sizeof(struct sockaddr_in6) )
110     return -1;
111
112    memcpy(nnode->addr.inet6, ((struct sockaddr_in6*)addr)->sin6_addr.s6_addr, sizeof(nnode->addr.inet6));
113   break;
114#endif
115#ifdef ROAR_HAVE_UNIX
116  case AF_UNIX:
117    // nothing to do/save here.
118   break;
119#endif
120#ifdef ROAR_HAVE_LIBDNET
121  case AF_DECnet:
122    if ( len < sizeof(struct sockaddr_dn) )
123     return -1;
124
125    nnode->addr.decnet.node  =  ((struct sockaddr_dn*)addr)->sdn_add.a_addr[0];
126    nnode->addr.decnet.node |= (((struct sockaddr_dn*)addr)->sdn_add.a_addr[1] & 0x03) << 8;
127    nnode->addr.decnet.area  =  ((struct sockaddr_dn*)addr)->sdn_add.a_addr[1] >> 2;
128   break;
129#endif
130#ifdef ROAR_HAVE_IPX
131  case AF_IPX:
132    return -1;
133   break;
134#endif
135  default:
136    return -1;
137   break;
138 }
139
140 ROAR_DBG("roar_nnode_new_from_sockaddr(nnode=%p, addr=%p, len=%lu) = 0", nnode, addr, (unsigned long)len);
141 return 0;
142}
143
144int roar_nnode_new_from_fh(struct roar_nnode * nnode, int fh, int remote) {
145 // TODO: fix this in a nice way
146#ifndef ROAR_TARGET_MICROCONTROLLER
147 struct sockaddr_storage sa;
148 socklen_t               len = sizeof(sa);
149 int                     ret;
150
151 _CHECK(nnode);
152
153 if ( fh == -1 )
154  return -1;
155
156 if ( remote ) {
157  ret = getpeername(fh, (struct sockaddr*)&sa, &len);
158 } else {
159  ret = getsockname(fh, (struct sockaddr*)&sa, &len);
160 }
161
162 if ( ret == -1 )
163  return -1;
164
165 return roar_nnode_new_from_sockaddr(nnode, (struct sockaddr*)&sa, len);
166#else
167 return -1;
168#endif
169}
170
171int roar_nnode_free       (struct roar_nnode * nnode) {
172 _CHECK(nnode);
173
174 return 0;
175}
176
177int roar_nnode_get_socktype (struct roar_nnode * nnode) {
178 _CHECK(nnode);
179
180 return nnode->socktype;
181}
182
183int roar_nnode_to_str     (struct roar_nnode * nnode, char * str, size_t len) {
184 // Format: PROTO: nodename[nodeaddr]
185 char proto[7]    = "???";
186 char nodename[4] = "";
187 char nodeaddr[48 /* IPv6 */] = "???";
188
189 _CHECK(nnode);
190
191 if ( len == 0 )
192  return 0;
193
194 _CHECK(str);
195
196 if ( len == 1 ) {
197  *str = 0;
198  return 0;
199 }
200
201 switch (nnode->socktype) {
202  case ROAR_SOCKET_TYPE_UNIX:
203    roar_mm_strscpy(proto,     "UNIX");
204    roar_mm_strscpy(nodeaddr, "LOCAL");
205   break;
206  case ROAR_SOCKET_TYPE_INET:
207    roar_mm_strscpy(proto,     "IPv4");
208    snprintf(nodeaddr, sizeof(nodeaddr), "%i.%i.%i.%i",
209                 nnode->addr.inet4[0], nnode->addr.inet4[1],
210                 nnode->addr.inet4[2], nnode->addr.inet4[3]
211           );
212   break;
213  case ROAR_SOCKET_TYPE_DECNET:
214    roar_mm_strscpy(proto,     "DECnet");
215    snprintf(nodeaddr, sizeof(nodeaddr), "%i.%i", nnode->addr.decnet.area, nnode->addr.decnet.node);
216   break;
217  case ROAR_SOCKET_TYPE_INET6:
218    roar_mm_strscpy(proto,     "IPv6");
219   break;
220  case ROAR_SOCKET_TYPE_IPX:
221    roar_mm_strscpy(proto,     "IPX");
222   break;
223  default:
224    snprintf(proto, sizeof(proto), "P#%i", nnode->socktype);
225   break;
226 }
227
228 if ( *nodename ) {
229  snprintf(str, len, "%s: %s[%s]", proto, nodename, nodeaddr);
230 } else {
231  snprintf(str, len, "%s: %s", proto, nodeaddr);
232 }
233
234 str[len-1] = 0;
235
236 return 0;
237}
238
239int roar_nnode_from_blob  (struct roar_nnode * nnode, void * blob, size_t * len) {
240 uint16_t socktype;
241
242 _CHECK(nnode);
243 _CHECK(blob);
244 _CHECK(len);
245
246 if ( *len < 2 )
247  return -1;
248
249 memcpy(&socktype, blob, 2);
250
251 socktype = ROAR_NET2HOST16(socktype);
252
253 if ( roar_nnode_new(nnode, socktype) == -1 )
254  return -1;
255
256 switch (socktype) {
257  case ROAR_SOCKET_TYPE_UNIX:
258    *len = 2;
259   break;
260  case ROAR_SOCKET_TYPE_INET:
261    if ( *len < 6 )
262     return -1;
263
264    memcpy(nnode->addr.inet4, blob+2, 4);
265
266    *len = 6;
267   break;
268  case ROAR_SOCKET_TYPE_DECNET:
269    if ( *len < 4 )
270     return -1;
271
272    nnode->addr.decnet.node   =  ((unsigned char*)blob)[2];
273    nnode->addr.decnet.node   = (((unsigned char*)blob)[3] & 0x03) << 8;
274    nnode->addr.decnet.area   =  ((unsigned char*)blob)[3] >> 2;
275
276    *len = 4;
277   break;
278  case ROAR_SOCKET_TYPE_INET6:
279    if ( *len < 18 )
280     return -1;
281
282    memcpy(nnode->addr.inet4, blob+2, 16);
283
284    *len = 18;
285   break;
286  case ROAR_SOCKET_TYPE_IPX:
287  default:
288    return -1;
289   break;
290 }
291
292 return 0;
293}
294
295int roar_nnode_to_blob    (struct roar_nnode * nnode, void * blob, size_t * len) {
296 uint16_t socktype_net;
297
298 _CHECK(nnode);
299 _CHECK(blob);
300 _CHECK(len);
301
302 if ( *len < 2 )
303  return -1;
304
305 socktype_net = ROAR_HOST2NET16(nnode->socktype);
306
307 memcpy(blob, &socktype_net, 2);
308
309 switch (nnode->socktype) {
310  case ROAR_SOCKET_TYPE_UNIX:
311    // all UNIX sockets allways match.
312    *len = 2;
313   break;
314  case ROAR_SOCKET_TYPE_INET:
315    if ( *len < 6 )
316     return -1;
317
318    memcpy(blob+2, nnode->addr.inet4, 4);
319    *len = 6;
320
321   break;
322  case ROAR_SOCKET_TYPE_DECNET:
323    if ( *len < 4 )
324     return -1;
325
326    ((unsigned char*)blob)[2] =   nnode->addr.decnet.node & 0x00FF;
327    ((unsigned char*)blob)[3] = ((nnode->addr.decnet.node & 0x0300) >> 8) | (nnode->addr.decnet.area << 2);
328    *len = 4;
329
330    return -1;
331   break;
332  case ROAR_SOCKET_TYPE_INET6:
333    if ( *len < 18 )
334     return -1;
335
336    memcpy(blob+2, nnode->addr.inet4, 16);
337    *len = 18;
338
339   break;
340  case ROAR_SOCKET_TYPE_IPX:
341  default:
342    return -1;
343   break;
344 }
345
346 return 0;
347}
348
349int roar_nnode_cmp        (struct roar_nnode * n0, struct roar_nnode * n1) {
350 _CHECK(n0);
351 _CHECK(n1);
352
353 if ( n0->socktype != n1->socktype )
354  return 1;
355
356 switch (n0->socktype) {
357  case ROAR_SOCKET_TYPE_UNIX:
358    // all UNIX sockets allways match.
359   break;
360  case ROAR_SOCKET_TYPE_INET:
361    if ( memcmp(n0->addr.inet4, n1->addr.inet4, sizeof(n0->addr.inet4)) != 0 )
362     return 1;
363   break;
364  case ROAR_SOCKET_TYPE_DECNET:
365    if ( n0->addr.decnet.area != n1->addr.decnet.area ||
366         n0->addr.decnet.node != n1->addr.decnet.node   )
367     return 1;
368   break;
369  case ROAR_SOCKET_TYPE_INET6:
370    if ( memcmp(n0->addr.inet6, n1->addr.inet6, sizeof(n0->addr.inet6)) != 0 )
371     return 1;
372   break;
373  case ROAR_SOCKET_TYPE_IPX:
374  default:
375    return -1;
376   break;
377 }
378
379 return 0;
380}
381
382//ll
Note: See TracBrowser for help on using the repository browser.