1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <config.h>

#include <asiolink/io_address.h>
#include <dhcp/dhcp4.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option.h>
#include <dhcp/pkt6.h>
#include <dhcp/pkt_filter.h>
#include <dhcp/testutils/iface_mgr_test_config.h>
#include <dhcp/tests/pkt_filter6_test_utils.h>
#include <dhcp/tests/packet_queue_testutils.h>
#include <testutils/gtest_utils.h>

#include <boost/scoped_ptr.hpp><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <gtest/gtest.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <fcntl.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <fstream><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <functional><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <iostream><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <sstream><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <arpa/inet.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <unistd.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace std;
using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using boost::scoped_ptr;
namespace ph = std::placeholders;

namespace {

// Note this is for the *real* loopback interface, *not* the fake one.
// So in tests using it you have LOOPBACK_NAME, LOOPBACK_INDEX and
// no "eth0" nor "eth1". In tests not using it you can have "lo", LO_INDEX,
// "eth0" or "eth1".
// Name of loopback interface detection.
const size_t BUF_SIZE = 32;
// Can be overwritten to "lo0" for instance on BSD systems.
char LOOPBACK_NAME[BUF_SIZE] = "lo";
// In fact is never 0, 1 is by far the most likely.
uint32_t LOOPBACK_INDEX = 0;

// Ports used during testing
const uint16_t PORT1 = 10547;   // V6 socket
const uint16_t PORT2 = 10548;   // V4 socket

// On some systems measured duration of receive6() and receive4() appears to be
// shorter than select() timeout.  This may be the case if different time
// resolutions are used by these functions.  For such cases we set the
// tolerance to 0.01s.
const uint32_t TIMEOUT_TOLERANCE = 10000;

// Macro for making select wait time arguments for receive functions
#define RECEIVE_WAIT_MS(m) 0,(m*1000)

/// This test verifies that the socket read buffer can be used to
/// receive the data and that the data can be read from it.
TEST(IfaceTest, readBuffer) {
    // Create fake interface object.
    Iface iface("em0", 0);
    // The size of read buffer should initially be 0 and the returned
    // pointer should be NULL.
    ASSERT_EQ(0, iface.getReadBufferSize());
    EXPECT_EQ(NULL, iface.getReadBuffer());

    // Let's resize the buffer.
    iface.resizeReadBuffer(256);
    // Check that the buffer has expected size.
    ASSERT_EQ(256, iface.getReadBufferSize());
    // The returned pointer should now be non-NULL.
    uint8_t* buf_ptr = iface.getReadBuffer();
    ASSERT_FALSE(buf_ptr == NULL);

    // Use the pointer to set some data.
    for (size_t i = 0; i < iface.getReadBufferSize(); ++i) {
        buf_ptr[i] = i;
    }

    // Get the pointer again and validate the data.
    buf_ptr = iface.getReadBuffer();
    ASSERT_EQ(256, iface.getReadBufferSize());
    for (size_t i = 0; i < iface.getReadBufferSize(); ++i) {
        // Use assert so as it fails on the first failure, no need
        // to continue further checks.
        ASSERT_EQ(i, buf_ptr[i]);
    }
}

// Check that counting the number of active addresses on the interface
// works as expected.
TEST(IfaceTest, countActive4) {
    Iface iface("eth0", 0);
    ASSERT_EQ(0, iface.countActive4());

    iface.addAddress(IOAddress("192.168.0.2"));
    ASSERT_EQ(1, iface.countActive4());

    iface.addAddress(IOAddress("2001:db8:1::1"));
    ASSERT_EQ(1, iface.countActive4());

    iface.addAddress(IOAddress("192.168.0.3"));
    ASSERT_EQ(2, iface.countActive4());

    ASSERT_NO_THROW(iface.setActive(IOAddress("192.168.0.2"), false));
    ASSERT_EQ(1, iface.countActive4());

    ASSERT_NO_THROW(iface.setActive(IOAddress("192.168.0.3"), false));
    ASSERT_EQ(0, iface.countActive4());
}

/// Mock object implementing PktFilter class.  It is used by
/// IfaceMgrTest::setPacketFilter to verify that IfaceMgr::setPacketFilter
/// sets this object as a handler for opening sockets. This dummy
/// class simply records that openSocket function was called by
/// the IfaceMgr as expected.
///
/// @todo This class currently doesn't verify that send/receive functions
/// were called. In order to test it, there is a need to supply dummy
/// function performing select() on certain sockets. The system select()
/// call will fail when dummy socket descriptor is provided and thus
/// TestPktFilter::receive will never be called. The appropriate extension
/// to IfaceMgr is planned along with implementation of other "Packet
/// Filters" such as these supporting Linux Packet Filtering and
/// Berkeley Packet Filtering.
class TestPktFilter : public PktFilter {
public:

    /// Constructor
    TestPktFilter()
        : open_socket_called_(false) {
    }

    virtual bool isDirectResponseSupported() const {
        return (false);
    }

    virtual bool isSocketReceivedTimeSupported() const {
        return (false);
    }

    /// @brief Pretend to open a socket.
    ///
    /// This function doesn't open a real socket. It always returns the
    /// same fake socket descriptor. It also records the fact that it has
    /// been called in the public open_socket_called_ member.
    /// As in the case of opening a real socket, this function will check
    /// if there is another fake socket "bound" to the same address and port.
    /// If there is, it will throw an exception. This allows to simulate the
    /// conditions when one of the sockets can't be open because there is
    /// a socket already open and test how IfaceMgr will handle it.
    ///
    /// @param iface An interface on which the socket is to be opened.
    /// @param addr An address to which the socket is to be bound.
    /// @param port A port to which the socket is to be bound.
    virtual SocketInfo openSocket(Iface& iface,
                                  const isc::asiolink::IOAddress& addr,
                                  const uint16_t port,
                                  const bool join_multicast,
                                  const bool) {
        // Check if there is any other socket bound to the specified address
        // and port on this interface.
        const Iface::SocketCollection& sockets = iface.getSockets();
        for (auto const& socket : sockets) {
            if (((socket.addr_ == addr) ||
                 ((socket.addr_ == IOAddress("::")) && join_multicast)) &&
                socket.port_ == port) {
                isc_throw(SocketConfigError, "test socket bind error");
            }
        }
        open_socket_called_ = true;
        return (SocketInfo(addr, port, 255));
    }

    /// Does nothing
    virtual Pkt4Ptr receive(Iface&, const SocketInfo&) {
        return (Pkt4Ptr());
    }

    /// Does nothing
    virtual int send(const Iface&, uint16_t, const Pkt4Ptr&) {
        return (0);
    }

    /// Holds the information whether openSocket was called on this
    /// object after its creation.
    bool open_socket_called_;
};

class NakedIfaceMgr: public IfaceMgr {
    // "Naked" Interface Manager, exposes internal fields
public:

    /// @brief Constructor.
    NakedIfaceMgr() {
        loDetect();
    }

    /// @brief detects name of the loopback interface
    ///
    /// This method detects name of the loopback interface.
    static void loDetect() {
        // Poor man's interface detection.  It will go away as soon as proper
        // interface detection is implemented
        if (if_nametoindex("lo") > 0) {
            snprintf(LOOPBACK_NAME, BUF_SIZE - 1, "lo");
        } else if (if_nametoindex("lo0") > 0) {
            snprintf(LOOPBACK_NAME, BUF_SIZE - 1, "lo0");
        } else {
            cout << "Failed to detect loopback interface. Neither "
                 << "lo nor lo0 worked. I give up." << endl;
            FAIL();
        }
        LOOPBACK_INDEX = if_nametoindex(LOOPBACK_NAME);
    }

    /// @brief Returns the collection of existing interfaces.
    IfaceCollection& getIfacesLst() { return (ifaces_); }

    /// @brief This function creates fictitious interfaces with fictitious
    /// addresses.
    ///
    /// These interfaces can be used in tests that don't actually try
    /// to open the sockets on these interfaces. Some tests use mock
    /// objects to mimic sockets being open. These interfaces are
    /// suitable for such tests.
    void createIfaces() {

        ifaces_.clear();

        // local loopback
        IfacePtr lo = createIface("lo", LO_INDEX);
        lo->addAddress(IOAddress("127.0.0.1"));
        lo->addAddress(IOAddress("::1"));
        ifaces_.push_back(lo);
        // eth0
        IfacePtr eth0 = createIface("eth0", ETH0_INDEX);
        eth0->addAddress(IOAddress("10.0.0.1"));
        eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
        eth0->addAddress(IOAddress("2001:db8:1::1"));
        ifaces_.push_back(eth0);
        // eth1
        IfacePtr eth1 = createIface("eth1", ETH1_INDEX);
        eth1->addAddress(IOAddress("192.0.2.3"));
        eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
        ifaces_.push_back(eth1);
    }

    /// @brief Create an object representing interface.
    ///
    /// Apart from creating an interface, this function also sets the
    /// interface flags:
    /// - loopback flag if interface name is "lo"
    /// - up always true
    /// - running always true
    /// - inactive always to false
    /// - multicast always to true
    /// - broadcast always to false
    ///
    /// If one needs to modify the default flag settings, the setIfaceFlags
    /// function should be used.
    ///
    /// @param name A name of the interface to be created.
    /// @param ifindex An index of the interface to be created.
    ///
    /// @return An object representing interface.
    static IfacePtr createIface(const std::string& name, const unsigned int ifindex) {
        IfacePtr iface(new Iface(name, ifindex));
        if (name == "lo") {
            iface->flag_loopback_ = true;
            // Don't open sockets on loopback interface.
            iface->inactive4_ = true;
            iface->inactive6_ = true;
        } else {
            iface->inactive4_ = false;
            iface->inactive6_ = false;
        }
        iface->flag_multicast_ = true;
        // On BSD systems, the SO_BINDTODEVICE option is not supported.
        // Therefore the IfaceMgr will throw an exception on attempt to
        // open sockets on more than one broadcast-capable interface at
        // the same time. In order to prevent this error, we mark all
        // interfaces broadcast-incapable for unit testing.
        iface->flag_broadcast_ = false;
        iface->flag_up_ = true;
        iface->flag_running_ = true;
        return (iface);
    }

    /// @brief Checks if the specified interface has a socket bound to a
    /// specified address.
    ///
    /// @param iface_name A name of the interface.
    /// @param addr An address to be checked for binding.
    ///
    /// @return true if there is a socket bound to the specified address.
    bool isBound(const std::string& iface_name, const std::string& addr) {
        IfacePtr iface = getIface(iface_name);
        if (!iface) {
            ADD_FAILURE() << "the interface " << iface_name << " doesn't exist";
            return (false);
        }
        const Iface::SocketCollection& sockets = iface->getSockets();
        for (auto const& sock : sockets) {
            if (sock.addr_ == IOAddress(addr)) {
                return (true);

            } else if ((sock.addr_ == IOAddress("::")) &&
                       (IOAddress(addr).isV6LinkLocal())) {
                for (auto const& a : iface->getAddresses()) {
                    if (a.get() == IOAddress(addr)) {
                        return (true);
                    }
                }
            }
        }
        return (false);
    }

    /// @brief Modify flags on the interface.
    ///
    /// @param name A name of the interface.
    /// @param loopback A new value of the loopback flag.
    /// @param up A new value of the up flag.
    /// @param running A new value of the running flag.
    /// @param inactive A new value of the inactive flag.
    void setIfaceFlags(const std::string& name, const bool loopback,
                       const bool up, const bool running,
                       const bool inactive4,
                       const bool inactive6) {
        for (auto const& iface : ifaces_) {
            if (iface->getName() == name) {
                iface->flag_loopback_ = loopback;
                iface->flag_up_ = up;
                iface->flag_running_ = running;
                iface->inactive4_ = inactive4;
                iface->inactive6_ = inactive6;
            }
        }
    }
};

/// @brief A test fixture class for IfaceMgr.
///
/// @todo Sockets being opened by IfaceMgr tests should be managed by
/// the test fixture. In particular, the class should close sockets after
/// each test. Current approach where test cases are responsible for
/// closing sockets is resource leak prone, especially in case of the
/// test failure path.
class IfaceMgrTest : public ::testing::Test {
public:
    /// @brief Constructor.
    IfaceMgrTest()
        : errors_count_(0) {
    }

    ~IfaceMgrTest() {
    }

    /// @brief Tests the number of IPv6 sockets on interface
    ///
    /// This function checks the expected number of open IPv6 sockets on the
    /// specified interface. On non-Linux systems, sockets are bound to a
    /// link-local address and the number of unicast addresses specified.
    /// On Linux systems, there is one more socket bound to a ff02::1:2
    /// multicast address.
    ///
    /// @param iface An interface on which sockets are open.
    /// @param unicast_num A number of unicast addresses bound.
    /// @param link_local_num A number of link local addresses bound.
    void checkSocketsCount6(const Iface& iface, const int unicast_num,
                            const int link_local_num = 1) {
        // On local-loopback interface, there should be no sockets.
        if (iface.flag_loopback_) {
            ASSERT_TRUE(iface.getSockets().empty())
                << "expected empty socket set on loopback interface "
                << iface.getName();
            return;
        }
#if defined OS_LINUX
        // On Linux, for each link-local address there may be an
        // additional socket opened and bound to ff02::1:2. This socket
        // is only opened if the interface is multicast-capable.
        ASSERT_EQ(unicast_num + (iface.flag_multicast_ ? link_local_num : 0)
                  + link_local_num, iface.getSockets().size())
            << "invalid number of sockets on interface "
            << iface.getName();
#else
        // On non-Linux, there is no additional socket.
        ASSERT_EQ(unicast_num + link_local_num, iface.getSockets().size())
            << "invalid number of sockets on interface "
            << iface.getName();

#endif
    }

    // Get the number of IPv4 or IPv6 sockets on the loopback interface
    int getOpenSocketsCount(const Iface& iface, uint16_t family) const {
        // Get all sockets.
        Iface::SocketCollection sockets = iface.getSockets();

        // Loop through sockets and try to find the ones which match the
        // specified type.
        int sockets_count = 0;
        for (auto const& sock : sockets) {
            // Match found, increase the counter.
            if (sock.family_ == family) {
                ++sockets_count;
            }
        }
        return (sockets_count);
    }

    /// @brief returns socket bound to a specific address (or NULL)
    ///
    /// A helper function, used to pick a socketinfo that is bound to a given
    /// address.
    ///
    /// @param sockets sockets collection
    /// @param addr address the socket is bound to
    ///
    /// @return socket info structure (or NULL)
    const isc::dhcp::SocketInfo*
    getSocketByAddr(const isc::dhcp::Iface::SocketCollection& sockets,
                    const IOAddress& addr) {
        for (auto const& s : sockets) {
            if (s.addr_ == addr) {
                return (&s);
            }
        }
        return (NULL);
    }

    /// @brief Implements an IfaceMgr error handler.
    ///
    /// This function can be installed as an error handler for the
    /// IfaceMgr::openSockets4 function. The error handler is invoked
    /// when an attempt to open a particular socket fails for any reason.
    /// Typically, the error handler will log a warning. When the error
    /// handler returns, the openSockets4 function should continue opening
    /// sockets on other interfaces.
    ///
    /// @param errmsg An error string indicating the reason for failure.
    void ifaceMgrErrorHandler(const std::string&) {
        // Increase the counter of invocations to this function. By checking
        // this number, a test may check if the expected number of errors
        // has occurred.
        ++errors_count_;
    }

    /// @brief Tests the ability to send and receive DHCPv6 packets
    ///
    /// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
    /// given queue configuration.  It then calls IfaceMgr::startDHCPReceiver
    /// and verifies whether or not the receive thread has been started as
    /// expected.  Next it creates a generic DHCPv6 packet and sends it over
    /// the loop back interface.  It invokes IfaceMgr::receive6 to receive the
    /// packet sent, and compares to the packets for equality.
    ///
    /// @param dhcp_queue_control dhcp-queue-control contents to use for the test
    /// @param exp_queue_enabled flag that indicates if packet queuing is expected
    /// to be enabled.
    void sendReceive6Test(data::ConstElementPtr dhcp_queue_control, bool exp_queue_enabled) {
        scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

        // Testing socket operation in a portable way is tricky
        // without interface detection implemented
        // let's assume that every supported OS have lo interface
        IOAddress lo_addr("::1");
        int socket1 = 0, socket2 = 0;
        EXPECT_NO_THROW(<--- There is an unknown macro here somewhere. Configuration is required. If EXPECT_NO_THROW is a macro then please configure it.
            socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
            socket2 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10546);
        );

        EXPECT_GE(socket1, 0);
        EXPECT_GE(socket2, 0);

        // Configure packet queueing as desired.
        bool queue_enabled = false;
        ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, dhcp_queue_control));

        // Verify that we have a queue only if we expected one.
        ASSERT_EQ(exp_queue_enabled, queue_enabled);

        // Thread should only start when there is a packet queue.
        ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
        ASSERT_TRUE(queue_enabled == ifacemgr->isDHCPReceiverRunning());

        // If the thread is already running, trying to start it again should fail.
        if (queue_enabled) {
            ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET6), InvalidOperation);
            // Should still have one running.
            ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
        }

        // Let's build our DHCPv6 packet.
        // prepare dummy payload
        uint8_t data[128];
        for (uint8_t i = 0; i < 128; i++) {
            data[i] = i;
        }

        Pkt6Ptr sendPkt = Pkt6Ptr(new Pkt6(data, 128));
        sendPkt->repack();
        sendPkt->setRemotePort(10547);
        sendPkt->setRemoteAddr(IOAddress("::1"));
        sendPkt->setIndex(LOOPBACK_INDEX);
        sendPkt->setIface(LOOPBACK_NAME);

        // Send the packet.
        EXPECT_EQ(true, ifacemgr->send(sendPkt));

        // Now, let's try and receive it.
        Pkt6Ptr rcvPkt;
        rcvPkt = ifacemgr->receive6(10);
        ASSERT_TRUE(rcvPkt); // received our own packet

        // let's check that we received what was sent
        ASSERT_EQ(sendPkt->data_.size(), rcvPkt->data_.size());
        EXPECT_EQ(0, memcmp(&sendPkt->data_[0], &rcvPkt->data_[0],
                            rcvPkt->data_.size()));

        EXPECT_EQ(sendPkt->getRemoteAddr(), rcvPkt->getRemoteAddr());

        // since we opened 2 sockets on the same interface and none of them is multicast,
        // none is preferred over the other for sending data, so we really should not
        // assume the one or the other will always be chosen for sending data. Therefore
        // we should accept both values as source ports.
        EXPECT_TRUE((rcvPkt->getRemotePort() == 10546) || (rcvPkt->getRemotePort() == 10547));

        // Stop the thread.  This should be no harm/no foul if we're not
        // queueuing.  Either way, we should not have a thread afterwards.
        ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
        ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
    }

    /// @brief Tests the ability to send and receive DHCPv4 packets
    ///
    /// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
    /// given queue configuration.  It then calls IfaceMgr::startDHCPReceiver
    /// and verifies whether or not the receive thread has been started as
    /// expected.  Next it creates a DISCOVER packet and sends it over
    /// the loop back interface.  It invokes IfaceMgr::receive4 to receive the
    /// packet sent, and compares to the packets for equality.
    ///
    /// @param dhcp_queue_control dhcp-queue-control contents to use for the test
    /// @param exp_queue_enabled flag that indicates if packet queuing is expected
    /// to be enabled.
    void sendReceive4Test(data::ConstElementPtr dhcp_queue_control, bool exp_queue_enabled) {
        scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

        // Testing socket operation in a portable way is tricky
        // without interface detection implemented.
        // Let's assume that every supported OS has lo interface
        IOAddress lo_addr("127.0.0.1");
        int socket1 = 0;
        EXPECT_NO_THROW(
            socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr,
                                           DHCP4_SERVER_PORT + 10000);
        );

        EXPECT_GE(socket1, 0);

        // Configure packet queueing as desired.
        bool queue_enabled = false;
        ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, dhcp_queue_control));

        // Verify that we have a queue only if we expected one.
        ASSERT_EQ(exp_queue_enabled, queue_enabled);

        // Thread should only start when there is a packet queue.
        ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
        ASSERT_TRUE(queue_enabled == ifacemgr->isDHCPReceiverRunning());

        // If the thread is already running, trying to start it again should fail.
        if (queue_enabled) {
            ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET), InvalidOperation);
            // Should still have one running.
            ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
        }

        // Let's construct the packet to send.
        boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );
        sendPkt->setLocalAddr(IOAddress("127.0.0.1"));
        sendPkt->setLocalPort(DHCP4_SERVER_PORT + 10000 + 1);
        sendPkt->setRemotePort(DHCP4_SERVER_PORT + 10000);
        sendPkt->setRemoteAddr(IOAddress("127.0.0.1"));
        sendPkt->setIndex(LOOPBACK_INDEX);
        sendPkt->setIface(string(LOOPBACK_NAME));
        sendPkt->setHops(6);
        sendPkt->setSecs(42);
        sendPkt->setCiaddr(IOAddress("192.0.2.1"));
        sendPkt->setSiaddr(IOAddress("192.0.2.2"));
        sendPkt->setYiaddr(IOAddress("192.0.2.3"));
        sendPkt->setGiaddr(IOAddress("192.0.2.4"));

        // Unpack() now checks if mandatory DHCP_MESSAGE_TYPE is present.
        // Workarounds (creating DHCP Message Type Option by hand) are no longer
        // needed as setDhcpType() is called in constructor.

        uint8_t sname[] = "That's just a string that will act as SNAME";
        sendPkt->setSname(sname, strlen((const char*)sname));
        uint8_t file[] = "/another/string/that/acts/as/a/file_name.txt";
        sendPkt->setFile(file, strlen((const char*)file));

        ASSERT_NO_THROW(
            sendPkt->pack();
        );

        // OK, Send the PACKET!
        bool result = false;
        EXPECT_NO_THROW(result = ifacemgr->send(sendPkt));
        EXPECT_TRUE(result);

        // Now let's try and receive it.
        boost::shared_ptr<Pkt4> rcvPkt;
        ASSERT_NO_THROW(rcvPkt = ifacemgr->receive4(10));
        ASSERT_TRUE(rcvPkt); // received our own packet
        ASSERT_NO_THROW(
            rcvPkt->unpack();
        );

        // let's check that we received what was sent
        EXPECT_EQ(sendPkt->len(), rcvPkt->len());
        EXPECT_EQ("127.0.0.1", rcvPkt->getRemoteAddr().toText());
        EXPECT_EQ(sendPkt->getRemotePort(), rcvPkt->getLocalPort());
        EXPECT_EQ(sendPkt->getHops(), rcvPkt->getHops());
        EXPECT_EQ(sendPkt->getOp(),   rcvPkt->getOp());
        EXPECT_EQ(sendPkt->getSecs(), rcvPkt->getSecs());
        EXPECT_EQ(sendPkt->getFlags(), rcvPkt->getFlags());
        EXPECT_EQ(sendPkt->getCiaddr(), rcvPkt->getCiaddr());
        EXPECT_EQ(sendPkt->getSiaddr(), rcvPkt->getSiaddr());
        EXPECT_EQ(sendPkt->getYiaddr(), rcvPkt->getYiaddr());
        EXPECT_EQ(sendPkt->getGiaddr(), rcvPkt->getGiaddr());
        EXPECT_EQ(sendPkt->getTransid(), rcvPkt->getTransid());
        EXPECT_TRUE(sendPkt->getSname() == rcvPkt->getSname());
        EXPECT_TRUE(sendPkt->getFile() == rcvPkt->getFile());
        EXPECT_EQ(sendPkt->getHtype(), rcvPkt->getHtype());
        EXPECT_EQ(sendPkt->getHlen(), rcvPkt->getHlen());

        // since we opened 2 sockets on the same interface and none of them is multicast,
        // none is preferred over the other for sending data, so we really should not
        // assume the one or the other will always be chosen for sending data. We should
        // skip checking source port of sent address.

        // Close the socket. Further we will test if errors are reported
        // properly on attempt to use closed socket.
        close(socket1);

        // @todo Closing the socket does NOT cause a read error out of the
        // receiveDHCP<X>Packets() select.  Apparently this is because the
        // thread is already inside the select when the socket is closed,
        // and (at least under Centos 7.5), this does not interrupt the
        // select.  For now, we'll only test this for direct receive.
        if (!queue_enabled) {
            EXPECT_THROW(ifacemgr->receive4(10), SocketReadError);
        }

        // Verify write fails.
        EXPECT_THROW(ifacemgr->send(sendPkt), SocketWriteError);

        // Stop the thread.  This should be no harm/no foul if we're not
        // queueuing.  Either way, we should not have a thread afterwards.
        ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
        ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
    }

    /// @brief Verifies that IfaceMgr DHCPv4 receive calls detect and
    /// purge external sockets that have gone bad without affecting
    /// affecting normal operations.  It can be run with or without
    /// packet queuing.
    ///
    /// @param use_queue determines if packet queuing is used or not.
    void purgeExternalSockets4Test(bool use_queue = false) {
        bool callback_ok = false;
        bool callback2_ok = false;

        scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

        if (use_queue) {
            bool queue_enabled = false;
            data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500);
            ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, config));
            ASSERT_TRUE(queue_enabled);

            // Thread should only start when there is a packet queue.
            ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
            ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
        }

        // Create first pipe and register it as extra socket
        int pipefd[2];
        EXPECT_TRUE(pipe(pipefd) == 0);
        ASSERT_FALSE(ifacemgr->isExternalSocket(pipefd[0]));
        EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0],
                        [&callback_ok, &pipefd](int fd) {
                            callback_ok = (pipefd[0] == fd);
                        }));
        ASSERT_TRUE(ifacemgr->isExternalSocket(pipefd[0]));

        // Let's create a second pipe and register it as well
        int secondpipe[2];
        EXPECT_TRUE(pipe(secondpipe) == 0);
        ASSERT_FALSE(ifacemgr->isExternalSocket(secondpipe[0]));
        EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0],
                        [&callback2_ok, &secondpipe](int fd) {
                            callback2_ok = (secondpipe[0] == fd);
                        }));
        ASSERT_TRUE(ifacemgr->isExternalSocket(secondpipe[0]));

        // Verify a call with no data and normal external sockets works ok.
        Pkt4Ptr pkt4;
        ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(RECEIVE_WAIT_MS(10)));

        // No callback invocations and no DHCPv4 pkt.
        EXPECT_FALSE(callback_ok);
        EXPECT_FALSE(callback2_ok);
        EXPECT_FALSE(pkt4);

        // Now close the first pipe.  This should make it's external socket invalid.
        close(pipefd[1]);
        close(pipefd[0]);

        // We call receive4() which should detect and remove the invalid socket.
        try {
            pkt4 = ifacemgr->receive4(RECEIVE_WAIT_MS(10));
            ADD_FAILURE() << "receive4 should have failed";
        } catch (const SocketReadError& ex) {
            EXPECT_EQ(std::string("SELECT interrupted by one invalid sockets,"
                                  " purged 1 socket descriptors"),
                      std::string(ex.what()));
        } catch (const std::exception& ex) {
            ADD_FAILURE() << "wrong exception thrown: " << ex.what();
        }

        // No callback invocations and no DHCPv4 pkt.
        EXPECT_FALSE(callback_ok);
        EXPECT_FALSE(callback2_ok);
        EXPECT_FALSE(pkt4);

        // Now check whether the second callback is still functional
        EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));

        // Call receive4 again, this should work.
        ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(RECEIVE_WAIT_MS(10)));

        // Should have callback2 data only.
        EXPECT_FALSE(callback_ok);
        EXPECT_TRUE(callback2_ok);
        EXPECT_FALSE(pkt4);

        // Stop the thread.  This should be no harm/no foul if we're not
        // queueuing.  Either way, we should not have a thread afterwards.
        ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
        ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
    }

    /// @brief Verifies that IfaceMgr DHCPv6 receive calls detect and
    /// purge external sockets that have gone bad without affecting
    /// affecting normal operations.  It can be run with or without
    /// packet queuing.
    ///
    /// @param use_queue determines if packet queuing is used or not.
    void purgeExternalSockets6Test(bool use_queue = false) {
        bool callback_ok = false;
        bool callback2_ok = false;

        scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

        if (use_queue) {
            bool queue_enabled = false;
            data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500);
            ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, config));
            ASSERT_TRUE(queue_enabled);

            // Thread should only start when there is a packet queue.
            ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
            ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
        }

        // Create first pipe and register it as extra socket
        int pipefd[2];
        EXPECT_TRUE(pipe(pipefd) == 0);
        ASSERT_FALSE(ifacemgr->isExternalSocket(pipefd[0]));
        EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0],
                        [&callback_ok, &pipefd](int fd) {
                            callback_ok = (pipefd[0] == fd);
                        }));
        ASSERT_TRUE(ifacemgr->isExternalSocket(pipefd[0]));

        // Let's create a second pipe and register it as well
        int secondpipe[2];
        EXPECT_TRUE(pipe(secondpipe) == 0);
        ASSERT_FALSE(ifacemgr->isExternalSocket(secondpipe[0]));
        EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0],
                        [&callback2_ok, &secondpipe](int fd) {
                            callback2_ok = (secondpipe[0] == fd);
                        }));
        ASSERT_TRUE(ifacemgr->isExternalSocket(secondpipe[0]));

        // Verify a call with no data and normal external sockets works ok.
        Pkt6Ptr pkt6;
        ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(RECEIVE_WAIT_MS(10)));

        // No callback invocations and no DHCPv6 pkt.
        EXPECT_FALSE(callback_ok);
        EXPECT_FALSE(callback2_ok);
        EXPECT_FALSE(pkt6);

        // Now close the first pipe.  This should make it's external socket invalid.
        close(pipefd[1]);
        close(pipefd[0]);

        // We call receive6() which should detect and remove the invalid socket.
        try {
            pkt6 = ifacemgr->receive6(RECEIVE_WAIT_MS(10));
            ADD_FAILURE() << "receive6 should have failed";
        } catch (const SocketReadError& ex) {
            EXPECT_EQ(std::string("SELECT interrupted by one invalid sockets,"
                                  " purged 1 socket descriptors"),
                      std::string(ex.what()));
        } catch (const std::exception& ex) {
            ADD_FAILURE() << "wrong exception thrown: " << ex.what();
        }

        // No callback invocations and no DHCPv6 pkt.
        EXPECT_FALSE(callback_ok);
        EXPECT_FALSE(callback2_ok);
        EXPECT_FALSE(pkt6);

        // Now check whether the second callback is still functional
        EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));

        // Call receive6 again, this should work.
        ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(RECEIVE_WAIT_MS(10)));

        // Should have callback2 data only.
        EXPECT_FALSE(callback_ok);
        EXPECT_TRUE(callback2_ok);
        EXPECT_FALSE(pkt6);

        // Stop the thread.  This should be no harm/no foul if we're not
        // queueuing.  Either way, we should not have a thread afterwards.
        ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
        ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
    }

    /// Holds the invocation counter for ifaceMgrErrorHandler.
    int errors_count_;
};

// We need some known interface to work reliably. Loopback interface is named
// lo on Linux and lo0 on BSD boxes. We need to find out which is available.
// This is not a real test, but rather a workaround that will go away when
// interface detection is implemented on all OSes.
TEST_F(IfaceMgrTest, loDetect) {
    NakedIfaceMgr::loDetect();
}

// Uncomment this test to create packet writer. It will
// write incoming DHCPv6 packets as C arrays. That is useful
// for generating test sequences based on actual traffic
//
// TODO: this potentially should be moved to a separate tool
//

#if 0
TEST_F(IfaceMgrTest, dhcp6Sniffer) {
    // Testing socket operation in a portable way is tricky
    // without interface detection implemented

    static_cast<void>(remove("interfaces.txt"));

    ofstream interfaces("interfaces.txt", ios::ate);
    interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
    interfaces.close();

    boost::scoped_ptr<NakedIfaceMgr> ifacemgr = new NakedIfaceMgr();

    Pkt6Ptr pkt;
    int cnt = 0;
    cout << "---8X-----------------------------------------" << endl;
    while (true) {
        pkt.reset(ifacemgr->receive());

        cout << "// this code is autogenerated. Do NOT edit." << endl;
        cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
        cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
        cout << "    Pkt6* pkt;" << endl;
        cout << "    pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
        cout << "    pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
        cout << "    pkt->remote_addr_ = IOAddress(\""
             << pkt->remote_addr_ << "\");" << endl;
        cout << "    pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
        cout << "    pkt->local_addr_ = IOAddress(\""
             << pkt->local_addr_ << "\");" << endl;
        cout << "    pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
        cout << "    pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;

        // TODO it is better to declare statically initialize the array
        // and then memcpy it to packet.
        for (int i=0; i< pkt->data_len_; i++) {
            cout << "    pkt->data_[" << i << "]="
                 << (int)(unsigned char)pkt->data_[i] << "; ";
            if (!(i%4))
                cout << endl;
        }
        cout << endl;
        cout << "    return (pkt);" << endl;
        cout << "}" << endl << endl;

        pkt.reset();
    }
    cout << "---8X-----------------------------------------" << endl;

    // Never happens. Infinite loop is infinite
}
#endif

// This test verifies that creation of the IfaceMgr instance doesn't
// cause an exception.
TEST_F(IfaceMgrTest, instance) {
    EXPECT_NO_THROW(IfaceMgr::instance());
}

// Basic tests for Iface inner class.
TEST_F(IfaceMgrTest, ifaceClass) {

  IfacePtr iface(new Iface("eth5", 7));
    EXPECT_STREQ("eth5/7", iface->getFullName().c_str());

    EXPECT_THROW_MSG(iface.reset(new Iface("", 10)), BadValue,
                     "Interface name must not be empty");

    EXPECT_NO_THROW(iface.reset(new Iface("big-index", 66666)));
    EXPECT_EQ(66666, iface->getIndex());
}

// This test checks the getIface by index method.
TEST_F(IfaceMgrTest, getIfaceByIndex) {
    NakedIfaceMgr ifacemgr;

    // Create a set of fake interfaces. At the same time, remove the actual
    // interfaces that have been detected by the IfaceMgr.
    ifacemgr.createIfaces();

    // Getting an unset index should throw.
    EXPECT_THROW_MSG(ifacemgr.getIface(UNSET_IFINDEX), BadValue, "interface index was not set");

    // Historically -1 was used as an unset value. Let's also check that it throws in case we didn't
    // migrate all code to UNSET_IFINDEX and in case the values diverge.
    EXPECT_THROW_MSG(ifacemgr.getIface(-1), BadValue, "interface index was not set");

    // Get the first interface defined.
    IfacePtr iface(ifacemgr.getIface(0));
    ASSERT_TRUE(iface);
    EXPECT_EQ("lo", iface->getName());

    // Attemt to get an undefined interface.
    iface = ifacemgr.getIface(3);
    EXPECT_FALSE(iface);

    // Check that we can go past INT_MAX.
    unsigned int int_max(numeric_limits<int>::max());
    iface = ifacemgr.getIface(int_max);
    EXPECT_FALSE(iface);
    iface = ifacemgr.createIface("wlan0", int_max);
    ifacemgr.addInterface(iface);
    iface = ifacemgr.getIface(int_max);
    EXPECT_TRUE(iface);
    iface = ifacemgr.getIface(int_max + 1);
    EXPECT_FALSE(iface);
    iface = ifacemgr.createIface("wlan1", int_max + 1);
    ifacemgr.addInterface(iface);
    iface = ifacemgr.getIface(int_max + 1);
    EXPECT_TRUE(iface);
}

// This test checks the getIface by packet method.
TEST_F(IfaceMgrTest, getIfaceByPkt) {
    NakedIfaceMgr ifacemgr;
    // Create a set of fake interfaces. At the same time, remove the actual
    // interfaces that have been detected by the IfaceMgr.
    ifacemgr.createIfaces();

    // Try IPv4 packet by name.
    Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 1234));
    IfacePtr iface = ifacemgr.getIface(pkt4);
    EXPECT_FALSE(iface);
    pkt4->setIface("eth0");
    iface = ifacemgr.getIface(pkt4);
    EXPECT_TRUE(iface);
    EXPECT_FALSE(pkt4->indexSet());

    // Try IPv6 packet by index.
    Pkt6Ptr pkt6(new Pkt6(DHCPV6_REPLY, 123456));
    iface = ifacemgr.getIface(pkt6);
    EXPECT_FALSE(iface);
    ASSERT_TRUE(ifacemgr.getIface("eth0"));
    pkt6->setIndex(ifacemgr.getIface("eth0")->getIndex() + 1);
    iface = ifacemgr.getIface(pkt6);
    ASSERT_TRUE(iface);
    EXPECT_TRUE(pkt6->indexSet());

    // Index has precedence when both name and index are available.
    EXPECT_EQ("eth1", iface->getName());
    pkt6->setIface("eth0");
    iface = ifacemgr.getIface(pkt6);
    ASSERT_TRUE(iface);
    EXPECT_EQ("eth1", iface->getName());

    // Not existing name fails.
    pkt4->setIface("eth2");
    iface = ifacemgr.getIface(pkt4);
    EXPECT_FALSE(iface);

    // Not existing index fails.
    pkt6->setIndex(3);
    iface = ifacemgr.getIface(pkt6);
    ASSERT_FALSE(iface);

    // Test that resetting the index is verifiable.
    pkt4->resetIndex();
    EXPECT_FALSE(pkt4->indexSet());
    pkt6->resetIndex();
    EXPECT_FALSE(pkt6->indexSet());

    // Test that you can also reset the index via setIndex().
    pkt4->setIndex(UNSET_IFINDEX);
    EXPECT_FALSE(pkt4->indexSet());
    pkt6->setIndex(UNSET_IFINDEX);
    EXPECT_FALSE(pkt6->indexSet());
}

// Test that the IPv4 address can be retrieved for the interface.
TEST_F(IfaceMgrTest, ifaceGetAddress) {
    Iface iface("eth0", 0);

    IOAddress addr("::1");
    // Initially, the Iface has no addresses assigned.
    EXPECT_FALSE(iface.getAddress4(addr));
    // Add some addresses with IPv4 address in the middle.
    iface.addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
    iface.addAddress(IOAddress("10.1.2.3"));
    iface.addAddress(IOAddress("2001:db8:1::2"));
    // The v4 address should be returned.
    EXPECT_TRUE(iface.getAddress4(addr));
    EXPECT_EQ("10.1.2.3", addr.toText());
    // Delete the IPv4 address and leave only two IPv6 addresses.
    ASSERT_NO_THROW(iface.delAddress(IOAddress("10.1.2.3")));
    // The IPv4 address should not be returned.
    EXPECT_FALSE(iface.getAddress4(addr));
    // Add a different IPv4 address at the end of the list.
    iface.addAddress(IOAddress("192.0.2.3"));
    // This new address should now be returned.
    EXPECT_TRUE(iface.getAddress4(addr));
    EXPECT_EQ("192.0.2.3", addr.toText());
}

// This test checks if it is possible to check that the specific address is
// assigned to the interface.
TEST_F(IfaceMgrTest, ifaceHasAddress) {
    IfaceMgrTestConfig config(true);

    IfacePtr iface = IfaceMgr::instance().getIface("eth0");
    ASSERT_TRUE(iface);
    EXPECT_TRUE(iface->hasAddress(IOAddress("10.0.0.1")));
    EXPECT_FALSE(iface->hasAddress(IOAddress("10.0.0.2")));
    EXPECT_TRUE(iface->hasAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));
    EXPECT_TRUE(iface->hasAddress(IOAddress("2001:db8:1::1")));
    EXPECT_FALSE(iface->hasAddress(IOAddress("2001:db8:1::2")));
}

// This test checks it is not allowed to add duplicate interfaces.
TEST_F(IfaceMgrTest, addInterface) {
    IfaceMgrTestConfig config(true);

    IfacePtr dup_name(new Iface("eth1", 123));
    EXPECT_THROW_MSG(IfaceMgr::instance().addInterface(dup_name), Unexpected,
                     "Can't add eth1/123 when eth1/2 already exists.");
    IfacePtr dup_index(new Iface("eth2", 2));
    EXPECT_THROW_MSG(IfaceMgr::instance().addInterface(dup_index), Unexpected,
                     "Can't add eth2/2 when eth1/2 already exists.");

    IfacePtr eth2(new Iface("eth2", 3));
    EXPECT_NO_THROW(IfaceMgr::instance().addInterface(eth2));
}

// TODO: Implement getPlainMac() test as soon as interface detection
// is implemented.
TEST_F(IfaceMgrTest, getIface) {

    cout << "Interface checks. Please ignore socket binding errors." << endl;
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Interface name, ifindex
    IfacePtr iface1(new Iface("lo1", 100));
    IfacePtr iface2(new Iface("eth9", 101));
    IfacePtr iface3(new Iface("en99", 102));
    IfacePtr iface4(new Iface("e1000g4", 103));
    cout << "This test assumes that there are less than 100 network interfaces"
         << " in the tested system and there are no lo1, eth9, en99, e1000g4"
         << " or wifi15 interfaces present." << endl;

    // Note: real interfaces may be detected as well
    ifacemgr->getIfacesLst().push_back(iface1);
    ifacemgr->getIfacesLst().push_back(iface2);
    ifacemgr->getIfacesLst().push_back(iface3);
    ifacemgr->getIfacesLst().push_back(iface4);

    cout << "There are " << ifacemgr->getIfacesLst().size()
         << " interfaces." << endl;
    for (auto const& iface : ifacemgr->getIfacesLst()) {
        cout << "  " << iface->getFullName() << endl;
    }

    // Check that interface can be retrieved by ifindex
    IfacePtr tmp = ifacemgr->getIface(102);
    ASSERT_TRUE(tmp);

    EXPECT_EQ("en99", tmp->getName());
    EXPECT_EQ(102, tmp->getIndex());

    // Check that interface can be retrieved by name
    tmp = ifacemgr->getIface("lo1");
    ASSERT_TRUE(tmp);

    EXPECT_EQ("lo1", tmp->getName());
    EXPECT_EQ(100, tmp->getIndex());

    // Check that non-existing interfaces are not returned
    EXPECT_FALSE(ifacemgr->getIface("wifi15") );
}

TEST_F(IfaceMgrTest, clearIfaces) {
    NakedIfaceMgr ifacemgr;
    // Create a set of fake interfaces. At the same time, remove the actual
    // interfaces that have been detected by the IfaceMgr.
    ifacemgr.createIfaces();

    ASSERT_GT(ifacemgr.countIfaces(), 0);

    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    ASSERT_NO_THROW(ifacemgr.openSockets4());

    ifacemgr.clearIfaces();

    EXPECT_EQ(0, ifacemgr.countIfaces());
}

// Verify that we have the expected default DHCPv4 packet queue.
TEST_F(IfaceMgrTest, packetQueue4) {
    NakedIfaceMgr ifacemgr;

    // Should not have a queue at start up.
    ASSERT_FALSE(ifacemgr.getPacketQueue4());

    // Verify that we can create a queue with default factory.
    data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 2000);
    ASSERT_NO_THROW(ifacemgr.getPacketQueueMgr4()->createPacketQueue(config));
    CHECK_QUEUE_INFO(ifacemgr.getPacketQueue4(), "{ \"capacity\": 2000, \"queue-type\": \""
                     << PacketQueueMgr4::DEFAULT_QUEUE_TYPE4 << "\", \"size\": 0 }");
}

// Verify that we have the expected default DHCPv6 packet queue.
TEST_F(IfaceMgrTest, packetQueue6) {
    NakedIfaceMgr ifacemgr;

    // Should not have a queue at start up.
    ASSERT_FALSE(ifacemgr.getPacketQueue6());

    // Verify that we can create a queue with default factory.
    data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 2000);
    ASSERT_NO_THROW(ifacemgr.getPacketQueueMgr6()->createPacketQueue(config));
    CHECK_QUEUE_INFO(ifacemgr.getPacketQueue6(), "{ \"capacity\": 2000, \"queue-type\": \""
                     << PacketQueueMgr6::DEFAULT_QUEUE_TYPE6 << "\", \"size\": 0 }");
}

TEST_F(IfaceMgrTest, receiveTimeout6) {
    using namespace boost::posix_time;
    std::cout << "Testing DHCPv6 packet reception timeouts."
              << " Test will block for a few seconds when waiting"
              << " for timeout to occur." << std::endl;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
    // Open socket on the lo interface.
    IOAddress lo_addr("::1");
    int socket1 = 0;
    ASSERT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547)
    );
    // Socket is open if result is non-negative.
    ASSERT_GE(socket1, 0);
    // Start receiver.
    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));

    // Remember when we call receive6().
    ptime start_time = microsec_clock::universal_time();
    // Call receive with timeout of 1s + 400000us = 1.4s.
    Pkt6Ptr pkt;
    ASSERT_NO_THROW(pkt = ifacemgr->receive6(1, 400000));
    // Remember when call to receive6() ended.
    ptime stop_time = microsec_clock::universal_time();
    // We did not send a packet to lo interface so we expect that
    // nothing has been received and timeout has been reached.
    ASSERT_FALSE(pkt);
    // Calculate duration of call to receive6().
    time_duration duration = stop_time - start_time;
    // We stop the clock when the call completes so it does not
    // precisely reflect the receive timeout. However the
    // uncertainty should be low enough to expect that measured
    // value is in the range <1.4s; 1.7s>.
    EXPECT_GE(duration.total_microseconds(),
              1400000 - TIMEOUT_TOLERANCE);
    EXPECT_LE(duration.total_microseconds(), 1700000);

    // Test timeout shorter than 1s.
    start_time = microsec_clock::universal_time();
    ASSERT_NO_THROW(pkt = ifacemgr->receive6(0, 500000));
    stop_time = microsec_clock::universal_time();
    ASSERT_FALSE(pkt);
    duration = stop_time - start_time;
    // Check if measured duration is within <0.5s; 0.8s>.
    EXPECT_GE(duration.total_microseconds(),
              500000 - TIMEOUT_TOLERANCE);
    EXPECT_LE(duration.total_microseconds(), 800000);

    // Test with invalid fractional timeout values.
    EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
    EXPECT_THROW(ifacemgr->receive6(1, 1000010), isc::BadValue);

    // Stop receiver.
    EXPECT_NO_THROW(ifacemgr->stopDHCPReceiver());
}

TEST_F(IfaceMgrTest, receiveTimeout4) {
    using namespace boost::posix_time;
    std::cout << "Testing DHCPv4 packet reception timeouts."
              << " Test will block for a few seconds when waiting"
              << " for timeout to occur." << std::endl;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
    // Open socket on the lo interface.
    IOAddress lo_addr("127.0.0.1");
    int socket1 = 0;
    ASSERT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10067)
    );
    // Socket is open if returned value is non-negative.
    ASSERT_GE(socket1, 0);

    // Start receiver.
    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));

    Pkt4Ptr pkt;
    // Remember when we call receive4().
    ptime start_time = microsec_clock::universal_time();
    // Call receive with timeout of 2s + 300000us = 2.3s.
    ASSERT_NO_THROW(pkt = ifacemgr->receive4(2, 300000));
    // Remember when call to receive4() ended.
    ptime stop_time = microsec_clock::universal_time();
    // We did not send a packet to lo interface so we expect that
    // nothing has been received and timeout has been reached.
    ASSERT_FALSE(pkt);
    // Calculate duration of call to receive4().
    time_duration duration = stop_time - start_time;
    // We stop the clock when the call completes so it does not
    // precisely reflect the receive timeout. However the
    // uncertainty should be low enough to expect that measured
    // value is in the range <2.3s; 2.6s>.
    EXPECT_GE(duration.total_microseconds(),
              2300000 - TIMEOUT_TOLERANCE);
    EXPECT_LE(duration.total_microseconds(), 2600000);

    // Test timeout shorter than 1s.
    start_time = microsec_clock::universal_time();
    ASSERT_NO_THROW(pkt = ifacemgr->receive4(0, 400000));
    stop_time = microsec_clock::universal_time();
    ASSERT_FALSE(pkt);
    duration = stop_time - start_time;
    // Check if measured duration is within <0.4s; 0.7s>.
    EXPECT_GE(duration.total_microseconds(),
              400000 - TIMEOUT_TOLERANCE);
    EXPECT_LE(duration.total_microseconds(), 700000);

    // Test with invalid fractional timeout values.
    EXPECT_THROW(ifacemgr->receive4(0, 1000000), isc::BadValue);
    EXPECT_THROW(ifacemgr->receive4(2, 1000005), isc::BadValue);

    // Stop receiver.
    EXPECT_NO_THROW(ifacemgr->stopDHCPReceiver());
}

TEST_F(IfaceMgrTest, multipleSockets) {
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Container for initialized socket descriptors
    std::list<uint16_t> init_sockets;

    // Create socket #1
    int socket1 = 0;
    ASSERT_NO_THROW(
        socket1 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT1, AF_INET);
    );
    ASSERT_GE(socket1, 0);
    init_sockets.push_back(socket1);

    // Create socket #2
    IOAddress lo_addr("127.0.0.1");
    int socket2 = 0;
    ASSERT_NO_THROW(
        socket2 = ifacemgr->openSocketFromRemoteAddress(lo_addr, PORT2);
    );
    ASSERT_GE(socket2, 0);
    init_sockets.push_back(socket2);

    // Get loopback interface. If we don't find one we are unable to run
    // this test but we don't want to fail.
    IfacePtr iface_ptr = ifacemgr->getIface(LOOPBACK_NAME);
    if (iface_ptr == NULL) {
        cout << "Local loopback interface not found. Skipping test. " << endl;
        return;
    }
    ASSERT_EQ(LOOPBACK_INDEX, iface_ptr->getIndex());
    // Once sockets have been successfully opened, they are supposed to
    // be on the list. Here we start to test if all expected sockets
    // are on the list and no other (unexpected) socket is there.
    Iface::SocketCollection sockets = iface_ptr->getSockets();
    int matched_sockets = 0;
    for (std::list<uint16_t>::iterator init_sockets_it =
             init_sockets.begin();
         init_sockets_it != init_sockets.end(); ++init_sockets_it) {
        // Set socket descriptors non blocking in order to be able
        // to call recv() on them without hang.
        int flags = fcntl(*init_sockets_it, F_GETFL, 0);
        ASSERT_GE(flags, 0);
        ASSERT_GE(fcntl(*init_sockets_it, F_SETFL, flags | O_NONBLOCK), 0);
        // recv() is expected to result in EWOULDBLOCK error on non-blocking
        // socket in case socket is valid but simply no data are coming in.
        char buf;
        recv(*init_sockets_it, &buf, 1, MSG_PEEK);
        EXPECT_EQ(EWOULDBLOCK, errno);
        // Apart from the ability to use the socket we want to make
        // sure that socket on the list is the one that we created.
        for (Iface::SocketCollection::const_iterator socket_it =
                 sockets.begin(); socket_it != sockets.end(); ++socket_it) {
            if (*init_sockets_it == socket_it->sockfd_) {
                // This socket is the one that we created.
                ++matched_sockets;
                break;
            }
        }
    }
    // All created sockets have been matched if this condition works.
    EXPECT_EQ(sockets.size(), matched_sockets);

    // closeSockets() is the other function that we want to test. It
    // is supposed to close all sockets so as we will not be able to use
    // them anymore communication.
    ifacemgr->closeSockets();

    // Closed sockets are supposed to be removed from the list
    sockets = iface_ptr->getSockets();
    ASSERT_EQ(0, sockets.size());

    // We are still in possession of socket descriptors that we created
    // on the beginning of this test. We can use them to check whether
    // closeSockets() only removed them from the list or they have been
    // really closed.
    for (std::list<uint16_t>::const_iterator init_sockets_it =
             init_sockets.begin();
         init_sockets_it != init_sockets.end(); ++init_sockets_it) {
        // recv() must result in error when using invalid socket.
        char buf;
        static_cast<void>(recv(*init_sockets_it, &buf, 1, MSG_PEEK));
        // EWOULDBLOCK would mean that socket is valid/open but
        // simply no data is received so we have to check for
        // other errors.
        EXPECT_NE(EWOULDBLOCK, errno);
    }
}

TEST_F(IfaceMgrTest, sockets6) {
    // Testing socket operation in a portable way is tricky
    // without interface detection implemented.

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    IOAddress lo_addr("::1");

    Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 123));
    pkt6->setIface(LOOPBACK_NAME);

    // Bind multicast socket to port 10547
    int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
    EXPECT_GE(socket1, 0); // socket >= 0

    EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));

    // Bind unicast socket to port 10548
    int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10548);
    EXPECT_GE(socket2, 0);

    // Removed code for binding socket twice to the same address/port
    // as it caused problems on some platforms (e.g. Mac OS X)

    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
    ifacemgr->closeSockets();

    // Use address that is not assigned to LOOPBACK iface.
    IOAddress invalidAddr("::2");
    EXPECT_THROW(
        ifacemgr->openSocket(LOOPBACK_NAME, invalidAddr, 10547),
        SocketConfigError
    );

    // Use non-existing interface name.
    EXPECT_THROW(
        ifacemgr->openSocket("non_existing_interface", lo_addr, 10548),
        BadValue
    );

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
}

TEST_F(IfaceMgrTest, socketsFromIface) {
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Open v6 socket on loopback interface and bind to port
    int socket1 = 0;
    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT1, AF_INET6);
    );
    // Socket descriptor must be non-negative integer
    EXPECT_GE(socket1, 0);
    close(socket1);

    // Open v4 socket on loopback interface and bind to different port
    int socket2 = 0;
    EXPECT_NO_THROW(
        socket2 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT2, AF_INET);
    );
    // socket descriptor must be non-negative integer
    EXPECT_GE(socket2, 0);
    close(socket2);

    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
    ifacemgr->closeSockets();

    // Use invalid interface name.
    EXPECT_THROW(
        ifacemgr->openSocketFromIface("non_existing_interface", PORT1, AF_INET),
        BadValue
    );

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
}


TEST_F(IfaceMgrTest, socketsFromAddress) {
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Open v6 socket on loopback interface and bind to port
    int socket1 = 0;
    IOAddress lo_addr6("::1");
    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocketFromAddress(lo_addr6, PORT1);
    );
    // socket descriptor must be non-negative integer
    EXPECT_GE(socket1, 0);

    // Open v4 socket on loopback interface and bind to different port
    int socket2 = 0;
    IOAddress lo_addr("127.0.0.1");
    EXPECT_NO_THROW(
        socket2 = ifacemgr->openSocketFromAddress(lo_addr, PORT2);
    );
    // socket descriptor must be positive integer
    EXPECT_GE(socket2, 0);

    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
    ifacemgr->closeSockets();

    // Use non-existing address.
    IOAddress invalidAddr("1.2.3.4");
    EXPECT_THROW(
        ifacemgr->openSocketFromAddress(invalidAddr, PORT1), BadValue
    );

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
}

TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Open v6 socket to connect to remote address.
    // Loopback address is the only one that we know
    // so let's treat it as remote address.
    int socket1 = 0;
    IOAddress lo_addr6("::1");
    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocketFromRemoteAddress(lo_addr6, PORT1);
    );
    EXPECT_GE(socket1, 0);

    // Open v4 socket to connect to remote address.
    int socket2 = 0;
    IOAddress lo_addr("127.0.0.1");
    EXPECT_NO_THROW(
        socket2 = ifacemgr->openSocketFromRemoteAddress(lo_addr, PORT2);
    );
    EXPECT_GE(socket2, 0);

    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
    ifacemgr->closeSockets();

    // There used to be a check here that verified the ability to open
    // suitable socket for sending broadcast request. However,
    // there is no guarantee for such test to work on all systems
    // because some systems may have no broadcast capable interfaces at all.
    // Thus, this check has been removed.

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
}

// TODO: disabled due to other naming on various systems
// (lo in Linux, lo0 in BSD systems)
TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
    // testing socket operation in a portable way is tricky
    // without interface detection implemented

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    IOAddress lo_addr("::1");
    IOAddress mcastAddr("ff02::1:2");

    // bind multicast socket to port 10547
    int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, mcastAddr, 10547);
    EXPECT_GE(socket1, 0); // socket > 0

    // expect success. This address/port is already bound, but
    // we are using SO_REUSEADDR, so we can bind it twice
    int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, mcastAddr, 10547);
    EXPECT_GE(socket2, 0);

    // there's no good way to test negative case here.
    // we would need non-multicast interface. We will be able
    // to iterate thru available interfaces and check if there
    // are interfaces without multicast-capable flag.

    close(socket1);
    close(socket2);
}

// Verifies that basic DHCPv6 packet send and receive operates
// in either direct or indirect mode.
TEST_F(IfaceMgrTest, sendReceive6) {
    data::ElementPtr queue_control;

    // Given an empty pointer, queueing should be disabled.
    // This should do direct reception.
    sendReceive6Test(queue_control, false);

    // Now let's populate queue control.
    queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, false);
    // With queueing disabled, we should use direct reception.
    sendReceive6Test(queue_control, false);

    // Queuing enabled, indirection reception should work.
    queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, true);
    sendReceive6Test(queue_control, true);
}

// Verifies that basic DHCPv4 packet send and receive operates
// in either direct or indirect mode.
TEST_F(IfaceMgrTest, sendReceive4) {
    data::ElementPtr queue_control;

    // Given an empty pointer, queueing should be disabled.
    // This should do direct reception.
    sendReceive4Test(queue_control, false);

    // Now let's populate queue control.
    queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, false);
    // With queueing disabled, we should use direct reception.
    sendReceive4Test(queue_control, false);

    // Queuing enabled, indirection reception should work.
    queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, true);
    sendReceive4Test(queue_control, true);
}

// Verifies that it is possible to set custom packet filter object
// to handle sockets opening and send/receive operation.
TEST_F(IfaceMgrTest, setPacketFilter) {

    // Create an instance of IfaceMgr.
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr);

    // Try to set NULL packet filter object and make sure it is rejected.
    boost::shared_ptr<TestPktFilter> custom_packet_filter;
    EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
                 isc::dhcp::InvalidPacketFilter);

    // Create valid object and check if it can be set.
    custom_packet_filter.reset(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));

    // Try to open socket using IfaceMgr. It should call the openSocket() function
    // on the packet filter object we have set.
    IOAddress lo_addr("127.0.0.1");
    int socket1 = 0;
    EXPECT_NO_THROW(
        socket1 = iface_mgr->openSocket(LOOPBACK_NAME, lo_addr,
                                        DHCP4_SERVER_PORT + 10000);
    );

    // Check that openSocket function was called.
    EXPECT_TRUE(custom_packet_filter->open_socket_called_);
    // This function always returns fake socket descriptor equal to 255.
    EXPECT_EQ(255, socket1);

    // Replacing current packet filter object while there are IPv4
    // sockets open is not allowed!
    EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
                 PacketFilterChangeDenied);

    // So, let's close the open sockets and retry. Now it should succeed.
    iface_mgr->closeSockets();
    EXPECT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
}

// This test checks that the default packet filter for DHCPv6 can be replaced
// with the custom one.
TEST_F(IfaceMgrTest, setPacketFilter6) {
    // Create an instance of IfaceMgr.
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr);

    // Try to set NULL packet filter object and make sure it is rejected.
    boost::shared_ptr<PktFilter6Stub> custom_packet_filter;
    EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
                 isc::dhcp::InvalidPacketFilter);

    // Create valid object and check if it can be set.
    custom_packet_filter.reset(new PktFilter6Stub());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));

    // Try to open socket using IfaceMgr. It should call the openSocket()
    // function on the packet filter object we have set.
    IOAddress lo_addr("::1");
    int socket1 = 0;
    EXPECT_NO_THROW(
        socket1 = iface_mgr->openSocket(LOOPBACK_NAME, lo_addr,
                                        DHCP6_SERVER_PORT + 10000);
    );
    // Check that openSocket function has been actually called on the packet
    // filter object.
    EXPECT_EQ(1, custom_packet_filter->open_socket_count_);
    // Also check that the returned socket descriptor has an expected value.
    EXPECT_EQ(0, socket1);

    // Replacing current packet filter object, while there are sockets open,
    // is not allowed!
    EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
                 PacketFilterChangeDenied);

    // So, let's close the sockets and retry. Now it should succeed.
    iface_mgr->closeSockets();
    EXPECT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
}

#if defined OS_LINUX || OS_BSD

// This test is only supported on Linux and BSD systems. It checks
// if it is possible to use the IfaceMgr to select the packet filter
// object which can be used to send direct responses to the host
// which doesn't have an address yet.
TEST_F(IfaceMgrTest, setMatchingPacketFilter) {

    // Create an instance of IfaceMgr.
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr);

    // Let IfaceMgr figure out which Packet Filter to use when
    // direct response capability is not desired. It should pick
    // PktFilterInet on Linux.
    EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(false));
    // The PktFilterInet is supposed to report lack of direct
    // response capability.
    EXPECT_FALSE(iface_mgr->isDirectResponseSupported());

    // There is working implementation of direct responses on Linux
    // and BSD (using PktFilterLPF and PktFilterBPF. When direct
    // responses are desired the object of this class should be set.
    EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(true));
    // This object should report that direct responses are supported.
    EXPECT_TRUE(iface_mgr->isDirectResponseSupported());
}

// This test checks that it is not possible to open two sockets: IP/UDP
// and raw socket and bind to the same address and port. The
// raw socket should be opened together with the fallback IP/UDP socket.
// The fallback socket should fail to open when there is another IP/UDP
// socket bound to the same address and port. Failing to open the fallback
// socket should preclude the raw socket from being open.
TEST_F(IfaceMgrTest, checkPacketFilterRawSocket) {
    IOAddress lo_addr("127.0.0.1");
    int socket1 = -1, socket2 = -1;
    // Create two instances of IfaceMgr.
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr1(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr1);
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr2(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr2);

    // Let IfaceMgr figure out which Packet Filter to use when
    // direct response capability is not desired. It should pick
    // PktFilterInet.
    EXPECT_NO_THROW(iface_mgr1->setMatchingPacketFilter(false));
    // Let's open a loopback socket with handy unpriviliged port number
    socket1 = iface_mgr1->openSocket(LOOPBACK_NAME, lo_addr,
                                     DHCP4_SERVER_PORT + 10000);

    EXPECT_GE(socket1, 0);

    // Then the second use PkFilterLPF mode
    EXPECT_NO_THROW(iface_mgr2->setMatchingPacketFilter(true));

    // The socket is open and bound. Another attempt to open socket and
    // bind to the same address and port should result in an exception.
    EXPECT_THROW(
        socket2 = iface_mgr2->openSocket(LOOPBACK_NAME, lo_addr,
                                         DHCP4_SERVER_PORT + 10000),
        isc::dhcp::SocketConfigError
    );
    // Surprisingly we managed to open another socket. We have to close it
    // to prevent resource leak.
    if (socket2 >= 0) {
        close(socket2);
        ADD_FAILURE() << "Two sockets opened and bound to the same IP"
            " address and UDP port";
    }

    if (socket1 >= 0) {
        close(socket1);
    }
}

#else

// Note: This test will only run on non-Linux and non-BSD systems.
// This test checks whether it is possible to use IfaceMgr to figure
// out which Packet Filter object should be used when direct responses
// to hosts, having no address assigned are desired or not desired.
// Since direct responses aren't supported on systems other than Linux
// and BSD the function under test should always set object of
// PktFilterInet type as current Packet Filter. This object does not
//support direct responses. Once implementation is added on systems
// other than BSD and Linux the OS specific version of the test will
// be removed.
TEST_F(IfaceMgrTest, setMatchingPacketFilter) {

    // Create an instance of IfaceMgr.
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr);

    // Let IfaceMgr figure out which Packet Filter to use when
    // direct response capability is not desired. It should pick
    // PktFilterInet.
    EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(false));
    // The PktFilterInet is supposed to report lack of direct
    // response capability.
    EXPECT_FALSE(iface_mgr->isDirectResponseSupported());

    // On non-Linux systems, we are missing the direct traffic
    // implementation. Therefore, we expect that PktFilterInet
    // object will be set.
    EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(true));
    // This object should report lack of direct response capability.
    EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
}

#endif

TEST_F(IfaceMgrTest, socket4) {

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Let's assume that every supported OS have lo interface.
    IOAddress lo_addr("127.0.0.1");
    // Use unprivileged port (it's convenient for running tests as non-root).
    int socket1 = 0;

    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr,
                                       DHCP4_SERVER_PORT + 10000);
    );

    EXPECT_GE(socket1, 0);

    Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1234));
    pkt->setIface(LOOPBACK_NAME);
    pkt->setIndex(LOOPBACK_INDEX);

    // Expect that we get the socket that we just opened.
    EXPECT_EQ(socket1, ifacemgr->getSocket(pkt).sockfd_);

    close(socket1);
}

// This test verifies that IPv4 sockets are open on all interfaces (except
// loopback), when interfaces are up, running and active (not disabled from
// the DHCP configuration).
TEST_F(IfaceMgrTest, openSockets4) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    // Use the custom packet filter object. This object mimics the socket
    // opening operation - the real socket is not open.
    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Simulate opening sockets using the dummy packet filter.
    ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));

    // Expect that the sockets are open on both eth0 and eth1.
    EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(ETH1_INDEX)->getSockets().size());
    // Socket shouldn't have been opened on loopback.
    EXPECT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
    EXPECT_TRUE(ifacemgr.getIface(LO_INDEX)->getSockets().empty());
}

// This test verifies that IPv4 sockets are open on the loopback interface
// when the loopback is active and allowed.
TEST_F(IfaceMgrTest, openSockets4Loopback) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    // Allow the loopback interface.
    ifacemgr.setAllowLoopBack(true);

    // Make the loopback interface active.
    ifacemgr.getIface("lo")->inactive4_ = false;

    // Use the custom packet filter object. This object mimics the socket
    // opening operation - the real socket is not open.
    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Simulate opening sockets using the dummy packet filter.
    ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));

    // Expect that the sockets are open on all interfaces.
    EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(ETH1_INDEX)->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface("lo")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(LO_INDEX)->getSockets().size());
}

// This test verifies that the socket is not open on the interface which is
// down, but sockets are open on all other non-loopback interfaces.
TEST_F(IfaceMgrTest, openSockets4IfaceDown) {
    IfaceMgrTestConfig config(true);

    // Boolean parameters specify that eth0 is:
    // - not a loopback
    // - is "down" (not up)
    // - is not running
    // - is active (is not inactive)
    config.setIfaceFlags("eth0", FlagLoopback(false), FlagUp(false),
                         FlagRunning(false), FlagInactive4(false),
                         FlagInactive6(false));
    ASSERT_FALSE(IfaceMgr::instance().getIface("eth0")->flag_up_);
    ASSERT_FALSE(IfaceMgr::instance().getIface(ETH0_INDEX)->flag_up_);

    // Install an error handler before trying to open sockets. This handler
    // should be called when the IfaceMgr fails to open socket on an interface
    // on which the server is configured to listen.
    isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
        std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);

    ASSERT_NO_THROW(IfaceMgr::instance().openSockets4(DHCP4_SERVER_PORT, true,
                                                      error_handler));
    // Since the interface is down, an attempt to open a socket should result
    // in error.
    EXPECT_EQ(1, errors_count_);

    // There should be no socket on eth0 open, because interface was down.
    EXPECT_TRUE(IfaceMgr::instance().getIface("eth0")->getSockets().empty());
    EXPECT_TRUE(IfaceMgr::instance().getIface(ETH0_INDEX)->getSockets().empty());

    // Expecting that the socket is open on eth1 because it was up, running
    // and active.
    EXPECT_EQ(2, IfaceMgr::instance().getIface("eth1")->getSockets().size());
    EXPECT_EQ(2, IfaceMgr::instance().getIface(ETH1_INDEX)->getSockets().size());
    // Same for eth1961.
    EXPECT_EQ(1, IfaceMgr::instance().getIface("eth1961")->getSockets().size());
    EXPECT_EQ(1, IfaceMgr::instance().getIface(ETH1961_INDEX)->getSockets().size());
    // Never open socket on loopback interface.
    EXPECT_TRUE(IfaceMgr::instance().getIface("lo")->getSockets().empty());
    EXPECT_TRUE(IfaceMgr::instance().getIface(LO_INDEX)->getSockets().empty());
}

// This test verifies that the socket is not open on the interface which is
// disabled from the DHCP configuration, but sockets are open on all other
// non-loopback interfaces.
TEST_F(IfaceMgrTest, openSockets4IfaceInactive) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Boolean parameters specify that eth1 is:
    // - not a loopback
    // - is up
    // - is running
    // - is inactive
    ifacemgr.setIfaceFlags("eth1", false, true, true, true, false);
    ASSERT_TRUE(ifacemgr.getIface("eth1")->inactive4_);
    ASSERT_TRUE(ifacemgr.getIface(ETH1_INDEX)->inactive4_);
    ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));

    // The socket on eth0 should be open because interface is up, running and
    // active (not disabled through DHCP configuration, for example).
    EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
    // There should be no socket open on eth1 because it was marked inactive.
    EXPECT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
    EXPECT_TRUE(ifacemgr.getIface(ETH1_INDEX)->getSockets().empty());
    // Sockets are not open on loopback interfaces too.
    EXPECT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
    EXPECT_TRUE(ifacemgr.getIface(LO_INDEX)->getSockets().empty());
}

// Test that exception is thrown when trying to bind a new socket to the port
// and address which is already in use by another socket.
TEST_F(IfaceMgrTest, openSockets4NoErrorHandler) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Open socket on eth1. The openSockets4 should detect that this
    // socket has been already open and an attempt to open another socket
    // and bind to this address and port should fail.
    ASSERT_NO_THROW(ifacemgr.openSocket("eth1", IOAddress("192.0.2.3"),
                                        DHCP4_SERVER_PORT));

    // The function throws an exception when it tries to open a socket
    // and bind it to the address in use.
    EXPECT_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0),
                 isc::dhcp::SocketConfigError);
}

// Test that the external error handler is called when trying to bind a new
// socket to the address and port being in use. The sockets on the other
// interfaces should open just fine.
TEST_F(IfaceMgrTest, openSocket4ErrorHandler) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Open socket on eth0.
    ASSERT_NO_THROW(ifacemgr.openSocket("eth0", IOAddress("10.0.0.1"),
                                        DHCP4_SERVER_PORT));

    // Install an error handler before trying to open sockets. This handler
    // should be called when the IfaceMgr fails to open socket on eth0.
    isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
        std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);
    // The openSockets4 should detect that there is another socket already
    // open and bound to the same address and port. An attempt to open
    // another socket and bind to this address and port should fail.
    ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, error_handler));
    // We expect that an error occurred when we tried to open a socket on
    // eth0, but the socket on eth1 should open just fine.
    EXPECT_EQ(1, errors_count_);

    // Reset errors count.
    errors_count_ = 0;

    // Now that we have two sockets open, we can try this again but this time
    // we should get two errors: one when opening a socket on eth0, another one
    // when opening a socket on eth1.
    ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, error_handler));
    EXPECT_EQ(2, errors_count_);
}

// Test that no exception is thrown when a port is already bound but skip open
// flag is provided.
TEST_F(IfaceMgrTest, openSockets4SkipOpen) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Open socket on eth1. The openSockets4 should detect that this
    // socket has been already open and an attempt to open another socket
    // and bind to this address and port should fail.
    ASSERT_NO_THROW(ifacemgr.openSocket("eth1", IOAddress("192.0.2.3"),
                                        DHCP4_SERVER_PORT));

    // The function doesn't throw an exception when it tries to open a socket
    // and bind it to the address in use but the skip open flag is provided.
    EXPECT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0, true));

    // Check that the other port is bound.
    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("10.0.0.1")));
}

// This test verifies that the function correctly checks that the v4 socket is
// open and bound to a specific address.
TEST_F(IfaceMgrTest, hasOpenSocketForAddress4) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    // Use the custom packet filter object. This object mimics the socket
    // opening operation - the real socket is not open.
    boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));

    // Simulate opening sockets using the dummy packet filter.
    ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));

    // Expect that the sockets are open on both eth0 and eth1.
    ASSERT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
    ASSERT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
    ASSERT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
    ASSERT_EQ(1, ifacemgr.getIface(ETH1_INDEX)->getSockets().size());
    // Socket shouldn't have been opened on loopback.
    ASSERT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
    ASSERT_TRUE(ifacemgr.getIface(LO_INDEX)->getSockets().empty());

    // Check that there are sockets bound to addresses that we have
    // set for interfaces.
    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("192.0.2.3")));
    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("10.0.0.1")));
    // Check that there is no socket for the address which is not
    // configured on any interface.
    EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("10.1.1.1")));

    // Check that v4 sockets are open, but no v6 socket is open.
    EXPECT_TRUE(ifacemgr.hasOpenSocket(AF_INET));
    EXPECT_FALSE(ifacemgr.hasOpenSocket(AF_INET6));
}

// This test checks that the sockets are open and bound to link local addresses
// only, if unicast addresses are not specified.
TEST_F(IfaceMgrTest, openSockets6LinkLocal) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that the number of sockets is correct on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);

    // Sockets on eth0 should be bound to link-local and should not be bound
    // to global unicast address, even though this address is configured on
    // the eth0.
    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
    // Socket on eth1 should be bound to link local only.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // If we are on Linux, there is one more socket bound to ff02::1:2
#if defined OS_LINUX
    EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// This test checks that the sockets are open on the loopback interface
// when the loopback is active and allowed.
TEST_F(IfaceMgrTest, openSockets6Loopback) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    // Allow the loopback interface.
    ifacemgr.setAllowLoopBack(true);

    // Make the loopback interface active.
    ifacemgr.getIface("lo")->inactive6_ = false;

    // The loopback interface has no link-local (as for Linux but not BSD)
    // so add one.
    ifacemgr.getIface("lo")->addUnicast(IOAddress("::1"));

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that the loopback interface has at least an open socket.
    EXPECT_EQ(1, ifacemgr.getIface("lo")->getSockets().size());
    EXPECT_EQ(1, ifacemgr.getIface(LO_INDEX)->getSockets().size());

    // This socket should be bound to ::1
    EXPECT_TRUE(ifacemgr.isBound("lo", "::1"));
}

// This test checks that socket is not open on the interface which doesn't
// have a link-local address.
TEST_F(IfaceMgrTest, openSockets6NoLinkLocal) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Remove a link local address from eth0. If there is no link-local
    // address, the socket should not open.
    ASSERT_TRUE(ifacemgr.getIface("eth0")->
                delAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that the number of sockets is correct on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    // The third parameter specifies that the number of link-local
    // addresses for eth0 is equal to 0.
    checkSocketsCount6(*ifacemgr.getIface("eth0"), 0, 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 0, 0);
    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0, 1);
    checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0, 1);

    // There should be no sockets open on eth0 because it neither has
    // link-local nor global unicast addresses.
    EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
    // Socket on eth1 should be bound to link local only.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // If we are on Linux, there is one more socket bound to ff02::1:2
#if defined OS_LINUX
    EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// This test checks that socket is open on the non-multicast-capable
// interface. This socket simply doesn't join multicast group.
TEST_F(IfaceMgrTest, openSockets6NotMulticast) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Make eth0 multicast-incapable.
    ifacemgr.getIface("eth0")->flag_multicast_ = false;

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that the number of sockets is correct on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);

    // Sockets on eth0 should be bound to link-local and should not be bound
    // to global unicast address, even though this address is configured on
    // the eth0.
    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
    // The eth0 is not a multicast-capable interface, so the socket should
    // not be bound to the multicast address.
    EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
    // Socket on eth1 should be bound to link local only.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // If we are on Linux, there is one more socket bound to ff02::1:2
    // on eth1.
#if defined OS_LINUX
    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// This test checks that the sockets are opened and bound to link local
// and unicast addresses which have been explicitly specified.
TEST_F(IfaceMgrTest, openSockets6Unicast) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Configure the eth0 to open socket on the unicast address, apart
    // from link-local address.
    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that we have correct number of sockets on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address.
    checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 1);
    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);

    // eth0 should have two sockets, one bound to link-local, another one
    // bound to unicast address.
    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
    // eth1 should have one socket, bound to link-local address.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // If we are on Linux, there is one more socket bound to ff02::1:2
#if defined OS_LINUX
    EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// This test checks that the socket is open and bound to a global unicast
// address if the link-local address does not exist for the particular
// interface.
TEST_F(IfaceMgrTest, openSockets6UnicastOnly) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Configure the eth0 to open socket on the unicast address, apart
    // from link-local address.
    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
    // Explicitly remove the link-local address from eth0.
    ASSERT_TRUE(ifacemgr.getIface("eth0")->
                delAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that we have correct number of sockets on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth0"), 1, 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 1, 0);
    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);

    // The link-local address is not present on eth0. Therefore, no socket
    // must be bound to this address, nor to multicast address.
    EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
    // There should be one socket bound to unicast address.
    EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
    // eth1 should have one socket, bound to link-local address.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // If we are on Linux, there is one more socket bound to ff02::1:2
#if defined OS_LINUX
    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// This test checks that no sockets are open for the interface which is down.
TEST_F(IfaceMgrTest, openSockets6IfaceDown) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Configure the eth0 to open socket on the unicast address, apart
    // from link-local address.
    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));

    // Boolean parameters specify that eth0 is:
    // - not a loopback
    // - is "down" (not up)
    // - is not running
    // - is active for both v4 and v6
    ifacemgr.setIfaceFlags("eth0", false, false, false, false, false);

    // Install an error handler before trying to open sockets. This handler
    // should be called when the IfaceMgr fails to open socket on eth0.
    isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
        std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT,
                                                    error_handler));
    EXPECT_TRUE(success);

    // Opening socket on the interface which is not configured, should
    // result in error.
    EXPECT_EQ(1, errors_count_);

    // Check that we have correct number of sockets on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    // There should be no sockets on eth0 because interface is down.
    ASSERT_TRUE(ifacemgr.getIface("eth0")->getSockets().empty());
    ASSERT_TRUE(ifacemgr.getIface(ETH0_INDEX)->getSockets().empty());
    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
    checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);

    // eth0 should have no sockets because the interface is down.
    EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
    EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
    // eth1 should have one socket, bound to link-local address.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // If we are on Linux, there is one more socket bound to ff02::1:2
#if defined OS_LINUX
    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// This test checks that no sockets are open for the interface which is
// inactive.
TEST_F(IfaceMgrTest, openSockets6IfaceInactive) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Configure the eth0 to open socket on the unicast address, apart
    // from link-local address.
    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));

    // Boolean parameters specify that eth1 is:
    // - not a loopback
    // - is up
    // - is running
    // - is active for v4
    // - is inactive for v6
    ifacemgr.setIfaceFlags("eth1", false, true, true, false, true);

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Check that we have correct number of sockets on each interface.
    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
    checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
    checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address
    checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 1);
    // There should be no sockets on eth1 because interface is inactive
    ASSERT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
    ASSERT_TRUE(ifacemgr.getIface(ETH1_INDEX)->getSockets().empty());

    // eth0 should have one socket bound to a link-local address, another one
    // bound to unicast address.
    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));

    // eth1 shouldn't have a socket bound to link local address because
    // interface is inactive.
    EXPECT_FALSE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
    EXPECT_FALSE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));

    // If we are on Linux, there is one more socket bound to ff02::1:2
#if defined OS_LINUX
    EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
#endif
}

// Test that the openSockets6 function does not throw if there are no interfaces
// detected. This function is expected to return false.
TEST_F(IfaceMgrTest, openSockets6NoIfaces) {
    NakedIfaceMgr ifacemgr;
    // Remove existing interfaces.
    ifacemgr.getIfacesLst().clear();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // This value indicates if at least one socket opens. There are no
    // interfaces, so it should be set to false.
    bool socket_open = false;
    ASSERT_NO_THROW(socket_open = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_FALSE(socket_open);
}

// Test that the external error handler is called when trying to bind a new
// socket to the address and port being in use. The sockets on the other
// interfaces should open just fine.
TEST_F(IfaceMgrTest, openSockets6ErrorHandler) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Open multicast socket on eth0.
    ASSERT_NO_THROW(ifacemgr.openSocket("eth0",
                                        IOAddress("fe80::3a60:77ff:fed5:cdef"),
                                        DHCP6_SERVER_PORT, true));

    // Install an error handler before trying to open sockets. This handler
    // should be called when the IfaceMgr fails to open socket on eth0.
    isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
        std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);
    // The openSockets6 should detect that a socket has been already
    // opened on eth0 and an attempt to open another socket and bind to
    // the same address and port should fail.
    ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
    // We expect that an error occurred when we tried to open a socket on
    // eth0, but the socket on eth1 should open just fine.
    EXPECT_EQ(1, errors_count_);

    // Reset errors count.
    errors_count_ = 0;

    // Now that we have two sockets open, we can try this again but this time
    // we should get two errors: one when opening a socket on eth0, another one
    // when opening a socket on eth1.
    ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
    EXPECT_EQ(2, errors_count_);
}

// Test that no exception is thrown when a port is already bound but skip open
// flag is provided.
TEST_F(IfaceMgrTest, openSockets6SkipOpen) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Open socket on eth0. The openSockets6 should detect that this
    // socket has been already open and an attempt to open another socket
    // and bind to this address and port should fail.
    ASSERT_NO_THROW(ifacemgr.openSocket("eth0",
                                        IOAddress("fe80::3a60:77ff:fed5:cdef"),
                                        DHCP6_SERVER_PORT, true));

    // The function doesn't throw an exception when it tries to open a socket
    // and bind it to the address in use but the skip open flag is provided.
    EXPECT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, 0, true));

    // Check that the other port is bound.
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
}

// This test verifies that the function correctly checks that the v6 socket is
// open and bound to a specific address.
TEST_F(IfaceMgrTest, hasOpenSocketForAddress6) {
    NakedIfaceMgr ifacemgr;

    // Remove all real interfaces and create a set of dummy interfaces.
    ifacemgr.createIfaces();

    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
    ASSERT_TRUE(filter);
    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));

    // Simulate opening sockets using the dummy packet filter.
    bool success = false;
    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
    EXPECT_TRUE(success);

    // Make sure that the sockets are bound as expected.
    ASSERT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));

    // There should be v6 sockets only, no v4 sockets.
    EXPECT_TRUE(ifacemgr.hasOpenSocket(AF_INET6));
    EXPECT_FALSE(ifacemgr.hasOpenSocket(AF_INET));

    // Check that there are sockets bound to the addresses we have configured
    // for interfaces.
    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:cdef")));
    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:abcd")));
    // Check that there is no socket bound to the address which hasn't been
    // configured on any interface.
    EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:feed:1")));
}

// Test the Iface structure itself
TEST_F(IfaceMgrTest, iface) {
    boost::scoped_ptr<Iface> iface;
    EXPECT_NO_THROW(iface.reset(new Iface("eth0",1)));

    EXPECT_EQ("eth0", iface->getName());
    EXPECT_EQ(1, iface->getIndex());
    EXPECT_EQ("eth0/1", iface->getFullName());

    // Let's make a copy of this address collection.
    Iface::AddressCollection addrs = iface->getAddresses();

    EXPECT_EQ(0, addrs.size());

    IOAddress addr1("192.0.2.6");
    iface->addAddress(addr1);

    addrs = iface->getAddresses();
    ASSERT_EQ(1, addrs.size());
    EXPECT_EQ("192.0.2.6", addrs.begin()->get().toText());

    // No such address, should return false.
    EXPECT_FALSE(iface->delAddress(IOAddress("192.0.8.9")));

    // This address is present, delete it!
    EXPECT_TRUE(iface->delAddress(IOAddress("192.0.2.6")));

    // Not really necessary, previous reference still points to the same
    // collection. Let's do it anyway, as test code may serve as example
    // usage code as well.
    addrs = iface->getAddresses();

    EXPECT_EQ(0, addrs.size());

    EXPECT_NO_THROW(iface.reset());
}

TEST_F(IfaceMgrTest, iface_methods) {
    Iface iface("foo", 1234);

    iface.setHWType(42);
    EXPECT_EQ(42, iface.getHWType());

    ASSERT_LT(Iface::MAX_MAC_LEN + 10, 255);

    uint8_t mac[Iface::MAX_MAC_LEN+10];
    for (uint8_t i = 0; i < Iface::MAX_MAC_LEN + 10; i++) {
        mac[i] = 255 - i;
    }

    EXPECT_EQ("foo", iface.getName());
    EXPECT_EQ(1234, iface.getIndex());

    // MAC is too long. Exception should be thrown and
    // MAC length should not be set.
    EXPECT_THROW(
        iface.setMac(mac, Iface::MAX_MAC_LEN + 1),
        OutOfRange
    );

    // MAC length should stay not set as exception was thrown.
    EXPECT_EQ(0, iface.getMacLen());

    // Setting maximum length MAC should be ok.
    iface.setMac(mac, Iface::MAX_MAC_LEN);

    // For some reason constants cannot be used directly in EXPECT_EQ
    // as this produces linking error.
    size_t len = Iface::MAX_MAC_LEN;
    EXPECT_EQ(len, iface.getMacLen());
    EXPECT_EQ(0, memcmp(mac, iface.getMac(), iface.getMacLen()));
}

TEST_F(IfaceMgrTest, socketInfo) {

    // Check that socketinfo for IPv4 socket is functional
    SocketInfo sock1(IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7, 7);
    EXPECT_EQ(7, sock1.sockfd_);
    EXPECT_EQ(-1, sock1.fallbackfd_);
    EXPECT_EQ("192.0.2.56", sock1.addr_.toText());
    EXPECT_EQ(AF_INET, sock1.family_);
    EXPECT_EQ(DHCP4_SERVER_PORT + 7, sock1.port_);

    // Check that non-default value of the fallback socket descriptor is set
    SocketInfo sock2(IOAddress("192.0.2.53"), DHCP4_SERVER_PORT + 8, 8, 10);
    EXPECT_EQ(8, sock2.sockfd_);
    EXPECT_EQ(10, sock2.fallbackfd_);
    EXPECT_EQ("192.0.2.53", sock2.addr_.toText());
    EXPECT_EQ(AF_INET, sock2.family_);
    EXPECT_EQ(DHCP4_SERVER_PORT + 8, sock2.port_);

    // Check that socketinfo for IPv6 socket is functional
    SocketInfo sock3(IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9, 9);
    EXPECT_EQ(9, sock3.sockfd_);
    EXPECT_EQ(-1, sock3.fallbackfd_);
    EXPECT_EQ("2001:db8:1::56", sock3.addr_.toText());
    EXPECT_EQ(AF_INET6, sock3.family_);
    EXPECT_EQ(DHCP4_SERVER_PORT + 9, sock3.port_);

    // Now let's test if IfaceMgr handles socket info properly
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
    IfacePtr loopback = ifacemgr->getIface(LOOPBACK_NAME);
    ASSERT_TRUE(loopback);
    loopback->addSocket(sock1);
    loopback->addSocket(sock2);
    loopback->addSocket(sock3);

    Pkt6Ptr pkt6(new Pkt6(DHCPV6_REPLY, 123456));

    // pkt6 does not have interface set yet
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        IfaceNotFound
    );

    // Try to send over non-existing interface
    pkt6->setIface("nosuchinterface45");
    pkt6->setIndex(12345);
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        IfaceNotFound
    );

    // Index is now checked first
    pkt6->setIface(LOOPBACK_NAME);
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        IfaceNotFound
    );

    // This will work
    pkt6->setIndex(LOOPBACK_INDEX);
    EXPECT_EQ(9, ifacemgr->getSocket(pkt6));

    bool deleted = false;
    EXPECT_NO_THROW(
        deleted = ifacemgr->getIface(LOOPBACK_NAME)->delSocket(9);
    );
    EXPECT_EQ(true, deleted);

    // It should throw again, there's no usable socket anymore
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        SocketNotFound
    );

    // Repeat for pkt4
    Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 1));

    // pkt4 does not have interface set yet.
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        IfaceNotFound
    );

    // Try to send over non-existing interface.
    pkt4->setIface("nosuchinterface45");
    pkt4->setIndex(12345);
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        IfaceNotFound
    );

    // Index is now checked first.
    pkt4->setIface(LOOPBACK_NAME);
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        IfaceNotFound
    );

    // Socket info is set, packet has well defined interface. It should work.
    pkt4->setIndex(LOOPBACK_INDEX);
    EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);

    // Set the local address to check if the socket for this address will
    // be returned.
    pkt4->setLocalAddr(IOAddress("192.0.2.56"));
    EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);

    // Modify the local address and expect that the other socket will be
    // returned.
    pkt4->setLocalAddr(IOAddress("192.0.2.53"));
    EXPECT_EQ(8, ifacemgr->getSocket(pkt4).sockfd_);

    EXPECT_NO_THROW(
        ifacemgr->getIface(LOOPBACK_NAME)->delSocket(7);
        ifacemgr->getIface(LOOPBACK_NAME)->delSocket(8);
    );

    // It should throw again, there's no usable socket anymore.
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        SocketNotFound
    );
}

#if defined(OS_BSD)
#include <net/if_dl.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#endif

#include <sys/socket.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <net/if.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <ifaddrs.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

/// @brief Checks the index of this interface
/// @param iface Kea interface structure to be checked
/// @param ifptr original structure returned by getifaddrs
/// @return true if index is returned properly
bool
checkIfIndex(const Iface & iface,
             struct ifaddrs *& ifptr) {
    return (iface.getIndex() == if_nametoindex(ifptr->ifa_name));
}

/// @brief Checks if the interface has proper flags set
/// @param iface Kea interface structure to be checked
/// @param ifptr original structure returned by getifaddrs
/// @return true if flags are set properly
bool
checkIfFlags(const Iface & iface,
             struct ifaddrs *& ifptr) {
        bool flag_loopback_ = ifptr->ifa_flags & IFF_LOOPBACK;
        bool flag_up_ = ifptr->ifa_flags & IFF_UP;
        bool flag_running_ = ifptr->ifa_flags & IFF_RUNNING;
        bool flag_multicast_ = ifptr->ifa_flags & IFF_MULTICAST;

    return ((iface.flag_loopback_ == flag_loopback_) &&
                        (iface.flag_up_ == flag_up_) &&
                        (iface.flag_running_ == flag_running_) &&
                        (iface.flag_multicast_ == flag_multicast_));
}

/// @brief Checks if MAC Address/IP Addresses are properly well formed
/// @param iface Kea interface structure to be checked
/// @param ifptr original structure returned by getifaddrs
/// @return true if addresses are returned properly
bool
checkIfAddrs(const Iface & iface, struct ifaddrs *& ifptr) {
    const unsigned char * p = 0;
#if defined(OS_LINUX)
    // Workaround for Linux ...
    if(ifptr->ifa_data != 0) {
        // We avoid localhost as it has no MAC Address
        if (!strncmp(iface.getName().c_str(), "lo", 2)) {
            return (true);
        }

        struct ifreq ifr;
        memset(& ifr.ifr_name, 0, sizeof ifr.ifr_name);
        strncpy(ifr.ifr_name, iface.getName().c_str(), sizeof(ifr.ifr_name) - 1);

        int s = -1; // Socket descriptor

        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            isc_throw(Unexpected, "Cannot create AF_INET socket");
        }

        if (ioctl(s, SIOCGIFHWADDR, & ifr) < 0) {
            close(s);
            isc_throw(Unexpected, "Cannot set SIOCGIFHWADDR flag");
        }

        p = reinterpret_cast<uint8_t *>(ifr.ifr_ifru.ifru_hwaddr.sa_data);

        close(s);

        /// @todo: Check MAC address length. For some interfaces it is
        /// different than 6. Some have 0, while some exotic ones (like
        /// infiniband) have 20.
        return (!memcmp(p, iface.getMac(), iface.getMacLen()));
    }
#endif

    if(!ifptr->ifa_addr) {
        return (false);
    }

    switch(ifptr->ifa_addr->sa_family) {
#if defined(OS_BSD)
        case AF_LINK: {
            // We avoid localhost as it has no MAC Address
            if (!strncmp(iface.getName().c_str(), "lo", 2)) {
                return (true);
            }

            struct sockaddr_dl * hwdata =
                   reinterpret_cast<struct sockaddr_dl *>(ifptr->ifa_addr);
            p = reinterpret_cast<uint8_t *>(LLADDR(hwdata));

            // Extract MAC address length
            if (hwdata->sdl_alen != iface.getMacLen()) {
                return (false);
            }

            return (!memcmp(p, iface.getMac(), hwdata->sdl_alen));
        }
#endif
        case AF_INET: {
            struct sockaddr_in * v4data =
                   reinterpret_cast<struct sockaddr_in *>(ifptr->ifa_addr);
            p = reinterpret_cast<uint8_t *>(& v4data->sin_addr);

            IOAddress addrv4 = IOAddress::fromBytes(AF_INET, p);

            for (auto const& a :iface.getAddresses()) {
                if(a.get().isV4() && (a.get()) == addrv4) {
                    return (true);
                }
            }

            return (false);
        }
        case AF_INET6: {
            struct sockaddr_in6 * v6data =
                   reinterpret_cast<struct sockaddr_in6 *>(ifptr->ifa_addr);
            p = reinterpret_cast<uint8_t *>(& v6data->sin6_addr);

            IOAddress addrv6 = IOAddress::fromBytes(AF_INET6, p);

            for (auto const&  a : iface.getAddresses()) {
                if (a.get().isV6() && (a.get() == addrv6)) {
                    return (true);
                }
            }

            return (false);
        }
        default:
            return (true);
    }
}

/// This test checks that the IfaceMgr detects interfaces correctly and
/// that detected interfaces have correct properties.
TEST_F(IfaceMgrTest, detectIfaces) {
    NakedIfaceMgr ifacemgr;

    // We are using struct ifaddrs as it is the only good portable one
    // ifreq and ioctls are far from portable. For BSD ifreq::ifa_flags field
    // is only a short which, nowadays, can be negative
    struct ifaddrs *iflist = 0, *ifptr = 0;
    ASSERT_EQ(0, getifaddrs(&iflist))
        << "Unit test failed to detect interfaces.";

    // Go over all interfaces detected by the unit test and see if they
    // match with the interfaces detected by IfaceMgr.
    for (ifptr = iflist; ifptr != 0; ifptr = ifptr->ifa_next) {
        // When more than one IPv4 address is assigned to the particular
        // physical interface, virtual interfaces may be created for each
        // additional IPv4 address. For example, when multiple addresses
        // are assigned to the eth0 interface, additional virtual interfaces
        // will be eth0:0, eth0:1 etc. This is the case on some Linux
        // distributions. The getifaddrs will return virtual interfaces,
        // with single address each, but the Netlink-based implementation
        // (used by IfaceMgr) will rather hold a list of physical interfaces
        // with multiple IPv4 addresses assigned. This means that the test
        // can't use a name of the interface returned by getifaddrs to match
        // with the interface name held by IfaceMgr. Instead, we use the
        // index of the interface because the virtual interfaces have the
        // same indexes as the physical interfaces.
        IfacePtr i = ifacemgr.getIface(if_nametoindex(ifptr->ifa_name));

        // If the given interface was also detected by the IfaceMgr,
        // check that its properties are correct.
        if (i != NULL) {
            // Check if interface index is reported properly
            EXPECT_TRUE(checkIfIndex(*i, ifptr))
                << "Non-matching index of the detected interface "
                << i->getName();

            // Check if flags are reported properly
            EXPECT_TRUE(checkIfFlags(*i, ifptr))
                << "Non-matching flags of the detected interface "
                << i->getName();

            // Check if addresses are reported properly
            EXPECT_TRUE(checkIfAddrs(*i, ifptr))
                << "Non-matching addresses on the detected interface "
                << i->getName();

        } else {
            // The interface detected here seems to be missing in the
            // IfaceMgr.
            ADD_FAILURE() << "Interface " << ifptr->ifa_name
                          << " not detected by the Interface Manager";
        }
    }

    freeifaddrs(iflist);
    iflist = 0;
}

volatile bool callback_ok;
volatile bool callback2_ok;

void my_callback(int /* fd */) {
    callback_ok = true;
}

void my_callback2(int /* fd */) {
    callback2_ok = true;
}

// Tests if a single external socket and its callback can be passed and
// it is supported properly by receive4() method.
TEST_F(IfaceMgrTest, SingleExternalSocket4) {

    callback_ok = false;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Create pipe and register it as extra socket
    int pipefd[2];
    EXPECT_TRUE(pipe(pipefd) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));

    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));

    Pkt4Ptr pkt4;
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));

    // Our callback should not be called this time (there was no data)
    EXPECT_FALSE(callback_ok);

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt4);

    // Now, send some data over pipe (38 bytes)
    EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt4);

    // There was some data, so this time callback should be called
    EXPECT_TRUE(callback_ok);

    // close both pipe ends
    close(pipefd[1]);
    close(pipefd[0]);

    ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
}

// Tests if multiple external sockets and their callbacks can be passed and
// it is supported properly by receive4() method.
TEST_F(IfaceMgrTest, MultipleExternalSockets4) {

    callback_ok = false;
    callback2_ok = false;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Create first pipe and register it as extra socket
    int pipefd[2];
    EXPECT_TRUE(pipe(pipefd) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));

    // Let's create a second pipe and register it as well
    int secondpipe[2];
    EXPECT_TRUE(pipe(secondpipe) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));

    Pkt4Ptr pkt4;
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));

    // Our callbacks should not be called this time (there was no data)
    EXPECT_FALSE(callback_ok);
    EXPECT_FALSE(callback2_ok);

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt4);

    // Now, send some data over the first pipe (38 bytes)
    EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt4);

    // There was some data, so this time callback should be called
    EXPECT_TRUE(callback_ok);
    EXPECT_FALSE(callback2_ok);

    // Read the data sent, because our test callbacks are too dumb to actually
    // do it. We don't care about the content read, because we're testing
    // the callbacks, not pipes.
    char buf[80];
    EXPECT_EQ(38, read(pipefd[0], buf, 80));

    // Clear the status...
    callback_ok = false;
    callback2_ok = false;

    // And try again, using the second pipe
    EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt4);

    // There was some data, so this time callback should be called
    EXPECT_FALSE(callback_ok);
    EXPECT_TRUE(callback2_ok);

    // close both pipe ends
    close(pipefd[1]);
    close(pipefd[0]);

    close(secondpipe[1]);
    close(secondpipe[0]);
}

// Tests if existing external socket can be deleted and that such deletion does
// not affect any other existing sockets. Tests uses receive4()
TEST_F(IfaceMgrTest, DeleteExternalSockets4) {

    callback_ok = false;
    callback2_ok = false;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Create first pipe and register it as extra socket
    int pipefd[2];
    EXPECT_TRUE(pipe(pipefd) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));

    // Let's create a second pipe and register it as well
    int secondpipe[2];
    EXPECT_TRUE(pipe(secondpipe) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));

    // Now delete the first session socket
    EXPECT_NO_THROW(ifacemgr->deleteExternalSocket(pipefd[0]));

    // Now check whether the second callback is still functional
    EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    Pkt4Ptr pkt4;
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt4);

    // There was some data, so this time callback should be called
    EXPECT_FALSE(callback_ok);
    EXPECT_TRUE(callback2_ok);

    // Let's reset the status
    callback_ok = false;
    callback2_ok = false;

    // Now let's send something over the first callback that was unregistered.
    // We should NOT receive any callback.
    EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));

    // Now check that the first callback is NOT called.
    ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
    EXPECT_FALSE(callback_ok);

    // close both pipe ends
    close(pipefd[1]);
    close(pipefd[0]);

    close(secondpipe[1]);
    close(secondpipe[0]);
}

// Tests that an existing external socket that becomes invalid
// is detected and purged, without affecting other sockets.
// Tests uses receive4() without queuing.
TEST_F(IfaceMgrTest, purgeExternalSockets4Direct) {
    purgeExternalSockets4Test();
}


// Tests that an existing external socket that becomes invalid
// is detected and purged, without affecting other sockets.
// Tests uses receive4() with queuing.
TEST_F(IfaceMgrTest, purgeExternalSockets4Indirect) {
    purgeExternalSockets4Test(true);
}

// Tests if a single external socket and its callback can be passed and
// it is supported properly by receive6() method.
TEST_F(IfaceMgrTest, SingleExternalSocket6) {

    callback_ok = false;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Create pipe and register it as extra socket
    int pipefd[2];
    EXPECT_TRUE(pipe(pipefd) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));

    Pkt6Ptr pkt6;
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));

    // Our callback should not be called this time (there was no data)
    EXPECT_FALSE(callback_ok);

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt6);

    // Now, send some data over pipe (38 bytes)
    EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt6);

    // There was some data, so this time callback should be called
    EXPECT_TRUE(callback_ok);

    // close both pipe ends
    close(pipefd[1]);
    close(pipefd[0]);
}

// Tests if multiple external sockets and their callbacks can be passed and
// it is supported properly by receive6() method.
TEST_F(IfaceMgrTest, MultipleExternalSockets6) {

    callback_ok = false;
    callback2_ok = false;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Create first pipe and register it as extra socket
    int pipefd[2];
    EXPECT_TRUE(pipe(pipefd) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));

    // Let's create a second pipe and register it as well
    int secondpipe[2];
    EXPECT_TRUE(pipe(secondpipe) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));

    Pkt6Ptr pkt6;
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));

    // Our callbacks should not be called this time (there was no data)
    EXPECT_FALSE(callback_ok);
    EXPECT_FALSE(callback2_ok);

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt6);

    // Now, send some data over the first pipe (38 bytes)
    EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt6);

    // There was some data, so this time callback should be called
    EXPECT_TRUE(callback_ok);
    EXPECT_FALSE(callback2_ok);

    // Read the data sent, because our test callbacks are too dumb to actually
    // do it. We don't care about the content read, because we're testing
    // the callbacks, not pipes.
    char buf[80];
    EXPECT_EQ(38, read(pipefd[0], buf, 80));

    // Clear the status...
    callback_ok = false;
    callback2_ok = false;

    // And try again, using the second pipe
    EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt6);

    // There was some data, so this time callback should be called
    EXPECT_FALSE(callback_ok);
    EXPECT_TRUE(callback2_ok);

    // close both pipe ends
    close(pipefd[1]);
    close(pipefd[0]);

    close(secondpipe[1]);
    close(secondpipe[0]);
}

// Tests if existing external socket can be deleted and that such deletion does
// not affect any other existing sockets. Tests uses receive6()
TEST_F(IfaceMgrTest, DeleteExternalSockets6) {

    callback_ok = false;
    callback2_ok = false;

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Create first pipe and register it as extra socket
    int pipefd[2];
    EXPECT_TRUE(pipe(pipefd) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));

    // Let's create a second pipe and register it as well
    int secondpipe[2];
    EXPECT_TRUE(pipe(secondpipe) == 0);
    EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));

    // Now delete the first session socket
    EXPECT_NO_THROW(ifacemgr->deleteExternalSocket(pipefd[0]));

    // Now check whether the second callback is still functional
    EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));

    // ... and repeat
    Pkt6Ptr pkt6;
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));

    // IfaceMgr should not process control socket data as incoming packets
    EXPECT_FALSE(pkt6);

    // There was some data, so this time callback should be called
    EXPECT_FALSE(callback_ok);
    EXPECT_TRUE(callback2_ok);

    // Let's reset the status
    callback_ok = false;
    callback2_ok = false;

    // Now let's send something over the first callback that was unregistered.
    // We should NOT receive any callback.
    EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));

    // Now check that the first callback is NOT called.
    ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
    EXPECT_FALSE(callback_ok);

    // close both pipe ends
    close(pipefd[1]);
    close(pipefd[0]);

    close(secondpipe[1]);
    close(secondpipe[0]);
}

// Tests that an existing external socket that becomes invalid
// is detected and purged, without affecting other sockets.
// Tests uses receive6() without queuing.
TEST_F(IfaceMgrTest, purgeExternalSockets6Direct) {
    purgeExternalSockets6Test();
}


// Tests that an existing external socket that becomes invalid
// is detected and purged, without affecting other sockets.
// Tests uses receive6() with queuing.
TEST_F(IfaceMgrTest, purgeExternalSockets6Indirect) {
    purgeExternalSockets6Test(true);
}

// Test checks if the unicast sockets can be opened.
// This test is now disabled, because there is no reliable way to test it. We
// can't even use loopback, because openSockets() skips loopback interface
// (as it should be, because DHCP server is not supposed to listen on loopback).
TEST_F(IfaceMgrTest, DISABLED_openUnicastSockets) {
    /// @todo Need to implement a test that is able to check whether we can open
    /// unicast sockets. There are 2 problems with it:
    /// 1. We need to have a non-link-local address on an interface that is
    ///    up, running, IPv6 and multicast capable
    /// 2. We need that information on every OS that we run tests on. So far
    ///    we are only supporting interface detection in Linux.
    ///
    /// To achieve this, we will probably need a pre-test setup, similar to what
    /// BIND9 is doing (i.e. configuring well known addresses on loopback).

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // Get the interface (todo: which interface)
    IfacePtr iface = ifacemgr->getIface("eth0");
    ASSERT_TRUE(iface);
    iface->inactive6_ = false;

    // Tell the interface that it should bind to this global interface
    EXPECT_NO_THROW(iface->addUnicast(IOAddress("2001:db8::1")));

    // Tell IfaceMgr to open sockets. This should trigger at least 2 sockets
    // to open on eth0: link-local and global. On some systems (Linux), an
    // additional socket for multicast may be opened.
    EXPECT_TRUE(ifacemgr->openSockets6(PORT1));

    const Iface::SocketCollection& sockets = iface->getSockets();
    ASSERT_GE(2, sockets.size());

    // Global unicast should be first
    EXPECT_TRUE(getSocketByAddr(sockets, IOAddress("2001:db8::1")));
    EXPECT_TRUE(getSocketByAddr(sockets, IOAddress("figure-out-link-local-addr")));
}

// Checks if there is a protection against unicast duplicates.
TEST_F(IfaceMgrTest, unicastDuplicates) {
    NakedIfaceMgr ifacemgr;

    IfacePtr iface = ifacemgr.getIface(LOOPBACK_NAME);
    if (!iface) {
        cout << "Local loopback interface not found. Skipping test. " << endl;
        return;
    }

    // Tell the interface that it should bind to this global interface
    // It is the first attempt so it should succeed
    EXPECT_NO_THROW(iface->addUnicast(IOAddress("2001:db8::1")));

    // Tell the interface that it should bind to this global interface
    // It is the second attempt so it should fail
    EXPECT_THROW(iface->addUnicast(IOAddress("2001:db8::1")), BadValue);
}

// This test requires addresses 2001:db8:15c::1/128 and fe80::1/64 to be
// configured on loopback interface
//
// Useful commands:
// ip a a 2001:db8:15c::1/128 dev lo
// ip a a fe80::1/64 dev lo
//
// If you do not issue those commands before running this test, it will fail.
TEST_F(IfaceMgrTest, DISABLED_getSocket) {
    // Testing socket operation in a portable way is tricky
    // without interface detection implemented.

    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    IOAddress lo_addr("::1");
    IOAddress link_local("fe80::1");
    IOAddress global("2001:db8:15c::1");

    IOAddress dst_link_local("fe80::dead:beef");
    IOAddress dst_global("2001:db8:15c::dead:beef");

    // Bind loopback address
    int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
    EXPECT_GE(socket1, 0); // socket >= 0

    // Bind link-local address
    int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, link_local, 10547);
    EXPECT_GE(socket2, 0);

    int socket3 = ifacemgr->openSocket(LOOPBACK_NAME, global, 10547);
    EXPECT_GE(socket3, 0);

    // Let's make sure those sockets are unique
    EXPECT_NE(socket1, socket2);
    EXPECT_NE(socket2, socket3);
    EXPECT_NE(socket3, socket1);

    // Create a packet
    Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 123));
    pkt6->setIface(LOOPBACK_NAME);
    pkt6->setIndex(LOOPBACK_INDEX);

    // Check that packets sent to link-local will get socket bound to link local
    pkt6->setLocalAddr(global);
    pkt6->setRemoteAddr(dst_global);
    EXPECT_EQ(socket3, ifacemgr->getSocket(pkt6));

    // Check that packets sent to link-local will get socket bound to link local
    pkt6->setLocalAddr(link_local);
    pkt6->setRemoteAddr(dst_link_local);
    EXPECT_EQ(socket2, ifacemgr->getSocket(pkt6));

    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
    ifacemgr->closeSockets();
}

// Verifies DHCPv4 behavior of configureDHCPPacketQueue()
TEST_F(IfaceMgrTest, configureDHCPPacketQueueTest4) {
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // First let's make sure there is no queue and no thread.
    ASSERT_FALSE(ifacemgr->getPacketQueue4());
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    bool queue_enabled = false;
    // Given an empty pointer, we should default to no queue.
    data::ConstElementPtr queue_control;
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
    EXPECT_FALSE(queue_enabled);
    EXPECT_FALSE(ifacemgr->getPacketQueue4());
    // configureDHCPPacketQueue() should never start the thread.
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Verify that calling startDHCPReceiver with no queue, does NOT start the thread.
    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Now let's try with a populated queue control, but with enable-queue = false.
    queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, false);
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
    EXPECT_FALSE(queue_enabled);
    EXPECT_FALSE(ifacemgr->getPacketQueue4());
    // configureDHCPPacketQueue() should never start the thread.
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Now let's enable the queue.
    queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, true);
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
    ASSERT_TRUE(queue_enabled);
    // Verify we have correctly created the queue.
    CHECK_QUEUE_INFO(ifacemgr->getPacketQueue4(), "{ \"capacity\": 500, \"queue-type\": \""
                     << PacketQueueMgr4::DEFAULT_QUEUE_TYPE4 << "\", \"size\": 0 }");
    // configureDHCPPacketQueue() should never start the thread.
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Calling startDHCPReceiver with a queue, should start the thread.
    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
    ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());

    // Verify that calling startDHCPReceiver when the thread is running, throws.
    ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET), InvalidOperation);

    // Create a disabled config.
    queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, false);

    // Trying to reconfigure with a running thread should throw.
    ASSERT_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control),
                 InvalidOperation);

    // We should still have our queue and the thread should still be running.
    EXPECT_TRUE(ifacemgr->getPacketQueue4());
    ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());

    // Now let's stop stop the thread.
    ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
    // Stopping the thread should not destroy the queue.
    ASSERT_TRUE(ifacemgr->getPacketQueue4());

    // Reconfigure with the queue turned off.  We should have neither queue nor thread.
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
    EXPECT_FALSE(ifacemgr->getPacketQueue4());
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
}

// Verifies DHCPv6 behavior of configureDHCPPacketQueue()
TEST_F(IfaceMgrTest, configureDHCPPacketQueueTest6) {
    scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // First let's make sure there is no queue and no thread.
    ASSERT_FALSE(ifacemgr->getPacketQueue6());
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    bool queue_enabled = false;
    // Given an empty pointer, we should default to no queue.
    data::ConstElementPtr queue_control;
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
    EXPECT_FALSE(queue_enabled);
    EXPECT_FALSE(ifacemgr->getPacketQueue6());
    // configureDHCPPacketQueue() should never start the thread.
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Verify that calling startDHCPReceiver with no queue, does NOT start the thread.
    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Now let's try with a populated queue control, but with enable-queue = false.
    queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, false);
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
    EXPECT_FALSE(queue_enabled);
    EXPECT_FALSE(ifacemgr->getPacketQueue6());
    // configureDHCPPacketQueue() should never start the thread.
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Now let's enable the queue.
    queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, true);
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
    ASSERT_TRUE(queue_enabled);
    // Verify we have correctly created the queue.
    CHECK_QUEUE_INFO(ifacemgr->getPacketQueue6(), "{ \"capacity\": 500, \"queue-type\": \""
                     << PacketQueueMgr6::DEFAULT_QUEUE_TYPE6 << "\", \"size\": 0 }");
    // configureDHCPPacketQueue() should never start the thread.
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());

    // Calling startDHCPReceiver with a queue, should start the thread.
    ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
    ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());

    // Verify that calling startDHCPReceiver when the thread is running, throws.
    ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET6), InvalidOperation);

    // Create a disabled config.
    queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, false);

    // Trying to reconfigure with a running thread should throw.
    ASSERT_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control),
                 InvalidOperation);

    // We should still have our queue and the thread should still be running.
    EXPECT_TRUE(ifacemgr->getPacketQueue6());
    ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());

    // Now let's stop stop the thread.
    ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
    // Stopping the thread should not destroy the queue.
    ASSERT_TRUE(ifacemgr->getPacketQueue6());

    // Reconfigure with the queue turned off.  We should have neither queue nor thread.
    ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
    EXPECT_FALSE(ifacemgr->getPacketQueue6());
    ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
}

}