-add Networkbrowser and Mountmanager to easy browse network for networkdevices and...
[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         
236         offset+=name_table_size;
237
238         /* Done with name table - it is okay */ 
239  
240         /* Now parse response footer */
241
242         if( offset+sizeof(response_footer->adapter_address) >= buffsize) goto broken_packet;    
243         memcpy(response_footer->adapter_address, 
244                (buff+offset), 
245                sizeof(response_footer->adapter_address));
246         offset+=sizeof(response_footer->adapter_address);
247
248         hostinfo->footer=response_footer;       
249
250         if( offset+sizeof(response_footer->version_major) >= buffsize) goto broken_packet;
251         response_footer->version_major = *(typeof(response_footer->version_major)*)(buff+offset);
252         offset+=sizeof(response_footer->version_major);
253         
254         if( offset+sizeof(response_footer->version_minor) >= buffsize) goto broken_packet;
255         response_footer->version_minor = *(typeof(response_footer->version_minor)*)(buff+offset);
256         offset+=sizeof(response_footer->version_minor);
257         
258         if( offset+sizeof(response_footer->duration) >= buffsize) goto broken_packet;
259         response_footer->duration = get16(buff+offset);
260         offset+=sizeof(response_footer->duration);
261         
262         if( offset+sizeof(response_footer->frmps_received) >= buffsize) goto broken_packet;
263         response_footer->frmps_received= get16(buff+offset);
264         offset+=sizeof(response_footer->frmps_received);
265         
266         if( offset+sizeof(response_footer->frmps_transmitted) >= buffsize) goto broken_packet;
267         response_footer->frmps_transmitted = get16(buff+offset);
268         offset+=sizeof(response_footer->frmps_transmitted);
269         
270         if( offset+sizeof(response_footer->iframe_receive_errors) >= buffsize) goto broken_packet;
271         response_footer->iframe_receive_errors = get16(buff+offset);
272         offset+=sizeof(response_footer->iframe_receive_errors);
273         
274         if( offset+sizeof(response_footer->transmit_aborts) >= buffsize) goto broken_packet;
275         response_footer->transmit_aborts =  get16(buff+offset);
276         offset+=sizeof(response_footer->transmit_aborts);
277         
278         if( offset+sizeof(response_footer->transmitted) >= buffsize) goto broken_packet;
279         response_footer->transmitted = get32(buff+offset);
280         offset+=sizeof(response_footer->transmitted);
281         
282         if( offset+sizeof(response_footer->received) >= buffsize) goto broken_packet;
283         response_footer->received = get32(buff+offset);
284         offset+=sizeof(response_footer->received);
285         
286         if( offset+sizeof(response_footer->iframe_transmit_errors) >= buffsize) goto broken_packet;
287         response_footer->iframe_transmit_errors = get16(buff+offset);
288         offset+=sizeof(response_footer->iframe_transmit_errors);
289         
290         if( offset+sizeof(response_footer->no_receive_buffer) >= buffsize) goto broken_packet;
291         response_footer->no_receive_buffer = get16(buff+offset);
292         offset+=sizeof(response_footer->no_receive_buffer);
293         
294         if( offset+sizeof(response_footer->tl_timeouts) >= buffsize) goto broken_packet;
295         response_footer->tl_timeouts = get16(buff+offset);
296         offset+=sizeof(response_footer->tl_timeouts);
297         
298         if( offset+sizeof(response_footer->ti_timeouts) >= buffsize) goto broken_packet;
299         response_footer->ti_timeouts = get16(buff+offset);
300         offset+=sizeof(response_footer->ti_timeouts);
301         
302         if( offset+sizeof(response_footer->free_ncbs) >= buffsize) goto broken_packet;
303         response_footer->free_ncbs = get16(buff+offset);
304         offset+=sizeof(response_footer->free_ncbs);
305         
306         if( offset+sizeof(response_footer->ncbs) >= buffsize) goto broken_packet;
307         response_footer->ncbs = get16(buff+offset);
308         offset+=sizeof(response_footer->ncbs);
309         
310         if( offset+sizeof(response_footer->max_ncbs) >= buffsize) goto broken_packet;
311         response_footer->max_ncbs = get16(buff+offset);
312         offset+=sizeof(response_footer->max_ncbs);
313         
314         if( offset+sizeof(response_footer->no_transmit_buffers) >= buffsize) goto broken_packet;
315         response_footer->no_transmit_buffers = get16(buff+offset);
316         offset+=sizeof(response_footer->no_transmit_buffers);
317         
318         if( offset+sizeof(response_footer->max_datagram) >= buffsize) goto broken_packet;
319         response_footer->max_datagram = get16(buff+offset);
320         offset+=sizeof(response_footer->max_datagram);
321         
322         if( offset+sizeof(response_footer->pending_sessions) >= buffsize) goto broken_packet;
323         response_footer->pending_sessions = get16(buff+offset);
324         offset+=sizeof(response_footer->pending_sessions);
325         
326         if( offset+sizeof(response_footer->max_sessions) >= buffsize) goto broken_packet;
327         response_footer->max_sessions = get16(buff+offset);
328         offset+=sizeof(response_footer->max_sessions);
329         
330         if( offset+sizeof(response_footer->packet_sessions) >= buffsize) goto broken_packet;
331         response_footer->packet_sessions = get16(buff+offset);
332         offset+=sizeof(response_footer->packet_sessions);
333         
334         /* Done with packet footer and the whole packet */
335
336         return hostinfo;
337         
338         broken_packet: 
339                 hostinfo->is_broken = offset;
340                 return hostinfo;        
341 };
342
343 nb_service_t services[] = {
344 {"__MSBROWSE__", 0x01, 0, "Master Browser"},
345 {"INet~Services", 0x1C, 0, "IIS"},
346 {"IS~", 0x00, 1, "IIS"},
347 {"", 0x00, 1, "Workstation Service"},
348 {"", 0x01, 1, "Messenger Service"},
349 {"", 0x03, 1, "Messenger Service"},
350 {"", 0x06, 1, "RAS Server Service"},
351 {"", 0x1F, 1, "NetDDE Service"},
352 {"", 0x20, 1, "File Server Service"},
353 {"", 0x21, 1, "RAS Client Service"},
354 {"", 0x22, 1, "Microsoft Exchange Interchange(MSMail Connector)"},
355 {"", 0x23, 1, "Microsoft Exchange Store"},
356 {"", 0x24, 1, "Microsoft Exchange Directory"},
357 {"", 0x30, 1, "Modem Sharing Server Service"},
358 {"", 0x31, 1, "Modem Sharing Client Service"},
359 {"", 0x43, 1, "SMS Clients Remote Control"},
360 {"", 0x44, 1, "SMS Administrators Remote Control Tool"},
361 {"", 0x45, 1, "SMS Clients Remote Chat"},
362 {"", 0x46, 1, "SMS Clients Remote Transfer"},
363 {"", 0x4C, 1, "DEC Pathworks TCPIP service on Windows NT"},
364 {"", 0x52, 1, "DEC Pathworks TCPIP service on Windows NT"},
365 {"", 0x87, 1, "Microsoft Exchange MTA"},
366 {"", 0x6A, 1, "Microsoft Exchange IMC"},
367 {"", 0xBE, 1, "Network Monitor Agent"},
368 {"", 0xBF, 1, "Network Monitor Application"},
369 {"", 0x03, 1, "Messenger Service"},
370 {"", 0x00, 0, "Domain Name"},
371 {"", 0x1B, 1, "Domain Master Browser"},
372 {"", 0x1C, 0, "Domain Controllers"},
373 {"", 0x1D, 1, "Master Browser"},
374 {"", 0x1E, 0, "Browser Service Elections"},
375 {"", 0x2B, 1, "Lotus Notes Server Service"},
376 {"IRISMULTICAST", 0x2F, 0, "Lotus Notes"},
377 {"IRISNAMESERVER", 0x33, 0, "Lotus Notes"},
378 {"Forte_$ND800ZA", 0x20, 1, "DCA IrmaLan Gateway Server Service"}
379 };
380
381 char* getnbservicename(my_uint8_t service, int unique, char* name) {
382         int i;
383         char *unknown;
384
385         unknown = (char*)malloc(100);
386
387         if(!unknown) err_die("Malloc failed.\n", 0);
388         
389         for(i=0; i < 35; i++) {
390                 if(strstr(name, services[i].nb_name) && 
391                         service == services[i].service_number &&
392                         unique == services[i].unique)
393                         printf("blubber name = %s\n",services[i].service_name);
394                 return services[i].service_name;
395         };      
396
397         snprintf(unknown, 100, "Unknown service (code %x)", service);
398         return(unknown);
399 };