00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "nip_init.h"
00032 #include "app/mdns.h"
00033 #include "dispatcher.h"
00034 #include "net/udp.h"
00035 #include "app/ports.h"
00036 #include "inet.h"
00037
00038 #if ( NIP_MDNS_ENABLE == 1 )
00039
00040
00041
00042 struct nip_mdns_check nip_mdns;
00043
00044 nip_net_if_id_t nip_mdns_if_id = NIP_NET_NO_IF;
00045 nip_udp_sock_id_t nip_mdns_sock = NIP_UDP_NO_SOCKET;
00046 nip_mdns_cache_id_t nip_mdns_hostname = NIP_MDNS_NO_CACHE_ID;
00047 nip_mdns_cache_id_t nip_mdns_host_ptr = NIP_MDNS_NO_CACHE_ID;
00048 nip_mdns_namestring_id_t nip_mdns_domain = NIP_MDNS_NO_NAMESTRING;
00049 nip_mem_handle_t nip_mdns_cs = NIP_MEM_NULL;
00050 nip_mem_ptr_t nip_mdns_cache = {NIP_MEM_NULL,NULL};
00051 nip_mem_handle_t nip_mdns_names = NIP_MEM_NULL;
00052 nip_mem_ptr_t nip_mdns_queries = {NIP_MEM_NULL,NULL};
00053
00054 void nip_mdns_register_hostname( struct nip_dns_string *name );
00055 void nip_mdns_disp_check_queries( void );
00056 nip_error_t nip_mdns_parse_packet( nip_udp_buf_type_t udp_buffer,
00057 nip_mdns_packet_task_t task, nip_mem_ptr_t *p, nip_mdns_qa_offset_t section );
00058
00059
00060
00061
00062
00063 nip_error_t nip_mdns_init( void )
00064 {
00065
00066 union
00067 {
00068 struct nip_udp_sock_addr addr;
00069
00070
00071
00072
00073
00074 uint8_t local[6];
00075 uint8_t avr[4];
00076 uint8_t mc_addr[4];
00077 } tmp;
00078 nip_mem_ptr_t name_ptr;
00079
00080
00081 if ( nip_mdns_cs == NIP_MEM_NULL )
00082 nip_mdns_cs = nip_mem_alloc( 0, 0, 0, NULL );
00083 if ( nip_mdns_cache.id == NIP_MEM_NULL )
00084 nip_mdns_cache.id = nip_mem_alloc( 0, 0, 0, NULL );
00085 if ( nip_mdns_names == NIP_MEM_NULL )
00086 nip_mdns_names = nip_mem_alloc( 0, 0, 0, NULL );
00087 if ( nip_mdns_queries.id == NIP_MEM_NULL )
00088 nip_mdns_queries.id = nip_mem_alloc( 0, 0, 0, NULL );
00089
00090
00091 if ( nip_mdns_domain == NIP_MDNS_NO_NAMESTRING )
00092 {
00093 tmp.local[0] = 5;
00094 tmp.local[1] = 'l';
00095 tmp.local[2] = 'o';
00096 tmp.local[3] = 'c';
00097 tmp.local[4] = 'a';
00098 tmp.local[5] = 'l';
00099 name_ptr.id = NIP_MEM_NULL;
00100 name_ptr.ptr = tmp.local;
00101 nip_mdns_domain = NIP_MDNS_REG_STRING( &name_ptr );
00102 }
00103
00104 if ( nip_mdns_domain == NIP_MDNS_NO_NAMESTRING
00105 || nip_mdns_cache.id == NIP_MEM_NULL
00106 || nip_mdns_cs == NIP_MEM_NULL )
00107 {
00108 return NIP_E_OUT_OF_MEMORY;
00109 }
00110
00111
00112 if ( nip_mdns.stat == NIP_MDNS_STAT_DOWN )
00113 return NIP_E_NOT_CONFIGURED;
00114
00115
00116 if ( nip_mdns_hostname == NIP_MDNS_NO_CACHE_ID )
00117 {
00118 tmp.avr[0] = 3;
00119
00120
00121 tmp.avr[1] = 'A';
00122 tmp.avr[2] = 'V';
00123 tmp.avr[3] = 'R';
00124
00125
00126 nip_mdns_register_hostname( (struct nip_dns_string *)tmp.avr );
00127 if ( nip_error != NIP_E_OK )
00128 return nip_error;
00129 }
00130
00131
00132 if ( nip_mdns_sock == NIP_UDP_NO_SOCKET && nip_mdns_if_id != NIP_NET_NO_IF )
00133 {
00134
00135 tmp.addr.port = NIP_UDP_PORT_MDNS;
00136 nip_memcpy( tmp.addr.ip, NIP_IP_ADDR( nip_mdns_if_id ), 4 );
00137
00138
00139
00140
00141 nip_mdns_sock = nip_udp_socket(
00142 &tmp.addr,
00143 NIP_UDP_SOCK_FLG_LISTENING | NIP_UDP_SOCK_FLG_NON_BLOCK
00144 );
00145 if ( nip_mdns_sock == NIP_UDP_NO_SOCKET )
00146 return nip_error;
00147 }
00148
00149
00150 tmp.mc_addr[0]=NIP_MDNS_ADDR0;
00151 tmp.mc_addr[1]=NIP_MDNS_ADDR1;
00152 tmp.mc_addr[2]=NIP_MDNS_ADDR2;
00153 tmp.mc_addr[3]=NIP_MDNS_ADDR3;
00154 return nip_ip_join_host_group( nip_mdns_if_id, tmp.mc_addr );
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 nip_error_t nip_mdns_name_cmp( struct nip_dns_string *n1, struct nip_dns_string *n2)
00190 {
00191 uint8_t pos;
00192 uint8_t utf8_head;
00193 uint8_t c1, c2;
00194
00195 if ( n1->len == n2->len )
00196 {
00197 pos = 0;
00198 utf8_head = 0;
00199 do
00200 {
00201 c1 =n1->s[pos]; c2 = n2->s[pos];
00202
00203
00204 if ( (utf8_head & 0x80) == 0 )
00205 utf8_head = c1;
00206 else
00207 utf8_head <<= 1;
00208
00209
00210
00211 if ( (utf8_head & 0x80) == 0 )
00212 {
00213 if ( c1 >= 'A' && c1 <='Z' ) c1 += 'a'-'A';
00214 if ( c2 >= 'A' && c2 <='Z' ) c2 += 'a'-'A';
00215 }
00216
00217 if ( c1 != c2 )
00218 goto abort_no_match;
00219
00220 } while ( ++pos < n1->len );
00221 return NIP_E_OK;
00222 }
00223
00224 abort_no_match:
00225 return NIP_E_NO_MATCH;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 nip_mdns_namestring_id_t nip_mdns_register_name( nip_mdns_namestring_id_t *id,
00259 uint8_t cnt, nip_mem_ptr_t *name_ptr, nip_mdns_namestring_usg_t usg )
00260 {
00261 nip_mdns_namestring_id_t res = NIP_MDNS_NO_NAMESTRING;
00262 nip_mdns_namestring_id_t new_id = 1;
00263 nip_mem_ptr_t current;
00264 nip_mem_ptr_t name_src;
00265 nip_error_t err;
00266 nip_mem_size_t len;
00267 nip_mem_size_t listsize;
00268 struct nip_dns_string *name = NULL;
00269 uint8_t i = 0;
00270 struct nip_mdns_namestring *l;
00271
00272 listsize = nip_mem_buf_used( nip_mdns_names );
00273
00274 do
00275 {
00276 current.id = nip_mdns_names;
00277 current.ptr = (void*)0;
00278
00279
00280 if ( name == NULL && (name = nip_mem_ptr( name_ptr )) == NULL && id == NULL )
00281 {
00282 new_id = NIP_MDNS_NO_NAMESTRING;
00283 break;
00284 }
00285
00286
00287 while ( (l = nip_mem_ptr( ¤t ) ) != NULL )
00288 {
00289
00290 if ( id != NULL && ( name_ptr == NULL || usg == 0 ) )
00291 {
00292 new_id = NIP_MDNS_NO_NAMESTRING;
00293 if ( id[i] == NIP_MDNS_NO_NAMESTRING )
00294 i = cnt;
00295 else if ( id[i] == l->id )
00296 {
00297 l->usg += usg;
00298 name_src.id = current.id;
00299 name_src.ptr = current.ptr + NIP_MDNS_STRINGOFF;
00300 len = l->str.len;
00301
00302
00303 l = NULL;
00304 nip_mem_release_block( current.id );
00305 nip_mem_release_ptr( name_ptr );
00306
00307
00308 nip_mem_insert( name_ptr, &name_src, len+1 );
00309
00310 }
00311 else
00312 {
00313
00314 goto next;
00315 }
00316
00317
00318
00319 if ( i >= NIP_MDNS_MAX_NAME_DEPTH-1 )
00320 {
00321 name_src.id = NIP_MEM_NULL;
00322 name_src.ptr = NULL;
00323 nip_mem_insert( name_ptr, &name_src, 1 );
00324 }
00325
00326 break;
00327 }
00328
00329
00330 if ( nip_mdns_name_cmp( &(l->str), name ) == NIP_E_OK )
00331 {
00332
00333 new_id = NIP_MDNS_NO_NAMESTRING;
00334 res = l->id;
00335 l->usg += usg;
00336 break;
00337 }
00338
00339
00340 if ( new_id == l->id )
00341 {
00342 new_id++;
00343 current.ptr = (void*)0;
00344 goto release;
00345 }
00346
00347 next:
00348
00349 current.ptr += sizeof( struct nip_mdns_namestring ) + l->str.len;
00350
00351 release:
00352 nip_mem_release_block( current.id );
00353 l = NULL;
00354 }
00355 if ( l != NULL )
00356 nip_mem_release_block( current.id );
00357
00358
00359 if ( new_id != NIP_MDNS_NO_NAMESTRING && new_id < NIP_MDNS_MAX_NAMESTRINGS && usg != 0 )
00360 {
00361 len = name->len;
00362
00363
00364
00365 nip_mem_release_ptr( name_ptr );
00366
00367
00368 if ( len == 0 )
00369 {
00370 id[i] = 0;
00371 goto quit;
00372 }
00373
00374
00375
00376 err = nip_mem_write( nip_mdns_names, NULL, sizeof( struct nip_mdns_namestring ) + len );
00377
00378 if ( err != NIP_E_OK )
00379 goto add_error;
00380
00381
00382 name = nip_mem_ptr( name_ptr );
00383 if ( name == NULL )
00384 goto add_error;
00385
00386 l = nip_mem_ptr( ¤t);
00387 if ( l == NULL )
00388 goto add_error;
00389
00390
00391 l->id = new_id;
00392 l->usg = usg;
00393 l->str.len = name->len;
00394
00395
00396 nip_memcpy( l->str.s, name->s, name->len );
00397
00398 res = new_id;
00399 if ( id != NULL )
00400 {
00401 id[i] = new_id;
00402 }
00403 nip_mem_release_ptr( ¤t );
00404
00405
00406 name_ptr->ptr += len+1;
00407 name = (struct nip_dns_string*)(((uint8_t*)name) + len+1);
00408
00409 continue;
00410
00411 add_error:
00412
00413 nip_mem_set_used( nip_mdns_names, listsize );
00414 goto release_name;
00415 }
00416 }
00417 while ( ++i < cnt );
00418
00419
00420 release_name:
00421
00422
00423 if ( name != NULL )
00424 nip_mem_release_ptr( name_ptr );
00425
00426 quit:
00427 return res;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 nip_mdns_query_id_t nip_mdns_query( nip_mdns_query_type_t type,
00441 struct nip_mdns_name *rr_name, nip_mdns_type_t rr_type )
00442 {
00443 nip_mdns_query_id_t res = NIP_MDNS_NO_QUERY;
00444 nip_mdns_query_id_t new_id = 0;
00445 nip_mem_size_t listsize;
00446 struct nip_mdns_query *l, *end;
00447 struct nip_mdns_query query;
00448
00449 listsize = nip_mem_buf_used( nip_mdns_queries.id );
00450
00451
00452 l = nip_mem_obtain_ptr( nip_mdns_queries.id );
00453 if ( l == NULL )
00454 {
00455 goto quit;
00456 }
00457
00458 end = (void *)((uint8_t*)l + listsize );
00459 while ( l != end )
00460 {
00461
00462 if ( nip_memcmp( &l->rr_name, rr_name, sizeof( struct nip_mdns_name ) ) == 0 )
00463 {
00464
00465 if ( l->type == NIP_MDNS_QTYPE_PROBE )
00466 {
00467 if ( type == NIP_MDNS_QTYPE_PROBE )
00468 {
00469 res = (l->id & NIP_MDNS_QUERY_ID_MASK);
00470 break;
00471 }
00472 }
00473
00474
00475 else if ( type == NIP_MDNS_QTYPE_REMOTE
00476 || ( type == NIP_MDNS_QTYPE_LOCAL && l->type == NIP_MDNS_QTYPE_REMLOC))
00477 {
00478 if ( l->type == NIP_MDNS_QTYPE_LOCAL )
00479 l->type = NIP_MDNS_QTYPE_REMLOC;
00480 res = (l->id & NIP_MDNS_QUERY_ID_MASK);
00481 break;
00482 }
00483 }
00484
00485
00486 if ( (new_id & NIP_MDNS_QUERY_ID_MASK) == (l->id & NIP_MDNS_QUERY_ID_MASK) )
00487 {
00488 new_id++;
00489 l = ( struct nip_mdns_query *)((uint8_t*)end - listsize );
00490 continue;
00491 }
00492
00493
00494 l = (void*) ((uint8_t *)l + sizeof( struct nip_mdns_query ));
00495 }
00496 nip_mem_release_block( nip_mdns_queries.id );
00497
00498 if ( (res & NIP_MDNS_QUERY_ID_MASK) == NIP_MDNS_NO_QUERY )
00499 {
00500 if ( (new_id & NIP_MDNS_QUERY_ID_MASK) < NIP_MDNS_MAX_QUERIES )
00501 {
00502 query.id = new_id | NIP_MDNS_QUERY_ACTIVE;
00503 query.type = type;
00504 query.rr_name = *rr_name;
00505 query.rr_type = rr_type;
00506
00507 query.timer = 0;
00508 if ( NIP_E_OK == nip_mem_write(
00509 nip_mdns_queries.id,
00510 (uint8_t*) &query,
00511 sizeof( struct nip_mdns_query ))
00512 )
00513 {
00514 res = new_id;
00515 }
00516
00517
00518 NIP_MDNS_NAME_USE( query.rr_name.part, NIP_MDNS_MAX_NAME_DEPTH );
00519 }
00520 }
00521
00522
00523 quit:
00524 return res;
00525 }
00526
00527
00528
00529
00530 nip_mdns_record_size_t nip_mdns_record_size( struct nip_mdns_record *r )
00531 {
00532
00533 nip_mdns_record_size_t off;
00534 switch ( r->type )
00535 {
00536 case NIP_MDNS_TYPE_A:
00537 off = NIP_MDNS_A_RECORD_SIZE;
00538 break;
00539 case NIP_MDNS_TYPE_SRV:
00540 off = NIP_MDNS_SRV_RECORD_SIZE;
00541 break;
00542 case NIP_MDNS_TYPE_PTR:
00543 off = NIP_MDNS_PTR_RECORD_SIZE;
00544 break;
00545
00546
00547 default:
00548 off = NIP_MDNS_OTH_RECORD_SIZE;
00549 }
00550
00551 return off;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 struct nip_mdns_cache *nip_mdns_cache_ptr( nip_mdns_cache_id_t id )
00564 {
00565 nip_mem_size_t listsize;
00566 struct nip_mdns_cache *l, *end;
00567
00568 listsize = nip_mem_buf_used( nip_mdns_cache.id );
00569 l = nip_mem_obtain_ptr( nip_mdns_cache.id );
00570
00571 if ( l == NULL )
00572 {
00573 nip_error = NIP_E_LOCKED;
00574 goto quit;
00575 }
00576
00577 end = (void*)((uint8_t*)l + listsize );
00578 while ( l != end )
00579 {
00580
00581 if ( l->id == id )
00582 {
00583 return l;
00584 }
00585
00586
00587 l = (struct nip_mdns_cache *)((uint8_t*)l
00588 + NIP_MDNS_BASE_CACHE_SIZE
00589 + nip_mdns_record_size( &l->record ));
00590 }
00591
00592 nip_mem_release_block( nip_mdns_cache.id );
00593
00594 nip_error = NIP_E_NOT_FOUND;
00595
00596 quit:
00597 return NULL;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 nip_error_t nip_mdns_cache_task( nip_mdns_task_t task,
00628 nip_mdns_cache_id_t *id, struct nip_mdns_record *record )
00629 {
00630 nip_mdns_cache_id_t res = NIP_MDNS_NO_CACHE_ID;
00631 nip_mdns_cache_id_t new_id = 1;
00632 nip_mem_size_t listsize;
00633 nip_mem_ptr_t list_ptr = { nip_mdns_cache.id, NULL };
00634 nip_mdns_record_size_t recsize;
00635 uint8_t *start;
00636 struct nip_mdns_cache *l;
00637
00638 listsize = nip_mem_buf_used( nip_mdns_cache.id );
00639 start = nip_mem_obtain_ptr( nip_mdns_cache.id );
00640 l = (struct nip_mdns_cache *)start;
00641
00642 if ( start == NULL )
00643 {
00644 nip_error = NIP_E_LOCKED;
00645 goto quit;
00646 }
00647
00648 while ( (nip_mem_size_t)list_ptr.ptr != listsize )
00649 {
00650 l = (struct nip_mdns_cache *)(start + (nip_mem_size_t)list_ptr.ptr);
00651 recsize = nip_mdns_record_size( &l->record );
00652
00653
00654 if ( task == NIP_MDNS_TASK_RESET )
00655 {
00656
00657 if ( l->stat & NIP_MDNS_CSTAT_AUTH_MASK )
00658 {
00659 l->stat = NIP_MDNS_CSTAT_PROBING;
00660 l->age = 0;
00661 }
00662 else
00663 l->stat = NIP_MDNS_CSTAT_DELETE;
00664
00665 goto next;
00666 }
00667
00668 if ( task & NIP_MDNS_TASK_GET )
00669 {
00670 if ( l->id == *id )
00671 {
00672 nip_memcpy( record, &l->record, recsize );
00673 if ( task == NIP_MDNS_TASK_GET_LEARNED )
00674 record->ttl -= l->age;
00675 nip_error = NIP_E_OK;
00676 goto release;
00677 }
00678
00679 nip_error = NIP_E_NOT_FOUND;
00680 goto next;
00681 }
00682
00683
00684 if ( l->record.type == record->type
00685 && nip_memcmp( &l->record.name, &record->name, sizeof( struct nip_mdns_name) ) == 0 )
00686 {
00687 if ( record->type != NIP_MDNS_TYPE_PTR
00688 || nip_memcmp( &l->record.data, &record->data, sizeof(struct nip_mdns_rdata_a) ))
00689
00690 {
00691 res = l->id;
00692 nip_error = NIP_E_EXISTS;
00693 break;
00694 }
00695 }
00696
00697
00698 if ( new_id == l->id )
00699 {
00700 new_id++;
00701 list_ptr.ptr = NULL;
00702 continue;
00703 }
00704
00705 next:
00706 list_ptr.ptr += NIP_MDNS_BASE_CACHE_SIZE + recsize;
00707 }
00708
00709 if ( task == NIP_MDNS_TASK_RESET )
00710 {
00711 nip_error = NIP_E_OK;
00712 goto release;
00713 }
00714
00715
00716 if ( ( res == NIP_MDNS_NO_CACHE_ID && (task & NIP_MDNS_TASK_REGISTER) )
00717 || task == NIP_MDNS_TASK_LEARN )
00718 {
00719 recsize = nip_mdns_record_size( record );
00720
00721
00722
00723 NIP_MDNS_NAME_USE( record->name.part, NIP_MDNS_MAX_NAME_DEPTH );
00724
00725
00726 if ( res == NIP_MDNS_NO_CACHE_ID )
00727 {
00728 if ( new_id >= NIP_MDNS_MAX_CACHE_SIZE )
00729 {
00730 nip_error = NIP_E_OUT_OF_RESSOURCES;
00731 goto release;
00732 }
00733
00734
00735 nip_mem_release_block( nip_mdns_cache.id );
00736
00737 if ( NIP_E_OK !=
00738 nip_mem_write( nip_mdns_cache.id, NULL, NIP_MDNS_BASE_CACHE_SIZE + recsize ))
00739 {
00740 nip_error = NIP_E_OUT_OF_MEMORY;
00741 goto quit;
00742 }
00743
00744
00745 l = nip_mem_ptr( &list_ptr );
00746 if ( l == NULL )
00747 {
00748 nip_error = NIP_E_INTERNAL_ERROR;
00749
00750 nip_mem_set_used( nip_mdns_cache.id, listsize );
00751 goto quit;
00752 }
00753
00754 l->id = new_id;
00755 res = new_id;
00756 }
00757 else
00758 {
00759
00760
00761 NIP_MDNS_UNREG_NAME( l->record.name.part, NIP_MDNS_MAX_NAME_DEPTH );
00762
00763
00764 }
00765
00766 if ( task == NIP_MDNS_TASK_LEARN )
00767 {
00768
00769 l->stat |= NIP_MDNS_CSTAT_LEARNED;
00770 }
00771 else if ( task == NIP_MDNS_TASK_REGUNIQUE )
00772 {
00773 l->stat = NIP_MDNS_CSTAT_PROBING;
00774 }
00775 else
00776 {
00777 l->stat = NIP_MDNS_CSTAT_ANNOUNCING;
00778 }
00779
00780
00781 nip_memcpy( &l->record, record, recsize );
00782 l->age = 0;
00783
00784
00785 nip_disp_notify( NIP_DISP_CHECK_MDNS );
00786
00787 }
00788 else if ( task == NIP_MDNS_TASK_SEARCH )
00789 {
00790 if ( res == NIP_MDNS_NO_CACHE_ID )
00791 nip_error = NIP_E_NOT_FOUND;
00792 else
00793 nip_error = NIP_E_OK;
00794 }
00795
00796 release:
00797 nip_mem_release_block( nip_mdns_cache.id );
00798
00799 quit:
00800 if ( id != NULL && res != NIP_MDNS_NO_CACHE_ID )
00801 *id = res;
00802
00803 return nip_error;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 nip_error_t nip_mdns_notify(nip_mdns_nfy_task_t task, nip_mdns_cache_id_t c_id,
00817 nip_mdns_query_id_t q_id, uint8_t nfy )
00818 {
00819 struct nip_mdns_cache_subscription *cs, *end, new;
00820 nip_mem_size_t listsize;
00821 nip_error_t res = NIP_E_OK;
00822
00823 listsize = nip_mem_buf_used( nip_mdns_cs );
00824 cs = nip_mem_obtain_ptr( nip_mdns_cs );
00825 if ( cs == NULL )
00826 {
00827 res = NIP_E_LOCKED;
00828 goto quit;
00829 }
00830
00831 end = (void*)(((uint8_t*)cs) + listsize);
00832 while ( cs < end )
00833 {
00834
00835
00836
00837
00838 if( ( (q_id & NIP_MDNS_QUERY_ID_MASK) == (cs->q_id & NIP_MDNS_QUERY_ID_MASK)
00839 && q_id != NIP_MDNS_NO_QUERY
00840 &&(c_id == cs->c_id || c_id == NIP_MDNS_NO_CACHE_ID ))
00841 || ( c_id == cs->c_id
00842 && q_id == NIP_MDNS_NO_QUERY
00843 && c_id != NIP_MDNS_NO_CACHE_ID)
00844 )
00845 {
00846 if ( task & NIP_MDNS_NFYTASK_NOTIFY )
00847 cs->q_id |= nfy;
00848
00849 if ( task == NIP_MDNS_NFYTASK_NOTIFIED )
00850 cs->q_id &= ~nfy;
00851
00852 if ( task == NIP_MDNS_NFYTASK_SUBSCRIBE )
00853 break;
00854
00855 if ( task == NIP_MDNS_NFYTASK_UNSUBSCRIBE )
00856 {
00857
00858 nip_memmove( cs, cs+1, ((uint8_t*) --end) - ((uint8_t*) cs) );
00859 listsize -= sizeof( struct nip_mdns_cache_subscription );
00860 }
00861 }
00862
00863 cs++;
00864 }
00865
00866 nip_mem_release_block( nip_mdns_cs );
00867
00868 if ( task == NIP_MDNS_NFYTASK_SUBSCRIBE && cs == end )
00869 {
00870 new.c_id = c_id;
00871 new.q_id = q_id | nfy;
00872 res = nip_mem_write( nip_mdns_cs, &new, sizeof( new ) );
00873 goto quit;
00874 }
00875
00876 if ( task == NIP_MDNS_NFYTASK_UNSUBSCRIBE )
00877 {
00878
00879 nip_mem_set_used( nip_mdns_cs, listsize );
00880 }
00881
00882 quit:
00883 return res;
00884 }
00885
00886
00887
00888
00889 nip_error_t nip_mdns_close( nip_mdns_query_id_t r_id )
00890 {
00891
00892 return NIP_E_OK;
00893 }
00894
00895
00896
00897
00898
00899
00900
00901 nip_mdns_cache_id_t nip_mdns_fetch_results( nip_mdns_query_id_t r_id )
00902 {
00903
00904 return NIP_MDNS_NO_CACHE_ID;
00905 }
00906
00907
00908
00909 nip_error_t nip_mdns_unregister( nip_mdns_cache_id_t id )
00910 {
00911
00912 return NIP_E_OK;
00913 }
00914
00915
00916
00917
00918
00919
00920 void nip_mdns_register_hostname( struct nip_dns_string *name )
00921 {
00922 nip_net_if_t *net_if = &nip_net_if_list[ nip_mdns_if_id ];
00923 struct nip_mdns_record dnsrec;
00924 nip_mem_ptr_t name_ptr = { NIP_MEM_NULL, (uint8_t*)name };
00925 #if NIP_MDNS_CREATE_IN_ADDR_ARPA_PTR == 1
00926 uint8_t name_str[8];
00927 uint8_t i,r;
00928 uint8_t part;
00929 uint8_t name_pos;
00930 #endif
00931
00932 dnsrec.type = NIP_MDNS_TYPE_A;
00933
00934 dnsrec.ttl = NIP_MDNS_DEFAULT_TTL_A;
00935
00936 dnsrec.name.part[0] = NIP_MDNS_REG_STRING( &name_ptr );
00937 dnsrec.name.part[1] = nip_mdns_domain;
00938 dnsrec.name.part[2] = NIP_MDNS_NO_NAMESTRING;
00939 nip_memcpy( dnsrec.data.a.ip_addr, net_if->ip_conf.addr, 4 );
00940
00941 if ( dnsrec.name.part[0] == NIP_MDNS_NO_NAMESTRING )
00942 {
00943 goto quit;
00944 }
00945
00946
00947 if ( nip_mdns_hostname != NIP_MDNS_NO_CACHE_ID )
00948 {
00949 nip_error = nip_mdns_unregister( nip_mdns_hostname );
00950 if ( nip_error != NIP_E_OK )
00951 goto unregister_hostname_usage;
00952 #if NIP_MDNS_CREATE_IN_ADDR_ARPA_PTR == 1
00953 nip_error = nip_mdns_unregister( nip_mdns_host_ptr );
00954 #endif
00955 }
00956
00957
00958 #if NIP_MDNS_DEFEND_HOSTNAME == 1
00959 NIP_MDNS_REGUNIQUE( &nip_mdns_hostname, &dnsrec );
00960 #else
00961 NIP_MDNS_REGISTER( &nip_mdns_hostname, &dnsrec );
00962 #endif
00963
00964 unregister_hostname_usage:
00965 NIP_MDNS_UNREG_NAME( dnsrec.name.part, 1 );
00966
00967 #if NIP_MDNS_CREATE_IN_ADDR_ARPA_PTR == 1
00968
00969 if ( nip_mdns_hostname != NIP_MDNS_NO_CACHE_ID )
00970 {
00971
00972 dnsrec.data.ptr.name.part[0] = dnsrec.name.part[0];
00973 dnsrec.data.ptr.name.part[1] = dnsrec.name.part[1];
00974 dnsrec.data.ptr.name.part[2] = dnsrec.name.part[2];
00975 part = 0;
00976
00977 do
00978 {
00979 name_ptr.ptr = name_str;
00980
00981 if ( part < 4 )
00982 {
00983 i = NIP_IP_ADDR( nip_mdns_if_id )[3-part];
00984 if ( i>=100 ) name_pos = 3;
00985 else if ( i>=10 ) name_pos = 2;
00986 else name_pos = 1;
00987 name_str[0] = name_pos;
00988 do {
00989 r = i%10;
00990 name_str[ name_pos-- ] = '0'+r;
00991 } while ((i/=10) != 0);
00992 }
00993 else if ( part == 4 )
00994 {
00995
00996 name_str[0] = 7;
00997 name_str[1] = 'i';
00998 name_str[2] = 'n';
00999 name_str[3] = '-';
01000 name_str[4] = 'a';
01001 name_str[5] = 'd';
01002 name_str[6] = 'd';
01003 name_str[7] = 'r';
01004 }
01005 else if ( part == 5 )
01006 {
01007
01008 name_str[0] = 4;
01009 name_str[1] = 'a';
01010 name_str[2] = 'r';
01011 name_str[3] = 'p';
01012 name_str[4] = 'a';
01013 }
01014 dnsrec.name.part[ part ] = NIP_MDNS_REG_STRING( &name_ptr );
01015 if ( dnsrec.name.part[ part ] == NIP_MDNS_NO_NAMESTRING )
01016 goto unregister_ptrname_usage;
01017 } while (++part < 6 );
01018
01019 dnsrec.type = NIP_MDNS_TYPE_PTR;
01020 dnsrec.ttl = NIP_MDNS_DEFAULT_TTL_A;
01021
01022
01023 NIP_MDNS_REGUNIQUE( &nip_mdns_host_ptr, &dnsrec );
01024
01025
01026 unregister_ptrname_usage:
01027 NIP_MDNS_UNREG_NAME( dnsrec.name.part, 6 );
01028 }
01029 #endif
01030
01031
01032
01033 quit:
01034 return;
01035 }
01036
01037
01038
01039 void nip_mdns_interface_up( nip_net_if_id_t if_id )
01040 {
01041
01042 nip_mdns_if_id = if_id;
01043 nip_mdns.stat = NIP_MDNS_STAT_INIT;
01044
01045
01046 NIP_MDNS_RESET_CACHE();
01047
01048 nip_disp_notify( NIP_DISP_CHECK_MDNS );
01049
01050 }
01051
01052 void nip_mdns_interface_down( void )
01053 {
01054
01055
01056
01057
01058
01059 nip_udp_close( nip_mdns_sock );
01060
01061
01062 nip_mdns_if_id = NIP_NET_NO_IF;
01063 nip_mdns.stat = NIP_MDNS_STAT_DOWN;
01064 }
01065
01066 void nip_mdns_disp_check_cache( void )
01067 {
01068 nip_mem_size_t listsize;
01069 nip_mdns_record_size_t csize;
01070 struct nip_mdns_cache *l;
01071 struct nip_mdns_cache c;
01072 nip_mdns_query_id_t q_id;
01073 nip_mdns_query_type_t q_type;
01074 uint8_t *item, *pstart, *name, i;
01075 nip_mem_size_t pstart_off;
01076 nip_mem_ptr_t item_ptr, name_ptr;
01077 nip_error_t res;
01078 nip_mdns_type_t rtype;
01079
01080
01081 listsize = nip_mem_buf_used( nip_mdns_cache.id );
01082
01083
01084 while ( (nip_mem_size_t)nip_mdns_cache.ptr < listsize )
01085 {
01086 l = nip_mem_ptr( &nip_mdns_cache );
01087 if ( l == NULL )
01088 goto quit;
01089
01090 csize = nip_mdns_record_size( &l->record ) + NIP_MDNS_BASE_CACHE_SIZE;
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 nip_memcpy( &c, l, csize);
01105
01106 nip_mem_release_ptr( &nip_mdns_cache );
01107
01108
01109
01110 if ( c.stat & NIP_MDNS_CSTAT_AUTH_BIT
01111 && nip_mdns.recv & NIP_MDNS_PTYPE_QUERY )
01112 {
01113
01114
01115 nip_udp_data_mem_ptr( nip_mdns_sock, NIP_UDP_RX_BUF, &item_ptr );
01116 pstart_off = (nip_mem_size_t)item_ptr.ptr;
01117
01118
01119 do
01120 {
01121 res = nip_mdns_parse_packet(
01122 NIP_UDP_RX_BUF,
01123 NIP_MDNS_PTASK_NEXT_ITEM,
01124 &item_ptr,
01125 NIP_MDNS_QDCOUNT_OFFSET );
01126
01127 pstart = nip_udp_data_ptr( nip_mdns_sock, NIP_UDP_RX_BUF );
01128
01129 if ( res == NIP_E_OK && pstart != NULL)
01130 {
01131
01132 item = pstart + (nip_mem_size_t)item_ptr.ptr - pstart_off;
01133 name = item;
01134 i = 0;
01135 name_ptr.id = NIP_MEM_NULL;
01136
01137 do
01138 {
01139 name_ptr.ptr = name;
01140
01141
01142 if ( *name & 0xC0 )
01143 {
01144
01145 name = pstart + ((name[0]&0x3F)<<8) + name[1];
01146 }
01147
01148 else if ( *name == 0x00 )
01149 {
01150 if ( (c.record.name.part[i] != NIP_MDNS_NO_NAMESTRING
01151 && i != NIP_MDNS_MAX_NAME_DEPTH - 1 )
01152 || i >= NIP_MDNS_MAX_NAME_DEPTH )
01153 res = NIP_E_NO_MATCH;
01154 }
01155 else
01156 {
01157
01158 if ( i >= NIP_MDNS_MAX_NAME_DEPTH
01159 || NIP_MDNS_CHECK_NAME( &name_ptr ) != c.record.name.part[i] )
01160 res = NIP_E_NO_MATCH;
01161 name += *name + 1;
01162 i++;
01163 }
01164
01165 if ( *item < 0xC0 && *item != 0x00)
01166 item += *item + 1;
01167
01168
01169
01170 if ( name >= pstart - pstart_off + nip_mdns.recv_size )
01171 {
01172 res = NIP_E_EOF;
01173 }
01174
01175 } while ( *name != 0x00 && res == NIP_E_OK );
01176 if (*item == 0x00 ) item++;
01177 else if (*item & 0xC0 ) item+=2;
01178
01179
01180 rtype = ntohs(*(uint16_t*)item);
01181 if ( (rtype != c.record.type && rtype != NIP_MDNS_TYPE_ANY )
01182 || item[3] != NIP_DNS_CLASS_IN )
01183 {
01184 res = NIP_E_NO_MATCH;
01185 }
01186
01187
01188 }
01189
01190
01191 nip_udp_ptr_release( nip_mdns_sock, NIP_UDP_RX_BUF );
01192
01193 if ( res == NIP_E_OK )
01194 {
01195
01196 q_id = nip_mdns_query( NIP_MDNS_QTYPE_REMOTE, &c.record.name, c.record.type );
01197 if ( q_id != NIP_MDNS_NO_QUERY )
01198 {
01199
01200 NIP_MDNS_SUBSCRIBE_REMOTE( c.id, q_id );
01201 }
01202 }
01203
01204 } while ( res != NIP_E_EOF );
01205
01206
01207
01208
01209
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219 if ( c.stat == NIP_MDNS_CSTAT_PROBING
01220 || NIP_MDNS_GET_AUTH_CSTAT( &c ) == NIP_MDNS_CSTAT_ANNOUNCING)
01221 {
01222
01223 if( c.age < NIP_MDNS_PROBE_COUNT + NIP_MDNS_ANNOUNCE_COUNT )
01224 {
01225 q_type = NIP_MDNS_QTYPE_PROBE;
01226 if ( c.age >= NIP_MDNS_PROBE_COUNT )
01227 {
01228 q_type = NIP_MDNS_QTYPE_ANNOUNCE;
01229 if ( c.stat == NIP_MDNS_CSTAT_PROBING )
01230 c.stat = NIP_MDNS_CSTAT_ANNOUNCING;
01231
01232 }
01233
01234 q_id = nip_mdns_query( q_type, &c.record.name, NIP_MDNS_TYPE_ANY );
01235
01236 if ( q_id != NIP_MDNS_NO_QUERY
01237 && NIP_MDNS_SUBSCRIBE_REMOTE( c.id, q_id ) == NIP_E_OK )
01238 {
01239
01240 c.age++;
01241 }
01242 }
01243 else
01244 {
01245 NIP_MDNS_SET_AUTH_CSTAT( &c, NIP_MDNS_CSTAT_UNIQUE_AUTH );
01246 }
01247 }
01248
01249
01250 l = nip_mem_ptr( &nip_mdns_cache );
01251 if ( l == NULL )
01252 goto quit;
01253
01254 nip_memcpy( l, &c, csize );
01255 nip_mem_release_block( nip_mdns_cache.id );
01256
01257
01258
01259
01260
01261 nip_mdns_cache.ptr = (void*)((nip_mem_size_t)nip_mdns_cache.ptr + csize);
01262 }
01263
01264
01265 nip_mdns_cache.ptr = (void*)0;
01266
01267 quit:
01268 nip_mdns.stat = NIP_MDNS_STAT_QUERY_CHECK;
01269 NIP_CURR_CMD = &nip_mdns_disp_check_queries;
01270 return;
01271 }
01272
01273
01274
01275
01276
01277
01278
01279
01280 nip_error_t nip_mdns_tx_init( nip_mdns_packet_type_t ptype )
01281 {
01282 struct nip_dns_header *header;
01283 nip_error_t res = NIP_E_OK;
01284
01285 if ( nip_mdns.send == NIP_MDNS_PTYPE_NONE
01286 || ( nip_mdns.send == NIP_MDNS_PTYPE_ANSWCONTINUED
01287 && ptype == NIP_MDNS_PTYPE_QUERY ))
01288 {
01289 res = nip_udp_init_send ( nip_mdns_sock, NIP_DNS_HSIZE );
01290 res = nip_udp_write ( nip_mdns_sock, NULL, NIP_DNS_HSIZE );
01291 header = nip_udp_data_ptr ( nip_mdns_sock, NIP_UDP_TX_BUF );
01292 if ( res != NIP_E_OK || header == NULL )
01293 {
01294
01295 nip_udp_cancel_send( nip_mdns_sock );
01296 res = NIP_E_AGAIN;
01297 goto quit;
01298 }
01299 if ( nip_mdns.send != NIP_MDNS_PTYPE_ANSWCONTINUED )
01300 nip_mdns.send = ptype;
01301
01302 if ( ptype == NIP_MDNS_PTYPE_RESPONSE )
01303 {
01304 header->qr_opcode_aa_tc_rd = ( NIP_DNS_QR_MASK | NIP_DNS_AA_MASK );
01305 }
01306 nip_udp_ptr_release( nip_mdns_sock, NIP_UDP_TX_BUF );
01307 } else
01308 if ( ptype != nip_mdns.send )
01309 res = NIP_E_AGAIN;
01310
01311 quit:
01312 return res;
01313 }
01314
01315
01316
01317
01318
01319 nip_error_t nip_mdns_tx_name( nip_mem_ptr_t *dst, struct nip_mdns_name *rr_name,
01320 nip_mdns_type_t rr_type, uint8_t uclass_byte )
01321 {
01322 nip_error_t res;
01323 nip_mem_ptr_t typeclass_ptr;
01324 uint8_t typeclass[4];
01325
01326
01327 res = NIP_MDNS_WRITE_NAME( rr_name->part, NIP_MDNS_MAX_NAME_DEPTH, dst );
01328 if ( res != NIP_E_OK )
01329 goto quit;
01330
01331 typeclass[0] = 0;
01332 typeclass[1] = rr_type;
01333 typeclass[2] = uclass_byte;
01334 typeclass[3] = NIP_DNS_CLASS_IN;
01335 typeclass_ptr.id = NIP_MEM_NULL;
01336 typeclass_ptr.ptr = typeclass;
01337
01338
01339 res = nip_mem_insert( dst, &typeclass_ptr, 4 );
01340
01341
01342
01343 quit:
01344 return res;
01345 }
01346
01347 void nip_mdns_transmit( void )
01348 {
01349 struct nip_udp_sock_addr addr;
01350
01351
01352 addr.port = NIP_UDP_PORT_MDNS;
01353 addr.ip[0] = NIP_MDNS_ADDR0;
01354 addr.ip[1] = NIP_MDNS_ADDR1;
01355 addr.ip[2] = NIP_MDNS_ADDR2;
01356 addr.ip[3] = NIP_MDNS_ADDR3;
01357
01358
01359 if ( nip_udp_transmit( nip_mdns_sock, &addr, nip_mdns_if_id ) == NIP_E_OK )
01360 {
01361 nip_mdns.send = NIP_MDNS_PTYPE_NONE;
01362 }
01363
01364 }
01365
01366
01367
01368
01369
01370
01371 nip_error_t nip_mdns_parse_packet( nip_udp_buf_type_t udp_buffer,
01372 nip_mdns_packet_task_t task, nip_mem_ptr_t *p, nip_mdns_qa_offset_t section )
01373 {
01374 uint8_t *pos, len, *end;
01375 uint16_t count;
01376 nip_error_t res = NIP_E_OK;
01377 nip_mem_ptr_t ptmp;
01378 struct nip_dns_header *header;
01379 nip_mem_size_t pstart_off, bufsize;
01380 nip_mdns_qa_offset_t sec = 0;
01381
01382 nip_udp_data_mem_ptr( nip_mdns_sock, udp_buffer, &ptmp );
01383
01384 bufsize = nip_mem_buf_used( ptmp.id );
01385 header = nip_mem_ptr( &ptmp );
01386 pstart_off = (nip_mem_size_t)ptmp.ptr;
01387 if ( header == NULL )
01388 {
01389 res = nip_error;
01390 goto quit;
01391 }
01392
01393
01394 pos = (uint8_t*)(header+1);
01395 end = (uint8_t*)(header) + bufsize;
01396
01397
01398 if ( task == NIP_MDNS_PTASK_SET_TC )
01399 {
01400 header->qr_opcode_aa_tc_rd |= NIP_DNS_TC_MASK;
01401 goto release;
01402 }
01403
01404
01405
01406 do
01407 {
01408
01409 count = ntohs( header->qa_count[ sec ] );
01410
01411
01412 if ( sec == section )
01413 {
01414 if ( task == NIP_MDNS_PTASK_SECTION_PTR )
01415 {
01416 goto release;
01417 }
01418 if ( task == NIP_MDNS_PTASK_INC_COUNTER )
01419 {
01420 header->qa_count[ section ] = htons( count+1 );
01421 goto release;
01422 }
01423 }
01424
01425
01426 while ( count > 0 )
01427 {
01428 ptmp.ptr = (void*)(pstart_off + pos - (uint8_t*)header);
01429
01430 if ( task == NIP_MDNS_PTASK_NEXT_ITEM && ptmp.ptr > p->ptr)
01431 goto release;
01432
01433
01434 do
01435 {
01436
01437 len = *pos;
01438 if ( len >= 0xC0 ) { pos += 2; break; }
01439 if ( len == 0x00 ) { pos += 1; break; }
01440
01441 if ( pos >= end )
01442 {
01443 res = NIP_E_EOF;
01444 goto release;
01445 }
01446 } while ( pos+=len+1 );
01447
01448
01449 pos += 4;
01450
01451
01452 if ( sec != NIP_MDNS_QDCOUNT_OFFSET )
01453 {
01454
01455 pos += 4;
01456
01457 pos += 2 + *pos;
01458 }
01459
01460
01461 if ( pos >= end )
01462 {
01463 res = NIP_E_EOF;
01464 goto release;
01465 }
01466 count--;
01467 }
01468
01469 if ( task == NIP_MDNS_PTASK_NEXT_ITEM && sec == section )
01470 {
01471
01472 res = NIP_E_EOF;
01473 goto release;
01474 }
01475
01476 } while ( ++sec < NIP_MDNS_QA_COUNTERS_NUMBER );
01477
01478 release:
01479 nip_mem_release_ptr( &ptmp );
01480
01481
01482 if ( p != NULL && res == NIP_E_OK )
01483 {
01484 p->id = ptmp.id;
01485 p->ptr = (void*)(pstart_off + pos - (uint8_t*)header);
01486 }
01487
01488 quit:
01489 return res;
01490 }
01491
01492
01493
01494
01495
01496
01497 void nip_mdns_disp_check_queries( void )
01498 {
01499 nip_mem_size_t listsize;
01500 struct nip_mdns_query *l;
01501 struct nip_mdns_query q;
01502 struct nip_mdns_record r;
01503 uint8_t count = 0;
01504 nip_error_t res = NIP_E_OK;
01505 nip_mem_ptr_t cs_ptr, insert_ptr, src_ptr;
01506 nip_mem_size_t section_off, head_off, len;
01507 nip_mdns_packet_type_t ptype;
01508 nip_mdns_qa_offset_t answer_section;
01509 nip_mdns_cache_id_t c_id;
01510 uint8_t name_flag;
01511
01512 struct {
01513 uint16_t ttl[2];
01514 uint16_t len;
01515 } data_header;
01516 struct nip_mdns_cache_subscription *cs;
01517
01518 while ( (l = nip_mem_ptr( &nip_mdns_queries )) != NULL )
01519 {
01520
01521 nip_memcpy( &q, l, sizeof( struct nip_mdns_query ));
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 nip_mem_release_ptr( &nip_mdns_queries );
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547 answer_section = NIP_MDNS_QDCOUNT_OFFSET;
01548 if ( q.timer == 0 && q.type & NIP_MDNS_QTYPE_TX_BIT )
01549 {
01550
01551 if ( q.type == NIP_MDNS_QTYPE_PROBE )
01552 {
01553 ptype = NIP_MDNS_PTYPE_PROBE;
01554 answer_section = NIP_MDNS_NSCOUNT_OFFSET;
01555 }
01556 else
01557 {
01558 ptype = NIP_MDNS_PTYPE_QUERY;
01559 answer_section = NIP_MDNS_ANCOUNT_OFFSET;
01560 }
01561
01562
01563 res = nip_mdns_tx_init( ptype );
01564
01565 if ( res == NIP_E_OK )
01566 {
01567
01568 nip_mdns_parse_packet(
01569 NIP_UDP_TX_BUF,
01570 NIP_MDNS_PTASK_SECTION_PTR,
01571 &insert_ptr,
01572 NIP_MDNS_QDCOUNT_OFFSET );
01573
01574
01575 if ( nip_mdns.send != NIP_MDNS_PTYPE_ANSWCONTINUED )
01576 {
01577
01578 if ( insert_ptr.id == NIP_MEM_NULL )
01579 goto quit;
01580 res = nip_mdns_tx_name( &insert_ptr, &q.rr_name, q.rr_type, 0 );
01581 if ( res != NIP_E_OK )
01582 goto quit;
01583
01584 nip_mdns_parse_packet(
01585 NIP_UDP_TX_BUF,
01586 NIP_MDNS_PTASK_INC_COUNTER,
01587 &insert_ptr,
01588 NIP_MDNS_QDCOUNT_OFFSET );
01589 count++;
01590 }
01591 else
01592 {
01593
01594
01595 nip_mdns.send = NIP_MDNS_PTYPE_QUERY;
01596 }
01597 }
01598 else
01599 {
01600
01601 answer_section = NIP_MDNS_QDCOUNT_OFFSET;
01602 }
01603 }
01604 cs_ptr.id = nip_mdns_cs;
01605 cs_ptr.ptr = (void*)0;
01606 src_ptr.id = NIP_MEM_NULL;
01607
01608
01609 if ( answer_section != NIP_MDNS_QDCOUNT_OFFSET
01610 || ( q.type & NIP_MDNS_QTYPE_REMOTE
01611 && (res = nip_mdns_tx_init( NIP_MDNS_PTYPE_RESPONSE )) == NIP_E_OK
01612 && (answer_section = NIP_MDNS_ANCOUNT_OFFSET) )
01613 )
01614 {
01615
01616 nip_mdns_parse_packet(
01617 NIP_UDP_TX_BUF,
01618 NIP_MDNS_PTASK_SECTION_PTR,
01619 &insert_ptr,
01620 answer_section );
01621
01622
01623 section_off = (nip_mem_size_t)insert_ptr.ptr;
01624
01625
01626
01627
01628 while ( (cs = nip_mem_ptr( &cs_ptr )) != NULL )
01629 {
01630
01631
01632
01633 c_id = NIP_MDNS_NO_CACHE_ID;
01634 if((cs->q_id & NIP_MDNS_NFY_REMOTE)
01635 && (cs->q_id & NIP_MDNS_QUERY_ID_MASK) == (q.id & NIP_MDNS_QUERY_ID_MASK))
01636 {
01637 c_id = cs->c_id;
01638 }
01639 nip_mem_release_block( nip_mdns_cs );
01640 if ( c_id == NIP_MDNS_NO_CACHE_ID )
01641 goto next_cs;
01642
01643 insert_ptr.ptr = (void*)section_off;
01644 len = 0;
01645
01646
01647 res = nip_mdns_cache_task( nip_mdns.send == NIP_MDNS_PTYPE_QUERY
01648 ? NIP_MDNS_TASK_GET_LEARNED
01649 : NIP_MDNS_TASK_GET
01650 , &c_id, &r );
01651 if ( res != NIP_E_OK )
01652 goto answer_abort;
01653
01654
01655 name_flag = 0;
01656 if ( q.type == NIP_MDNS_QTYPE_ANNOUNCE )
01657 name_flag = NIP_DNS_CF_FLAG;
01658 res = nip_mdns_tx_name( &insert_ptr, &r.name, r.type, name_flag );
01659 if ( res != NIP_E_OK )
01660 goto answer_abort;
01661
01662
01663 head_off = (nip_mem_size_t)insert_ptr.ptr;
01664
01665
01666
01667 src_ptr.id = NIP_MEM_NULL;
01668 src_ptr.ptr = (uint8_t*)&r.data;
01669 if ( r.type == NIP_MDNS_TYPE_A )
01670 {
01671 len = 4;
01672 }
01673 else
01674 if ( r.type == NIP_MDNS_TYPE_SRV )
01675 {
01676 len = 6;
01677 r.data.srv.priority = htons( r.data.srv.priority );
01678 r.data.srv.weight = htons( r.data.srv.weight );
01679 r.data.srv.port = r.data.srv.port;
01680 }
01681 else
01682 if ( r.type == NIP_MDNS_TYPE_PTR )
01683 {
01684 res = NIP_MDNS_WRITE_NAME( r.data.ptr.name.part, NIP_MDNS_MAX_NAME_DEPTH, &insert_ptr );
01685 if ( res != NIP_E_OK )
01686 goto answer_abort;
01687 }
01688 else
01689 {
01690
01691 src_ptr.id = r.data.oth.string;
01692 src_ptr.ptr = (void*)0;
01693 len = nip_mem_buf_used( r.data.oth.string );
01694 }
01695
01696 res = nip_mem_insert( &insert_ptr, &src_ptr, len );
01697 if ( res != NIP_E_OK )
01698 {
01699 len = 0;
01700 goto answer_abort;
01701 }
01702
01703 if ( r.type == NIP_MDNS_TYPE_SRV )
01704 {
01705
01706 res = NIP_MDNS_WRITE_NAME( r.data.srv.target.part, NIP_MDNS_MAX_NAME_DEPTH, &insert_ptr );
01707 if ( res != NIP_E_OK )
01708 goto answer_abort;
01709 }
01710
01711
01712 len = (nip_mem_size_t)insert_ptr.ptr-head_off;
01713 data_header.ttl[0] = 0;
01714 data_header.ttl[1] = htons( r.ttl );
01715 data_header.len = htons( len );
01716 insert_ptr.ptr = (void*)head_off;
01717 src_ptr.id = NIP_MEM_NULL;
01718 src_ptr.ptr = (uint8_t*)&data_header;
01719 res = nip_mem_insert( &insert_ptr, &src_ptr, sizeof( data_header ) );
01720 if ( res != NIP_E_OK )
01721 goto answer_abort;
01722
01723
01724 nip_mdns_parse_packet( NIP_UDP_TX_BUF, NIP_MDNS_PTASK_INC_COUNTER, &insert_ptr, answer_section );
01725 count++;
01726
01727
01728 NIP_MDNS_QUERY_NOTIFIED( c_id, q.id );
01729
01730 next_cs:
01731
01732 cs_ptr.ptr += sizeof( struct nip_mdns_cache_subscription );
01733 }
01734 goto query_done;
01735
01736 answer_abort:
01737
01738 len += (nip_mem_size_t)insert_ptr.ptr - section_off;
01739 insert_ptr.ptr = (void*) section_off;
01740 nip_mem_cut( &insert_ptr, len );
01741
01742
01743 if ( nip_mdns.send == NIP_MDNS_PTYPE_QUERY )
01744 {
01745 nip_mdns.send = NIP_MDNS_PTYPE_ANSWCONTINUED;
01746
01747
01748 nip_mdns_parse_packet( NIP_UDP_TX_BUF, NIP_MDNS_PTASK_SET_TC, &insert_ptr, 0 );
01749 }
01750 goto quit;
01751
01752 }
01753
01754 query_done:
01755
01756
01757
01758 if ( !(q.type & NIP_MDNS_QTYPE_LOCAL_BIT ) )
01759 {
01760 if ( NIP_E_OK == nip_mem_cut( &nip_mdns_queries, sizeof( struct nip_mdns_query ) ))
01761 {
01762
01763 NIP_MDNS_UNSUBSCRIBE_QUERY( q.id );
01764 }
01765 else
01766 {
01767
01768 goto quit;
01769 }
01770 }
01771 else
01772 {
01773
01774 l = nip_mem_ptr( &nip_mdns_queries );
01775 if ( l == NULL )
01776 {
01777 nip_error = NIP_E_LOCKED;
01778 goto quit;
01779 }
01780 nip_memcpy( l, &q, sizeof( struct nip_mdns_query ));
01781 nip_mem_release_ptr( &nip_mdns_queries );
01782
01783
01784
01785 nip_mdns_queries.ptr = (void*)((nip_mem_size_t)nip_mdns_queries.ptr + sizeof( struct nip_mdns_query ));
01786 }
01787 }
01788
01789
01790 listsize = nip_mem_buf_used( nip_mdns_queries.id );
01791 if ( (nip_mem_size_t) nip_mdns_queries.ptr == listsize )
01792 {
01793
01794 nip_mdns_queries.ptr = NULL;
01795
01796
01797 nip_mdns.stat = NIP_MDNS_STAT_UP;
01798 }
01799
01800
01801 if ( nip_mdns.recv & NIP_MDNS_PTYPE_RESPONSE )
01802 {
01803 nip_udp_cancel_recv( nip_mdns_sock );
01804 nip_mdns.recv = NIP_MDNS_PTYPE_NONE;
01805 }
01806
01807 quit:
01808 #if NIP_MDNS_DISCARD_ON_OUT_OF_MEMORY == 1
01809 if ( res == NIP_E_OUT_OF_MEMORY
01810 && count == 0
01811 && nip_mdns.recv != NIP_MDNS_PTYPE_NONE )
01812 {
01813
01814 nip_udp_cancel_recv( nip_mdns_sock );
01815 nip_mdns.recv = NIP_MDNS_PTYPE_NONE;
01816
01817
01818 nip_disp_notify( NIP_DISP_CHECK_MDNS );
01819 }
01820 #endif
01821
01822 if ( nip_mdns.send != NIP_MDNS_PTYPE_NONE )
01823 {
01824
01825 if ( count > 0 )
01826 NIP_CURR_CMD = &nip_mdns_transmit;
01827 else
01828 {
01829 nip_udp_cancel_send( nip_mdns_sock );
01830 nip_mdns.send = NIP_MDNS_PTYPE_NONE;
01831 }
01832 }
01833 return;
01834 }
01835
01836
01837
01838 void nip_mdns_disp_check( void )
01839 {
01840 struct nip_dns_header *header;
01841 struct nip_udp_sock_addr rem_addr;
01842
01843
01844 if ( ( nip_mdns.stat == NIP_MDNS_STAT_DOWN )
01845 || ( nip_mdns.stat == NIP_MDNS_STAT_INIT
01846 && nip_mdns_init() != NIP_E_OK )
01847 )
01848 {
01849
01850 while ( nip_mdns_sock != NIP_UDP_NO_SOCKET
01851 && nip_udp_recvfrom( nip_mdns_sock, NULL, 0, NULL ) > 0 )
01852 {
01853 nip_udp_cancel_recv( nip_mdns_sock );
01854 }
01855 return;
01856 }
01857
01858
01859 if ( nip_mdns.stat != NIP_MDNS_STAT_QUERY_CHECK
01860 && nip_mdns.stat != NIP_MDNS_STAT_CACHE_CHECK
01861 && nip_mdns.recv != NIP_MDNS_PTYPE_NONE )
01862 {
01863 nip_udp_cancel_recv( nip_mdns_sock );
01864 nip_mdns.recv = NIP_MDNS_PTYPE_NONE;
01865 }
01866
01867
01868 if ( nip_mdns.recv == NIP_MDNS_PTYPE_NONE )
01869 {
01870 do
01871 {
01872
01873 nip_mdns.recv_size = nip_udp_recvfrom( nip_mdns_sock, NULL, 0, &rem_addr );
01874
01875 if ( nip_mdns.recv_size > 0 )
01876 {
01877
01878
01879
01880
01881 if ( nip_mdns.recv_size < sizeof( struct nip_dns_header ) )
01882 {
01883 goto discard;
01884 }
01885
01886 header = nip_udp_data_ptr( nip_mdns_sock, NIP_UDP_RX_BUF );
01887
01888 if ( header == NULL )
01889 break;
01890
01891
01892 if ( (header->qr_opcode_aa_tc_rd & NIP_DNS_QR_MASK) > 0 )
01893 nip_mdns.recv = NIP_MDNS_PTYPE_RESPONSE;
01894 else
01895 {
01896 if ( header->qa_count[ NIP_MDNS_QDCOUNT_OFFSET ] != 0
01897 && header->qa_count[ NIP_MDNS_NSCOUNT_OFFSET ] != 0 )
01898 nip_mdns.recv = NIP_MDNS_PTYPE_PROBE;
01899 else
01900 nip_mdns.recv = NIP_MDNS_PTYPE_QUERY;
01901 }
01902
01903
01904
01905 if ( (header->qr_opcode_aa_tc_rd & NIP_DNS_OP_MASK) > 0
01906 || (header->ra_z_ad_cd_rcode & NIP_DNS_RC_MASK) > 0
01907 || ( nip_mdns.recv == NIP_MDNS_PTYPE_PROBE
01908 && nip_memcmp( NIP_IP_ADDR( nip_mdns_if_id ), rem_addr.ip, 4 ) == 0 )
01909 )
01910 {
01911 nip_udp_ptr_release( nip_mdns_sock, NIP_UDP_RX_BUF );
01912 goto discard;
01913 }
01914
01915
01916 nip_udp_ptr_release( nip_mdns_sock, NIP_UDP_RX_BUF );
01917 }
01918
01919 continue;
01920
01921 discard:
01922 nip_mdns.recv = NIP_MDNS_PTYPE_NONE;
01923 nip_udp_cancel_recv( nip_mdns_sock );
01924
01925
01926 } while ( nip_mdns.recv == NIP_MDNS_PTYPE_NONE && nip_mdns.recv_size > 0 );
01927 }
01928
01929 if ( nip_mdns.stat == NIP_MDNS_STAT_QUERY_CHECK )
01930 {
01931 NIP_CURR_CMD = &nip_mdns_disp_check_queries;
01932 goto moveon;
01933 }
01934
01935
01936 NIP_CURR_CMD = &nip_mdns_disp_check_cache;
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957 moveon:
01958 return;
01959
01960 }
01961
01962
01963 #endif