fix segfault
[enigma2-plugins.git] / networkbrowser / src / lib / statusq.c
1 /*###########################################################################
2 #
3 # This file contains a portion of code from Samba package, 
4 # which contains the following license:                    
5 # Unix SMB/Netbios implementation
6 # Version 1.9
7 # Main SMB server routine
8 # Copyright (C) Andrew Tridgell 1992-199
9 #
10 # written by :  Stephen J. Friedl
11 #               Software Consultant
12 #               steve@unixwiz.net
13 #
14 # Copyright (C) 2007 - 2008 by
15 # nixkoenner <nixkoenner@newnigma2.to>
16 # License: GPL
17 #
18 # This program is free software; you can redistribute it and/or modify
19 # it under the terms of the GNU General Public License as published by
20 # the Free Software Foundation; either version 2 of the License, or
21 # (at your option) any later version.
22 #
23 # This program is distributed in the hope that it will be useful,
24 # but WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 # GNU General Public License for more details.
27 #
28 # You should have received a copy of the GNU General Public License
29 # along with this program; if not, write to the Free Software
30 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #
32 ###########################################################################*/
33
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <stdlib.h>
39 #include <sys/time.h>
40 #include "statusq.h"
41 #include <string.h>
42 #include <stdio.h>
43 #include <stddef.h>
44 #include <ctype.h>
45 #include "errors.h"
46
47 extern int quiet;
48
49 /* Start of code from Samba */
50 int name_mangle( char *In, char *Out, char name_type ) {
51         int   i;
52         int   c;
53         int   len;
54         char  buf[20];
55         char *p = Out;
56         char* scope="";
57
58         /* Safely copy the input string, In, into buf[]. */
59         (void)memset( buf, 0, 20 );
60         if (strcmp(In,"*") == 0) buf[0] = '*';
61         else
62 #ifdef HAVE_SNPRINTF
63                 (void)snprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
64 #else
65                 (void)sprintf( buf, "%-15.15s%c", In, name_type );
66 #endif /* HAVE_SNPRINTF */
67
68         /* Place the length of the first field into the output buffer. */
69         p[0] = 32;
70         p++;
71
72         /* Now convert the name to the rfc1001/1002 format. */
73         for( i = 0; i < 16; i++ ) {
74                 c = toupper( buf[i] );
75                 p[i*2]     = ( (c >> 4) & 0x000F ) + 'A';
76                 p[(i*2)+1] = (c & 0x000F) + 'A';
77         }
78         p += 32;
79         p[0] = '\0';
80
81         /* Add the scope string. */
82         for( i = 0, len = 0; NULL != scope; i++, len++ ) {
83                 switch( scope[i] ) {
84                 case '\0':
85                         p[0]     = len;
86                         if( len > 0 ) p[len+1] = 0;
87                         return( strlen(Out) );
88                 case '.':
89                         p[0] = len;
90                 p   += (len + 1);
91                 len  = 0;
92                         break;
93                 default:
94                         p[len+1] = scope[i];
95                         break;
96                 }
97         }
98         return( strlen(Out) );
99 }; /* name_mangle */
100 /* end of code from Samba */
101
102
103 int send_query(int sock, struct in_addr dest_addr, my_uint32_t rtt_base) {
104         struct nbname_request request;
105         struct sockaddr_in dest_sockaddr;
106         int status;
107         struct timeval tv;
108         char errmsg[80];
109
110         bzero((void*)&dest_sockaddr, sizeof(dest_sockaddr));
111         dest_sockaddr.sin_family = AF_INET;
112         dest_sockaddr.sin_port = htons(NB_DGRAM);
113         dest_sockaddr.sin_addr = dest_addr;
114  
115         request.flags = htons(FL_BROADCAST);
116         request.question_count = htons(1);
117         request.answer_count = 0;
118         request.name_service_count = 0;
119         request.additional_record_count = 0;
120         name_mangle("*", request.question_name,0);
121         request.question_type = htons(0x21);
122         request.question_class = htons(0x01);
123
124         gettimeofday(&tv, NULL);
125         /* Use transaction ID as a timestamp */
126         request.transaction_id = htons((tv.tv_sec-rtt_base)*1000+tv.tv_usec/1000);
127         /* printf("%s: timestamp: %d\n", inet_ntoa(dest_addr), request.transaction_id); */
128         
129         status = sendto(sock, (char*)&request, sizeof(request), 0,
130                 (struct sockaddr *)&dest_sockaddr, sizeof(dest_sockaddr));
131         if(status==-1) {
132                 snprintf(errmsg, 80, "%s\tSendto failed", inet_ntoa(dest_addr));
133                 err_print(errmsg, quiet); return(-1);
134         };
135         return 0;
136 };
137
138 my_uint32_t get32(void* data) {
139         union {
140                 char bytes[4];
141                 my_uint32_t all;
142         } x;
143
144         memcpy(x.bytes, data, 4);
145         return(ntohl(x.all));
146 };
147
148 my_uint16_t get16(void* data) {
149         union {
150                 char bytes[2];
151                 my_uint16_t all;
152         } x;
153
154         memcpy(x.bytes, data, 2);
155         return(ntohs(x.all));
156 };
157
158 struct nb_host_info* parse_response(char* buff, int buffsize) {
159         struct nb_host_info* hostinfo = NULL;
160         nbname_response_footer_t* response_footer;
161         nbname_response_header_t* response_header;
162         int name_table_size;
163         int offset = 0;
164
165         if((response_header = malloc(sizeof(nbname_response_header_t)))==NULL) return NULL;
166         if((response_footer = malloc(sizeof(nbname_response_footer_t)))==NULL) return NULL;
167         bzero(response_header, sizeof(nbname_response_header_t));
168         bzero(response_footer, sizeof(nbname_response_footer_t));
169         
170         if((hostinfo = malloc(sizeof(struct nb_host_info)))==NULL) return NULL;
171         hostinfo->header = NULL;
172         hostinfo->names = NULL;
173         hostinfo->footer = NULL;
174
175         /* Parsing received packet */
176         /* Start with header */
177         if( offset+sizeof(response_header->transaction_id) >= buffsize) goto broken_packet;
178         response_header->transaction_id = get16(buff+offset); 
179         //Move pointer to the next structure field
180         offset+=sizeof(response_header->transaction_id);
181         hostinfo->header = response_header;
182
183         // Check if there is room for next field in buffer
184         if( offset+sizeof(response_header->flags) >= buffsize) goto broken_packet; 
185         response_header->flags = get16(buff+offset);
186         offset+=sizeof(response_header->flags);
187         
188         if( offset+sizeof(response_header->question_count) >= buffsize) goto broken_packet;
189         response_header->question_count = get16(buff+offset);
190         offset+=sizeof(response_header->question_count);
191         
192         if( offset+sizeof(response_header->answer_count) >= buffsize) goto broken_packet;
193         response_header->answer_count = get16(buff+offset);
194         offset+=sizeof(response_header->answer_count);
195         
196         if( offset+sizeof(response_header->name_service_count) >= buffsize) goto broken_packet;
197         response_header->name_service_count = get16(buff+offset);
198         offset+=sizeof(response_header->name_service_count);
199         
200         if( offset+sizeof(response_header->additional_record_count) >= buffsize) goto broken_packet;
201         response_header->additional_record_count = get16(buff+offset);
202         offset+=sizeof(response_header->additional_record_count);
203         
204         if( offset+sizeof(response_header->question_name) >= buffsize) goto broken_packet;
205         strncpy(response_header->question_name, buff+offset, sizeof(response_header->question_name));
206         offset+=sizeof(response_header->question_name);
207         
208         if( offset+sizeof(response_header->question_type) >= buffsize) goto broken_packet;
209         response_header->question_type = get16(buff+offset);
210         offset+=sizeof(response_header->question_type);
211         
212         if( offset+sizeof(response_header->question_class) >= buffsize) goto broken_packet;
213         response_header->question_class = get16(buff+offset);
214         offset+=sizeof(response_header->question_class);
215         
216         if( offset+sizeof(response_header->ttl) >= buffsize) goto broken_packet;
217         response_header->ttl = get32(buff+offset);
218         offset+=sizeof(response_header->ttl);
219         
220         if( offset+sizeof(response_header->rdata_length) >= buffsize) goto broken_packet;
221         response_header->rdata_length = get16(buff+offset);
222         offset+=sizeof(response_header->rdata_length);
223         
224         if( offset+sizeof(response_header->number_of_names) >= buffsize) goto broken_packet;
225         response_header->number_of_names = *(typeof(response_header->number_of_names)*)(buff+offset);
226   offset+=sizeof(response_header->number_of_names);
227
228         /* Done with packet header - it is okay */
229         
230         name_table_size = (response_header->number_of_names) * (sizeof(struct nbname));
231         if( offset+name_table_size >= buffsize) goto broken_packet;
232         
233         if((hostinfo->names = malloc(name_table_size))== NULL) return NULL;
234         memcpy(hostinfo->names, buff + offset, name_table_size);
235         //printf("DEBUG: %s , %d\n", hostinfo->names, name_table_size);
236         
237         offset+=name_table_size;
238
239         /* Done with name table - it is okay */ 
240  
241         /* Now parse response footer */
242
243         if( offset+sizeof(response_footer->adapter_address) >= buffsize) goto broken_packet;    
244         memcpy(response_footer->adapter_address, 
245                (buff+offset), 
246                sizeof(response_footer->adapter_address));
247         offset+=sizeof(response_footer->adapter_address);
248
249         hostinfo->footer=response_footer;       
250
251         if( offset+sizeof(response_footer->version_major) >= buffsize) goto broken_packet;
252         response_footer->version_major = *(typeof(response_footer->version_major)*)(buff+offset);
253         offset+=sizeof(response_footer->version_major);
254         
255         if( offset+sizeof(response_footer->version_minor) >= buffsize) goto broken_packet;
256         response_footer->version_minor = *(typeof(response_footer->version_minor)*)(buff+offset);
257         offset+=sizeof(response_footer->version_minor);
258         
259         if( offset+sizeof(response_footer->duration) >= buffsize) goto broken_packet;
260         response_footer->duration = get16(buff+offset);
261         offset+=sizeof(response_footer->duration);
262         
263         if( offset+sizeof(response_footer->frmps_received) >= buffsize) goto broken_packet;
264         response_footer->frmps_received= get16(buff+offset);
265         offset+=sizeof(response_footer->frmps_received);
266         
267         if( offset+sizeof(response_footer->frmps_transmitted) >= buffsize) goto broken_packet;
268         response_footer->frmps_transmitted = get16(buff+offset);
269         offset+=sizeof(response_footer->frmps_transmitted);
270         
271         if( offset+sizeof(response_footer->iframe_receive_errors) >= buffsize) goto broken_packet;
272         response_footer->iframe_receive_errors = get16(buff+offset);
273         offset+=sizeof(response_footer->iframe_receive_errors);
274         
275         if( offset+sizeof(response_footer->transmit_aborts) >= buffsize) goto broken_packet;
276         response_footer->transmit_aborts =  get16(buff+offset);
277         offset+=sizeof(response_footer->transmit_aborts);
278         
279         if( offset+sizeof(response_footer->transmitted) >= buffsize) goto broken_packet;
280         response_footer->transmitted = get32(buff+offset);
281         offset+=sizeof(response_footer->transmitted);
282         
283         if( offset+sizeof(response_footer->received) >= buffsize) goto broken_packet;
284         response_footer->received = get32(buff+offset);
285         offset+=sizeof(response_footer->received);
286         
287         if( offset+sizeof(response_footer->iframe_transmit_errors) >= buffsize) goto broken_packet;
288         response_footer->iframe_transmit_errors = get16(buff+offset);
289         offset+=sizeof(response_footer->iframe_transmit_errors);
290         
291         if( offset+sizeof(response_footer->no_receive_buffer) >= buffsize) goto broken_packet;
292         response_footer->no_receive_buffer = get16(buff+offset);
293         offset+=sizeof(response_footer->no_receive_buffer);
294         
295         if( offset+sizeof(response_footer->tl_timeouts) >= buffsize) goto broken_packet;
296         response_footer->tl_timeouts = get16(buff+offset);
297         offset+=sizeof(response_footer->tl_timeouts);
298         
299         if( offset+sizeof(response_footer->ti_timeouts) >= buffsize) goto broken_packet;
300         response_footer->ti_timeouts = get16(buff+offset);
301         offset+=sizeof(response_footer->ti_timeouts);
302         
303         if( offset+sizeof(response_footer->free_ncbs) >= buffsize) goto broken_packet;
304         response_footer->free_ncbs = get16(buff+offset);
305         offset+=sizeof(response_footer->free_ncbs);
306         
307         if( offset+sizeof(response_footer->ncbs) >= buffsize) goto broken_packet;
308         response_footer->ncbs = get16(buff+offset);
309         offset+=sizeof(response_footer->ncbs);
310         
311         if( offset+sizeof(response_footer->max_ncbs) >= buffsize) goto broken_packet;
312         response_footer->max_ncbs = get16(buff+offset);
313         offset+=sizeof(response_footer->max_ncbs);
314         
315         if( offset+sizeof(response_footer->no_transmit_buffers) >= buffsize) goto broken_packet;
316         response_footer->no_transmit_buffers = get16(buff+offset);
317         offset+=sizeof(response_footer->no_transmit_buffers);
318         
319         if( offset+sizeof(response_footer->max_datagram) >= buffsize) goto broken_packet;
320         response_footer->max_datagram = get16(buff+offset);
321         offset+=sizeof(response_footer->max_datagram);
322         
323         if( offset+sizeof(response_footer->pending_sessions) >= buffsize) goto broken_packet;
324         response_footer->pending_sessions = get16(buff+offset);
325         offset+=sizeof(response_footer->pending_sessions);
326         
327         if( offset+sizeof(response_footer->max_sessions) >= buffsize) goto broken_packet;
328         response_footer->max_sessions = get16(buff+offset);
329         offset+=sizeof(response_footer->max_sessions);
330         
331         if( offset+sizeof(response_footer->packet_sessions) >= buffsize) goto broken_packet;
332         response_footer->packet_sessions = get16(buff+offset);
333         offset+=sizeof(response_footer->packet_sessions);
334         
335         /* Done with packet footer and the whole packet */
336
337         return hostinfo;
338         
339         broken_packet: 
340                 hostinfo->is_broken = offset;
341                 return hostinfo;        
342 };
343
344 nb_service_t services[] = {
345 {"__MSBROWSE__", 0x01, 0, "Master Browser"},
346 {"INet~Services", 0x1C, 0, "IIS"},
347 {"IS~", 0x00, 1, "IIS"},
348 {"", 0x00, 1, "Workstation Service"},
349 {"", 0x01, 1, "Messenger Service"},
350 {"", 0x03, 1, "Messenger Service"},
351 {"", 0x06, 1, "RAS Server Service"},
352 {"", 0x1F, 1, "NetDDE Service"},
353 {"", 0x20, 1, "File Server Service"},
354 {"", 0x21, 1, "RAS Client Service"},
355 {"", 0x22, 1, "Microsoft Exchange Interchange(MSMail Connector)"},
356 {"", 0x23, 1, "Microsoft Exchange Store"},
357 {"", 0x24, 1, "Microsoft Exchange Directory"},
358 {"", 0x30, 1, "Modem Sharing Server Service"},
359 {"", 0x31, 1, "Modem Sharing Client Service"},
360 {"", 0x43, 1, "SMS Clients Remote Control"},
361 {"", 0x44, 1, "SMS Administrators Remote Control Tool"},
362 {"", 0x45, 1, "SMS Clients Remote Chat"},
363 {"", 0x46, 1, "SMS Clients Remote Transfer"},
364 {"", 0x4C, 1, "DEC Pathworks TCPIP service on Windows NT"},
365 {"", 0x52, 1, "DEC Pathworks TCPIP service on Windows NT"},
366 {"", 0x87, 1, "Microsoft Exchange MTA"},
367 {"", 0x6A, 1, "Microsoft Exchange IMC"},
368 {"", 0xBE, 1, "Network Monitor Agent"},
369 {"", 0xBF, 1, "Network Monitor Application"},
370 {"", 0x03, 1, "Messenger Service"},
371 {"", 0x00, 0, "Domain Name"},
372 {"", 0x1B, 1, "Domain Master Browser"},
373 {"", 0x1C, 0, "Domain Controllers"},
374 {"", 0x1D, 1, "Master Browser"},
375 {"", 0x1E, 0, "Browser Service Elections"},
376 {"", 0x2B, 1, "Lotus Notes Server Service"},
377 {"IRISMULTICAST", 0x2F, 0, "Lotus Notes"},
378 {"IRISNAMESERVER", 0x33, 0, "Lotus Notes"},
379 {"Forte_$ND800ZA", 0x20, 1, "DCA IrmaLan Gateway Server Service"}
380 };
381
382 char* getnbservicename(my_uint8_t service, int unique, char* name) {
383         int i;
384         char *unknown;
385
386         unknown = (char*)malloc(100);
387
388         if(!unknown) err_die("Malloc failed.\n", 0);
389         
390         for(i=0; i < 35; i++) {
391                 if(strstr(name, services[i].nb_name) && 
392                         service == services[i].service_number &&
393                         unique == services[i].unique)
394                         printf("blubber name = %s\n",services[i].service_name);
395                 return services[i].service_name;
396         };      
397
398         snprintf(unknown, 100, "Unknown service (code %x)", service);
399         return(unknown);
400 };