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 "dispatcher.h"
00032 #include "inet.h"
00033 #include "os_core.h"
00034 #include "net/net_if.h"
00035 #include "net/arp.h"
00036 #include "net/ip.h"
00037 #include "net/udp.h"
00038 #include "app/dhcp.h"
00039 #include "net/autoip.h"
00040 #include "net/tcp.h"
00041 #include "app/mdns.h"
00042
00043 uint16_t nip_ipv4_id;
00044 uint8_t nip_ip_localhost[4] = {127,0,0,1};
00045 uint8_t nip_ip_broadcast[4] = {255,255,255,255};
00046 uint8_t nip_ip_null[4] = {0,0,0,0};
00047
00048 #if (NIP_IP_ENABLE == 1)
00049
00050 #if (NIP_MULTICAST_ENABLE == 1)
00051 uint8_t nip_ip_all_hosts[4] = {124,0,0,1};
00052 #if ( NIP_IP_MAX_HOST_GROUPS == 1 )
00053 struct nip_ip_group_membership nip_ip_group;
00054 #else
00055 struct nip_ip_group_membership nip_ip_groups[ NIP_IP_MAX_HOST_GROUPS ];
00056 #endif
00057 #endif
00058
00059
00060 #if (NIP_ICMP_ENABLE == 1) && defined ( NIP_ICMP_TEST_NO_MEM_MGR )
00061 struct ICMP_HEADER nip_test_no_mem_icmp;
00062 #endif
00063
00064
00065 void nip_ip_disp_deliver( void );
00066
00067
00068
00069
00070
00071
00072 uint16_t nip_internet_checksum( uint16_t *buf, uint16_t size )
00073 {
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 uint16_t sum = 0;
00111 size /= 2;
00112 do
00113 {
00114 sum += *buf;
00115 if ( sum < *buf ) sum++;
00116 buf++;
00117 } while ( --size > 0 );
00118 return ~sum;
00119 }
00120
00121
00122
00123
00124
00125
00126 void nip_ip_subnet_set( nip_net_if_id_t if_id, uint8_t *mask )
00127 {
00128 nip_net_if_t *net_if = &nip_net_if_list[ if_id ];
00129 uint8_t i;
00130
00131
00132 nip_memcpy( net_if->ip_conf.subnet_mask, mask, 4 );
00133
00134
00135 i = 0;
00136 do
00137 {
00138 net_if->ip_conf.brdcst_addr[i] = net_if->ip_conf.addr[i] | ~net_if->ip_conf.subnet_mask[i];
00139 } while ( ++i < 4 );
00140 }
00141
00142
00143
00144
00145 void nip_ip_down( nip_net_if_id_t if_id )
00146 {
00147 nip_net_if_t *net_if = &nip_net_if_list[ if_id ];
00148
00149
00150
00151
00152
00153 #if NIP_MDNS_ENABLE == 1
00154 nip_mdns_interface_down();
00155 #endif
00156
00157 net_if->ip_conf.state = NIP_IP_CONF_STAT_UNCONFIGURED;
00158 }
00159
00160
00161
00162
00163 void nip_ip_up( nip_net_if_id_t if_id )
00164 {
00165
00166
00167 #if NIP_IGMP_ENABLE == 1
00168 nip_ip_query_groups( if_id );
00169 #endif
00170
00171
00172 #if NIP_MDNS_ENABLE == 1
00173 nip_mdns_interface_up( if_id );
00174 #endif
00175
00176 }
00177
00178
00179
00180
00181
00182
00183 void nip_ip_addr_set( nip_net_if_id_t if_id, uint8_t *addr )
00184 {
00185 nip_net_if_t *net_if = &nip_net_if_list[ if_id ];
00186
00187
00188 if ( nip_memcmp( addr, net_if->ip_conf.addr, 4 ) != 0 )
00189 {
00190 nip_ip_down( if_id );
00191
00192 nip_memcpy( net_if->ip_conf.addr, addr, 4 );
00193
00194
00195 nip_memset( net_if->ip_conf.subnet_mask, 0, 4 );
00196 net_if->ip_conf.subnet_mask[0] = 255;
00197 if ( (addr[0] & 0x80) == 0x80 )
00198 net_if->ip_conf.subnet_mask[1] = 255;
00199 if ( (addr[0] & 0xC0) == 0xC0 )
00200 net_if->ip_conf.subnet_mask[2] = 255;
00201
00202
00203 nip_ip_subnet_set( if_id, net_if->ip_conf.subnet_mask );
00204
00205
00206 net_if->ip_conf.state = NIP_IP_CONF_STAT_CONFIGURED;
00207
00208
00209 if ( net_if->phy_conf.flags & NIP_PHY_IFF_UP )
00210 {
00211 nip_ip_up( if_id );
00212 }
00213 }
00214 }
00215
00216
00217
00218 void nip_ip_addr_autoconf( nip_net_if_id_t if_id )
00219 {
00220
00221 nip_ip_down( if_id );
00222
00223 #if NIP_DHCP_ENABLE == 1
00224 nip_dhcp_start( if_id );
00225 #endif
00226 #if NIP_AUTOIP_ENABLE == 1
00227 nip_autoip_start( if_id );
00228 #endif
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 nip_net_if_trans_t *nip_ip_route( uint8_t *target_addr, nip_net_if_id_t if_id,
00257 nip_net_if_trans_t *trans )
00258 {
00259 nip_net_if_id_t test_if = 0;
00260 nip_net_if_id_t transmit_if = NIP_NET_NO_IF;
00261 nip_net_if_id_t gateway_if = NIP_NET_NO_IF;
00262 nip_net_trans_status_t oldstat;
00263 nip_net_trans_id_t test_trans;
00264 uint8_t cnt,i,b,l;
00265 uint8_t *local_addr = NULL;
00266 uint8_t *gateway;
00267 nip_if_ip_conf_t *ip;
00268 #if NIP_MULTICAST_ENABLE == 1 && NIP_IP_MAX_HOST_GROUPS > 1
00269 nip_host_group_id_t group;
00270 #endif
00271 #if NIP_AUTOIP_ENABLE == 1
00272 uint8_t autoip_target = 0;
00273 #endif
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 if ( trans == NULL )
00284 {
00285
00286 test_trans = 0;
00287 #if ( NIP_NET_IF_TRANS_COUNT > 1 )
00288 do
00289 {
00290 #endif
00291 trans = &nip_net_trans_list[ test_trans ];
00292
00293 #if ( NIP_NET_IF_TRANS_COUNT > 1 )
00294 if ( trans->status == NIP_NET_IF_IDLE )
00295 {
00296
00297 break;
00298 }
00299 } while ( ++test_trans < NIP_NET_MAX_TRANSMISSIONS );
00300 #endif
00301
00302 if ( test_trans >= NIP_NET_MAX_TRANSMISSIONS )
00303 {
00304
00305 nip_error = NIP_E_AGAIN;
00306 return NULL;
00307 }
00308
00309
00310 nip_memset( trans, 0, sizeof( nip_net_if_trans_t ) );
00311 }
00312
00313
00314 oldstat = trans->status;
00315 trans->status = NIP_NET_IF_ROUTING;
00316
00317
00318
00319
00320
00321 if ( target_addr[0] == 127 )
00322 {
00323 trans->flags.deliverlocal = 1;
00324 nip_memcpy( trans->params.ip.src_nw_addr, nip_ip_localhost, 4 );
00325 }
00326 else
00327 {
00328
00329
00330 #if ( NIP_NET_IF_COUNT > 1 )
00331 do
00332 {
00333 #endif // ( NIP_NET_IF_COUNT > 1 )
00334
00335
00336
00337 ip = & nip_net_if_list[ test_if ].ip_conf;
00338
00339 cnt = 0; i = 0; b = 0; l = 0;
00340
00341
00342
00343 do
00344 {
00345
00346 if ( ( target_addr[cnt] & ip->subnet_mask[cnt]) == (ip->addr[cnt] & ip->subnet_mask[cnt]) )
00347 {
00348 i++;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 if ( target_addr[cnt] == ip->brdcst_addr[cnt] ) b++;
00360
00361
00362 if ( target_addr[cnt] == ip->addr[cnt] ) l++;
00363 } while ( ++cnt < 4 );
00364
00365
00366 if ( nip_memcmp( target_addr, nip_ip_broadcast, 4 ) == 0 || b == 4 )
00367 {
00368 l = 4;
00369 }
00370
00371
00372 if ( target_addr[0] >= 0xE0 )
00373 {
00374 b = 4;
00375 #if NIP_MULTICAST_ENABLE == 1
00376 #if NIP_IP_MAX_HOST_GROUPS == 1
00377 #define GROUP_ATTRi(attr) nip_ip_group.attr
00378 #else
00379 group = 0;
00380 #define GROUP_ATTRi(attr) nip_ip_groups[group].attr
00381 do {
00382 #endif
00383 if ((GROUP_ATTRi(state) != NIP_IP_GROUP_NON
00384
00385 && nip_memcmp( GROUP_ATTRi(addr), target_addr, 4 ) == 0)
00386 || nip_memcmp( nip_ip_all_hosts, target_addr, 4 ) == 0)
00387 {
00388 l = 4;
00389 }
00390 #if NIP_IP_MAX_HOST_GROUPS != 1
00391 } while ( ++group < NIP_IP_MAX_HOST_GROUPS );
00392 #endif
00393 #endif
00394 }
00395
00396
00397
00398
00399
00400 if ( l == 4 )
00401 {
00402 trans->flags.deliverlocal = 1;
00403 nip_memcpy( trans->params.ip.src_nw_addr, ip->addr, 4 );
00404 }
00405
00406
00407
00408 if ( (if_id == NIP_NET_NO_IF || test_if == if_id) && transmit_if == NIP_NET_NO_IF )
00409 {
00410
00411 #if NIP_AUTOIP_ENABLE == 1
00412 if ( target_addr[0] == 169 && target_addr[1] == 254 )
00413 autoip_target = 1;
00414 #endif
00415
00416
00417
00418 if ( b == 4
00419 #if NIP_AUTOIP_ENABLE == 1
00420 || (autoip_target == 1 && target_addr[2] == 255 && target_addr[3] == 255)
00421 #endif
00422 )
00423 {
00424 local_addr = target_addr;
00425 transmit_if = test_if;
00426 trans->flags.ll_broadcast = 1;
00427 }
00428 else
00429 if ( i == 4
00430 #if NIP_AUTOIP_ENABLE == 1
00431
00432 || autoip_target == 1
00433 || (ip->addr[0] == 169 && ip->addr[1] == 254)
00434 #endif
00435
00436
00437 || ( if_id != NIP_NET_NO_IF && nip_memcmp( ip->addr, nip_ip_null, 4 ) == 0 ))
00438 {
00439 local_addr = target_addr;
00440 transmit_if = test_if;
00441 }
00442 else
00443
00444
00445 if ( ip->std_gateway[0] != 0 && local_addr == NULL)
00446 {
00447 gateway = ip->std_gateway;
00448 gateway_if = test_if;
00449 }
00450 }
00451
00452 #if ( NIP_NET_IF_COUNT > 1 )
00453 } while ( ++test_if < NIP_NET_IF_COUNT );
00454 #endif
00455
00456 }
00457
00458
00459 if ( transmit_if == NIP_NET_NO_IF && gateway_if != NIP_NET_NO_IF )
00460 {
00461 local_addr = gateway;
00462 transmit_if = gateway_if;
00463 }
00464
00465 if ( transmit_if != NIP_NET_NO_IF )
00466 {
00467 trans->flags.forward = 1;
00468 nip_memcpy( trans->params.ip.ll_nw_addr , local_addr , 4 );
00469 nip_memcpy( trans->params.ip.src_nw_addr, ip->addr, 4 );
00470 }
00471
00472
00473 if ( ! (trans->flags.forward || trans->flags.deliverlocal) )
00474 {
00475 trans->status = oldstat;
00476 nip_error = NIP_E_NO_ROUTE_TO_HOST;
00477 return NULL;
00478 }
00479
00480
00481
00482
00483 trans->if_id = transmit_if;
00484 nip_memcpy( trans->params.ip.dst_nw_addr, target_addr, 4 );
00485 trans->status = NIP_NET_IF_ROUTED;
00486
00487 return trans;
00488 }
00489
00490
00491
00492 void nip_ip_disp_send( void )
00493 {
00494 struct IP_HEADER head;
00495
00496 nip_net_if_trans_t *trans = nip_disp.next.common.trans;
00497 nip_net_if_id_t if_id;
00498 nip_net_if_t *net_if;
00499 nip_phy_if_t *phy;
00500 nip_if_ip_conf_t *ip;
00501 uint8_t *payload, *header;
00502 uint8_t i;
00503 uint16_t len;
00504
00505
00506 switch( trans->status )
00507 {
00508 case NIP_NET_IF_ROUTE:
00509
00510
00511 if ( NULL == nip_ip_route( trans->params.ip.dst_nw_addr, NIP_NET_NO_IF, trans ) )
00512 {
00513
00514
00515 trans->status = NIP_NET_IF_SEND_NRT;
00516 goto finish;
00517 }
00518 case NIP_NET_IF_RTS:
00519 case NIP_NET_IF_RESOLV_ADDR:
00520
00521 if ( trans->flags.forward == 0 ) goto deliverlocal;
00522
00523
00524 if_id = trans->if_id;
00525 net_if = &nip_net_if_list[ if_id ];
00526 phy = &net_if->phy_conf;
00527 ip = &net_if->ip_conf;
00528
00529
00530 if ( trans->status == NIP_NET_IF_RTS ) goto rts;
00531
00532 break;
00533 default:
00534 goto finish;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544 if ( phy->type == NIP_PHY_IF_ETH )
00545 {
00546
00547
00548
00549
00550
00551 }
00552 // broadcast
00553 else*/
00554 #if (NIP_ARP_ENABLE==1)
00555 if ( trans->flags.ll_broadcast )
00556 #endif
00557 {
00558 i = 0;
00559 do
00560 nip_disp.next.common.remote_hw_addr[i] = 0xFF;
00561 while (++i < 6 );
00562 }
00563 #if (NIP_ARP_ENABLE==1)
00564
00565 else
00566 {
00567 trans->status = NIP_NET_IF_RESOLV_ADDR;
00568 NIP_CURR_CMD = &nip_arp_disp_resolve;
00569 return;
00570 }
00571 #endif
00572 }
00573
00574 rts:
00575
00576
00577
00578
00579 len = trans->header_size + trans->payload_size + NIP_IP_DEFAULT_HEADER_SIZE;
00580
00581 head.ihl = 5;
00582 head.version = 4;
00583 head.tos = 0;
00584 head.total_length = htons( len );
00585
00586 head.id = ++nip_ipv4_id;
00587 head.frag_offset = 0;
00588 head.ttl = trans->params.ip.ttl>0 ? trans->params.ip.ttl : NIP_IP_TTL;
00589 head.protocol = trans->params.ip.protocol;
00590 head.checksum = 0x0000;
00591 nip_memcpy( head.src_addr, trans->params.ip.src_nw_addr, 4 );
00592 nip_memcpy( head.dst_addr, trans->params.ip.dst_nw_addr, 4 );
00593 head.checksum = nip_internet_checksum( (uint16_t*)&head, NIP_IP_DEFAULT_HEADER_SIZE );
00594
00595 #if (NIP_ICMP_ENABLE == 1) && defined (NIP_ICMP_TEST_NO_MEM_MGR)
00596 if ( head.protocol == NIP_IP_PROTO_ICMP )
00597 payload = (uint8_t*)&nip_test_no_mem_icmp;
00598 else
00599 #endif
00600
00601 if ( trans->payload == NIP_MEM_NULL && trans->header == NIP_MEM_NULL )
00602 {
00603
00604 goto finish;
00605 }
00606
00607 payload = nip_mem_obtain_ptr( trans->payload );
00608 if ( payload == NULL && trans->payload != NIP_MEM_NULL )
00609 goto finish;
00610
00611 header = nip_mem_obtain_ptr( trans->header );
00612 if ( header == NULL && trans->header != NIP_MEM_NULL )
00613 {
00614 nip_mem_release_block( trans->payload );
00615 goto finish;
00616 }
00617
00618 if ( payload == NULL && header == NULL )
00619 {
00620
00621 if ( nip_error == NIP_E_INVALID_BLOCK )
00622 {
00623 trans->status = NIP_NET_IF_DONE;
00624 goto finish;
00625 }
00626
00627 trans->status = NIP_NET_IF_RESOLV_ADDR;
00628 return;
00629 }
00630
00631
00632 phy->hard_send_init(
00633 if_id,
00634 NULL,
00635 htons(0x0800),
00636 nip_disp.next.common.remote_hw_addr,
00637 phy->hw_addr,
00638 len
00639 );
00640
00641
00642
00643 phy->hard_send( if_id, (uint8_t*)&head, NIP_IP_DEFAULT_HEADER_SIZE );
00644 phy->hard_send( if_id, header , trans->header_size );
00645 phy->hard_send( if_id, payload + trans->payload_off, trans->payload_size );
00646
00647 #if (NIP_ICMP_ENABLE == 1) && defined (NIP_ICMP_TEST_NO_MEM_MGR)
00648 if ( head.protocol != NIP_IP_PROTO_ICMP )
00649 #endif
00650 if ( payload != NULL )
00651 nip_mem_release_block( trans->payload );
00652 if ( header != NULL )
00653 nip_mem_release_block( trans->header );
00654
00655
00656 deliverlocal:
00657
00658 NIP_CURR_CMD = &nip_ip_disp_deliver;
00659 return;
00660
00661 finish:
00662
00663 nip_reset_trans( trans );
00664 }
00665
00666
00667
00668 #if (NIP_ICMP_ENABLE == 1)
00669
00670
00671 void nip_icmp_disp_receive( void )
00672 {
00673 struct ICMP_HEADER *icmp;
00674 nip_net_if_trans_t *trans = nip_disp.next.common.trans;
00675
00676
00677 #if defined (NIP_ICMP_TEST_NO_MEM_MGR)
00678 icmp = &nip_test_no_mem_icmp;
00679 #else
00680 icmp = nip_mem_obtain_ptr( trans->payload );
00681 if ( icmp == NULL )
00682 {
00683
00684
00685
00686
00687
00688 goto discard;
00689 return;
00690 }
00691 #endif
00692
00693 icmp->checksum = nip_internet_checksum( (uint16_t*) icmp,trans->payload_size);
00694 if ( icmp->checksum != 0x00 )
00695 {
00696
00697 goto discard;
00698 }
00699
00700
00701 switch ( icmp->type )
00702 {
00703 case NIP_ICMP_T_ECHO_REQ:
00704
00705 icmp->type = NIP_ICMP_T_ECHO_REP;
00706 icmp->checksum = 0x00;
00707
00708 icmp->checksum = nip_internet_checksum( (uint16_t*) icmp, trans->payload_size );
00709 break;
00710
00711 default:
00712
00713 goto discard;
00714 }
00715
00716 #if !defined (NIP_ICMP_TEST_NO_MEM_MGR)
00717
00718 nip_mem_release_block( trans->payload );
00719 #endif
00720
00721 trans->status = NIP_NET_IF_ROUTE;
00722 trans->params.ip.protocol = NIP_IP_PROTO_ICMP;
00723 nip_memcpy( trans->params.ip.dst_nw_addr, trans->params.ip.src_nw_addr, 4 );
00724
00725
00726 NIP_CURR_CMD = &nip_ip_disp_send;
00727 return;
00728
00729 discard:
00730 #if !defined (NIP_ICMP_TEST_NO_MEM_MGR)
00731 nip_mem_release_block( trans->payload );
00732 #endif
00733 nip_reset_trans( trans );
00734 return;
00735 }
00736 #endif // (NIP_ICMP_ENABLE == 1)
00737
00738
00739 void nip_ip_disp_receive( void )
00740 {
00741 struct IP_HEADER head;
00742 nip_net_if_id_t if_id = NIP_CURR_IF;
00743 nip_net_if_t *net_if = &nip_net_if_list[ if_id ];
00744 nip_phy_if_t *phy = &net_if->phy_conf;
00745
00746
00747 nip_net_if_trans_t *trans;
00748 uint8_t cnt;
00749 uint16_t word;
00750 uint16_t *word_ptr;
00751 uint16_t sum;
00752 cnt = sizeof( struct IP_HEADER );
00753
00754
00755 if ( cnt != phy->hard_read( if_id, (uint8_t*) &head, cnt ) )
00756 {
00757
00758
00759 return;
00760 }
00761
00762
00763 if ( head.version != 0x04 )
00764 {
00765 return;
00766 }
00767
00768 trans = nip_ip_route( head.dst_addr, NIP_NET_NO_IF, NULL );
00769 if ( trans == NULL )
00770 return;
00771
00772
00773 trans->flags.reset_status = 1;
00774
00775
00776 cnt = 0;
00777 sum = 0;
00778 word_ptr = (uint16_t*)&head;
00779
00780
00781
00782
00783 do
00784 {
00785
00786
00787
00788
00789 if ( cnt >= sizeof ( struct IP_HEADER )/2 )
00790 {
00791 word_ptr = &word;
00792
00793 if ( phy->hard_read( if_id, (uint8_t*) word_ptr, 2 ) != 2 ) break;
00794 }
00795
00796 sum += *word_ptr;
00797
00798 if ( sum < *word_ptr ) sum++;
00799 if ( ++cnt >= head.ihl * 2 ) break;
00800 word_ptr++;
00801
00802 } while ( 1 );
00803
00804 if ( sum != 0xFFFF )
00805 {
00806
00807 goto reset_trans;
00808 }
00809
00810
00811
00812
00813
00814
00815
00816 word = ntohs(head.total_length) - cnt*2;
00817
00818 #if (NIP_ICMP_ENABLE == 1) && defined (NIP_ICMP_TEST_NO_MEM_MGR)
00819 if ( head.protocol == NIP_IP_PROTO_ICMP )
00820 {
00821 word_ptr = (uint16_t*)&nip_test_no_mem_icmp;
00822 }
00823 else
00824 {
00825 #endif
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 nip_memcpy( trans->params.ip.dst_nw_addr, head.dst_addr, 4 );
00839 nip_memcpy( trans->params.ip.src_nw_addr, head.src_addr, 4 );
00840 trans->params.ip.protocol = head.protocol;
00841
00842
00843 trans->payload = nip_mem_alloc(
00844 word,
00845 word,
00846 NIP_MEM_FLG_DELREAD,
00847 NULL
00848 );
00849
00850 if ( trans->payload == NIP_MEM_NULL )
00851 {
00852
00853 goto reset_trans;
00854 }
00855
00856
00857 word_ptr = nip_mem_obtain_ptr( trans->payload );
00858
00859 #if (NIP_ICMP_ENABLE == 1) && defined (NIP_ICMP_TEST_NO_MEM_MGR)
00860 }
00861 #endif
00862
00863
00864 trans->status = NIP_NET_IF_RECEIVING;
00865 trans->payload_size = word;
00866 trans->flags.free_payload = 1;
00867 word = phy->hard_read( if_id, (uint8_t*) word_ptr, trans->payload_size );
00868
00869 if ( trans->payload_size != word )
00870 {
00871
00872
00873 goto reset_trans;
00874 }
00875
00876
00877
00878 nip_mem_set_used( trans->payload, trans->payload_size );
00879
00880
00881 nip_mem_release_block( trans->payload );
00882
00883
00884 nip_disp.next.common.trans = trans;
00885
00886
00887
00888
00889
00890 NIP_CURR_CMD = &nip_ip_disp_deliver;
00891 return;
00892
00893 reset_trans:
00894 nip_reset_trans( trans );
00895 }
00896
00897
00898
00899
00900 void nip_ip_disp_deliver( void )
00901 {
00902 nip_net_if_trans_t *trans = nip_disp.next.common.trans;
00903
00904 if ( trans->flags.deliverlocal == 1 )
00905 {
00906
00907
00908 #if (NIP_ICMP_ENABLE == 1)
00909 if ( trans->params.ip.protocol == NIP_IP_PROTO_ICMP )
00910 {
00911 NIP_CURR_CMD = &nip_icmp_disp_receive;
00912 return;
00913 }
00914 #endif // (NIP_ICMP_ENABLE == 1)
00915 #if (NIP_UDP_ENABLE == 1)
00916 else if ( trans->params.ip.protocol == NIP_IP_PROTO_UDP )
00917 {
00918 NIP_CURR_CMD = &nip_udp_disp_receive;
00919 return;
00920 }
00921 #endif // (NIP_UDP_ENABLE == 1)
00922 #if (NIP_TCP_ENABLE == 1)
00923 else if ( trans->params.ip.protocol == NIP_IP_PROTO_TCP )
00924 {
00925 NIP_CURR_CMD = &nip_tcp_disp_receive;
00926 return;
00927 }
00928 #endif // (NIP_TCP_ENABLE == 1)
00929 #if (NIP_IGMP_ENABLE == 1)
00930 else if ( trans->params.ip.protocol == NIP_IP_PROTO_IGMP )
00931 {
00932 NIP_CURR_CMD = &nip_igmp_disp_receive;
00933 return;
00934 }
00935 #endif // (NIP_TCP_ENABLE == 1)
00936 }
00937 trans->status = NIP_NET_IF_DONE;
00938
00939 nip_reset_trans( trans );
00940
00941 return;
00942
00943 }
00944
00945 #if NIP_MULTICAST_ENABLE == 1
00946
00947 #if NIP_IP_MAX_HOST_GROUPS > 1
00948
00949
00950
00951
00952 struct nip_ip_group_membership *nip_ip_find_group_membership( nip_net_if_id_t if_id, uint8_t *addr )
00953 {
00954 nip_host_group_id_t group = 0;
00955 #define GROUP_ATTRi(attr) nip_ip_groups[group].attr
00956
00957 do
00958 {
00959
00960 if (( addr != NULL
00961 && nip_memcmp( addr, GROUP_ATTRi(addr), 4 ) == 0
00962 && GROUP_ATTRi(state) != NIP_IP_GROUP_NON
00963 && GROUP_ATTRi(if_id) == if_id
00964 )
00965 ||
00966 ( addr == NULL
00967 && GROUP_ATTRi(state) == NIP_IP_GROUP_NON
00968 ))
00969 return &nip_ip_groups[group];
00970
00971 if ( ++group == NIP_IP_MAX_HOST_GROUPS )
00972 {
00973
00974 return NULL;
00975 }
00976 } while ( 1 );
00977
00978 }
00979 #endif
00980
00981 #if NIP_IGMP_ENABLE == 1
00982
00983 void nip_ip_disp_check_group( void )
00984 {
00985 nip_mem_handle_t buf;
00986 nip_net_if_trans_t *trans;
00987 struct nip_igmp_msg *msg;
00988
00989 #if NIP_IP_MAX_HOST_GROUPS == 1
00990 #define GROUP_ATTRi(attr) nip_ip_group.attr
00991 #else
00992 nip_host_group_id_t group = 0;
00993 #define GROUP_ATTRi(attr) nip_ip_groups[group].attr
00994
00995 do
00996 {
00997 #endif
00998 if ( GROUP_ATTRi(state) == NIP_IP_GROUP_DELAYING )
00999 {
01000
01001 if ( GROUP_ATTRi(t_report) <= nip_tickcount() )
01002 {
01003
01004 buf = nip_mem_alloc(
01005 sizeof( struct nip_igmp_msg ),
01006 sizeof( struct nip_igmp_msg ),
01007 0,
01008 NULL
01009 );
01010
01011
01012 if ( buf == NIP_MEM_NULL )
01013 return;
01014
01015
01016 trans = nip_ip_route( nip_ip_all_hosts, NIP_CURR_IF, NULL );
01017
01018
01019 if ( trans == NULL )
01020 {
01021 nip_mem_free( buf );
01022 return;
01023 }
01024
01025
01026 msg = nip_mem_obtain_ptr( buf );
01027 msg->ver_type = NIP_IGMP_VERTYPE_REPORT;
01028 msg->checksum = 0;
01029 nip_memcpy( msg->addr, GROUP_ATTRi(addr), 4 );
01030 msg->checksum = nip_internet_checksum(
01031 (uint16_t *)msg,
01032 sizeof( struct nip_igmp_msg )
01033 );
01034 nip_mem_release_block( buf );
01035
01036
01037 trans->payload = buf;
01038
01039
01040 trans->flags.deliverlocal = 0;
01041 trans->params.ip.ttl = 1;
01042
01043
01044 trans->status = NIP_NET_IF_RESOLV_ADDR;
01045 nip_disp_notify( NIP_DISP_CHECK_TRANS );
01046
01047
01048 GROUP_ATTRi(state) = NIP_IP_GROUP_IDLE;
01049 }
01050 }
01051
01052 #if NIP_IP_MAX_HOST_GROUPS != 1
01053 } while ( ++group < NIP_IP_MAX_HOST_GROUPS );
01054 #endif
01055
01056 }
01057
01058
01059 void nip_ip_query_groups( nip_net_if_id_t if_id )
01060 {
01061 nip_host_group_id_t group = 0;
01062 #if NIP_IP_MAX_HOST_GROUPS == 1
01063 #define GROUP_ATTRi(attr) nip_ip_group.attr
01064 #else
01065 #define GROUP_ATTRi(attr) nip_ip_groups[group].attr
01066
01067 do
01068 {
01069 #endif
01070 if ( GROUP_ATTRi(state) == NIP_IP_GROUP_IDLE && GROUP_ATTRi(if_id) == if_id)
01071 {
01072
01073 GROUP_ATTRi(t_report) = nip_tickcount() + ((&group)[group] % 10);
01074 }
01075 #if NIP_IP_MAX_HOST_GROUPS != 1
01076 } while ( ++group < NIP_IP_MAX_HOST_GROUPS );
01077 #endif
01078 }
01079
01080
01081 void nip_igmp_disp_receive( void )
01082 {
01083 nip_net_if_trans_t *trans = nip_disp.next.common.trans;
01084 struct nip_igmp_msg *msg;
01085 #if NIP_IP_MAX_HOST_GROUPS == 1
01086 #define GROUP_ATTR(attr) nip_ip_group.attr
01087 #else
01088 struct nip_ip_group_membership *group;
01089 #define GROUP_ATTR(attr) group->attr
01090 #endif
01091
01092
01093 msg = nip_mem_obtain_ptr( trans->payload );
01094
01095
01096
01097 if ( msg->ver_type == NIP_IGMP_VERTYPE_QUERY )
01098 {
01099 nip_ip_query_groups( NIP_CURR_IF );
01100 }
01101 else
01102 {
01103
01104 #if NIP_IP_MAX_HOST_GROUPS == 1
01105 if ( GROUP_ATTR(state) == NIP_IP_GROUP_DELAYING
01106 && nip_memcmp( GROUP_ATTR(addr), msg->addr, 4 ) == 0
01107 && GROUP_ATTR(if_id) == NIP_CURR_IF )
01108 GROUP_ATTR(state) = NIP_IP_GROUP_IDLE;
01109 #else
01110 group = nip_ip_find_group_membership( NIP_CURR_IF, msg->addr );
01111 if ( group != NULL )
01112 GROUP_ATTR(state) = NIP_IP_GROUP_IDLE;
01113 #endif
01114 }
01115
01116 nip_mem_release_block( trans->payload );
01117 nip_reset_trans( trans );
01118 }
01119
01120 #endif
01121
01122
01123
01124
01125
01126
01127 nip_error_t nip_ip_join_host_group( nip_net_if_id_t if_id, uint8_t *addr )
01128 {
01129
01130
01131
01132 #if NIP_IP_MAX_HOST_GROUPS == 1
01133 #define GROUP_ATTR(attr) nip_ip_group.attr
01134
01135 if ( GROUP_ATTR(state) != NIP_IP_GROUP_NON
01136 && ( GROUP_ATTR(if_id) != if_id
01137 || nip_memcmp( addr, GROUP_ATTR(addr), 4 ) != 0)
01138 )
01139 return NIP_E_OUT_OF_RESSOURCES;
01140
01141 #else
01142 struct nip_ip_group_membership *group;
01143 #define GROUP_ATTR(attr) group->attr
01144
01145 group = nip_ip_find_group_membership( if_id, addr );
01146 if ( group == NULL )
01147 group = nip_ip_find_group_membership( if_id, NULL );
01148
01149 if ( group == NULL )
01150 return NIP_E_OUT_OF_RESSOURCES;
01151 #endif
01152
01153
01154
01155
01156 if ( GROUP_ATTR(state) == NIP_IP_GROUP_NON )
01157 {
01158
01159 GROUP_ATTR(if_id) = if_id;
01160 GROUP_ATTR(member_cnt) = 1;
01161 GROUP_ATTR(state) = NIP_IP_GROUP_DELAYING;
01162 nip_memcpy( GROUP_ATTR(addr), addr, 4 );
01163 #if NIP_IGMP_ENABLE == 1
01164 GROUP_ATTR(t_report) = nip_tickcount();
01165 nip_disp_notify_if( if_id, NIP_DISP_IF_GROUP );
01166 nip_dispatcher();
01167 #endif
01168 }
01169 else
01170 {
01171 GROUP_ATTR(member_cnt)++;
01172 }
01173
01174 return NIP_E_OK;
01175 }
01176
01177
01178 void nip_ip_leave_host_group( nip_net_if_id_t if_id, uint8_t *addr )
01179 {
01180
01181
01182
01183 #if NIP_IP_MAX_HOST_GROUPS == 1
01184 #define GROUP_ATTR(attr) nip_ip_group.attr
01185
01186 if ( GROUP_ATTR(state) == NIP_IP_GROUP_NON
01187 || ( GROUP_ATTR(if_id) != if_id
01188 && nip_memcmp( addr, GROUP_ATTR(addr), 4 ) != 0)
01189 )
01190
01191 return;
01192
01193 #else
01194 struct nip_ip_group_membership *group;
01195 #define GROUP_ATTR(attr) group->attr
01196
01197 group = nip_ip_find_group_membership( if_id, addr );
01198 if ( group == NULL )
01199 return;
01200 #endif
01201
01202
01203 if ( --GROUP_ATTR(member_cnt) == 0 )
01204 {
01205
01206 GROUP_ATTR(state) = NIP_IP_GROUP_NON;
01207 }
01208 }
01209
01210 #endif
01211
01212 #endif