diff --git a/PmpMyApp.xcodeproj/project.pbxproj b/PmpMyApp.xcodeproj/project.pbxproj index 93c361d..b214e3a 100644 --- a/PmpMyApp.xcodeproj/project.pbxproj +++ b/PmpMyApp.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 2F18D56B0B7C516D00149D44 /* draft-cheshire-nat-pmp.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = "draft-cheshire-nat-pmp.rtf"; path = "doc/draft-cheshire-nat-pmp.rtf"; sourceTree = ""; }; + 2F18D56C0B7C516D00149D44 /* draft-cheshire-nat-pmp.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = "draft-cheshire-nat-pmp.txt"; path = "doc/draft-cheshire-nat-pmp.txt"; sourceTree = ""; }; 2F5A48700B75598F0052B0C1 /* pmpmapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pmpmapper.h; path = source/pmpmapper.h; sourceTree = ""; }; 2F5A48710B75598F0052B0C1 /* pmpmapper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pmpmapper.c; path = source/pmpmapper.c; sourceTree = ""; }; 2F5A488A0B7565810052B0C1 /* PMPMapper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PMPMapper; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -94,6 +96,7 @@ children = ( 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, + 2F18D5690B7C515D00149D44 /* Documentation */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, @@ -129,6 +132,15 @@ name = Frameworks; sourceTree = ""; }; + 2F18D5690B7C515D00149D44 /* Documentation */ = { + isa = PBXGroup; + children = ( + 2F18D56B0B7C516D00149D44 /* draft-cheshire-nat-pmp.rtf */, + 2F18D56C0B7C516D00149D44 /* draft-cheshire-nat-pmp.txt */, + ); + name = Documentation; + sourceTree = ""; + }; 2F5A486C0B7559600052B0C1 /* NAT-PMP */ = { isa = PBXGroup; children = ( diff --git a/PmpMyApp.xcodeproj/tyler.mode1 b/PmpMyApp.xcodeproj/tyler.mode1 index 7f100ab..b5c9b02 100644 --- a/PmpMyApp.xcodeproj/tyler.mode1 +++ b/PmpMyApp.xcodeproj/tyler.mode1 @@ -257,6 +257,7 @@ 080E96DDFE201D6D7F000001 2F5A486C0B7559600052B0C1 29B97315FDCFA39411CA2CEA + 2F18D5690B7C515D00149D44 29B97317FDCFA39411CA2CEA 1C37FBAC04509CD000000102 1C37FABC05509CD000000102 @@ -264,7 +265,7 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 4 + 6 2 1 0 @@ -290,7 +291,7 @@ 186 RubberWindowFrame - 4 104 1072 924 0 0 1680 1028 + 1 104 1159 924 0 0 1680 1028 Module PBXSmartGroupTreeModule @@ -320,7 +321,7 @@ _historyCapacity 0 bookmark - 2F18D5670B7C4F3B00149D44 + 2F18D65A0B7C688B00149D44 history 2F5A489C0B7565AE0052B0C1 @@ -328,8 +329,9 @@ 2F901EC10B7AED84004FF42C 2F901EF70B7AEED5004FF42C 2F9021510B7BE0FB004FF42C - 2F9021520B7BE0FB004FF42C - 2F9021760B7C1179004FF42C + 2F18D5750B7C51B000149D44 + 2F18D62D0B7C661600149D44 + 2F18D62E0B7C661600149D44 prevStack @@ -340,6 +342,9 @@ 2F901EC50B7AED84004FF42C 2F901ED80B7AEDBC004FF42C 2F901EE10B7AEE09004FF42C + 2F18D5770B7C51B000149D44 + 2F18D60F0B7C60BE00149D44 + 2F18D62F0B7C661600149D44 SplitCount @@ -351,14 +356,14 @@ GeometryConfiguration Frame - {{0, 0}, {864, 878}} + {{0, 0}, {951, 879}} RubberWindowFrame - 4 104 1072 924 0 0 1680 1028 + 1 104 1159 924 0 0 1680 1028 Module PBXNavigatorGroup Proportion - 878pt + 879pt ContentConfiguration @@ -371,9 +376,9 @@ GeometryConfiguration Frame - {{0, 883}, {864, 0}} + {{0, 883}, {951, 0}} RubberWindowFrame - 4 104 1072 924 0 0 1680 1028 + 1 104 1159 924 0 0 1680 1028 Module XCDetailModule @@ -382,7 +387,7 @@ Proportion - 864pt + 951pt Name @@ -533,12 +538,17 @@ 5 WindowOrderList + 2F18D5FC0B7C5F9400149D44 + 2F18D5FD0B7C5F9400149D44 + 2F5A48CE0B756D650052B0C1 + 1CD10A99069EF8BA00B06720 + 2F18D5FA0B7C5F9400149D44 2F5A48970B7565A60052B0C1 - /Software/Subversion/trunk/PmpMyApp/PmpMyApp.xcodeproj 1C0AD2B3069F1EA900FABCE6 + /Software/Subversion/trunk/PmpMyApp/PmpMyApp.xcodeproj WindowString - 4 104 1072 924 0 0 1680 1028 + 1 104 1159 924 0 0 1680 1028 WindowTools @@ -576,10 +586,12 @@ 0pt + BecomeActive + ContentConfiguration PBXBuildLogShowsTranscriptDefaultKey - {{0, 36}, {620, 434}} + {{0, 209}, {620, 261}} PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel @@ -628,7 +640,7 @@ WindowToolGUID 2F5A48970B7565A60052B0C1 WindowToolIsVisible - + FirstTimeWindowDisplayed @@ -659,8 +671,8 @@ yes sizes - {{0, 0}, {459, 270}} - {{459, 0}, {580, 270}} + {{0, 0}, {457, 274}} + {{457, 0}, {582, 274}} VerticalSplitView @@ -675,8 +687,8 @@ yes sizes - {{0, 0}, {1039, 270}} - {{0, 270}, {1039, 258}} + {{0, 0}, {1039, 274}} + {{0, 274}, {1039, 254}} @@ -700,7 +712,7 @@ Frame {{0, 0}, {1039, 528}} RubberWindowFrame - 1807 189 1039 569 1680 26 1280 1024 + 1805 187 1039 569 1680 26 1280 1024 Module PBXDebugSessionModule @@ -723,19 +735,19 @@ TableOfContents 1CD10A99069EF8BA00B06720 - 2F9020D50B7BBFD1004FF42C + 2F18D5F40B7C5F9400149D44 1C162984064C10D400B95A72 - 2F9020D60B7BBFD1004FF42C - 2F9020D70B7BBFD1004FF42C - 2F9020D80B7BBFD1004FF42C - 2F9020D90B7BBFD1004FF42C - 2F9020DA0B7BBFD1004FF42C - 2F9020DB0B7BBFD1004FF42C + 2F18D5F50B7C5F9400149D44 + 2F18D5F60B7C5F9400149D44 + 2F18D5F70B7C5F9400149D44 + 2F18D5F80B7C5F9400149D44 + 2F18D5F90B7C5F9400149D44 + 2F18D5FA0B7C5F9400149D44 ToolbarConfiguration xcode.toolbar.config.debug WindowString - 1807 189 1039 569 1680 26 1280 1024 + 1805 187 1039 569 1680 26 1280 1024 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible @@ -892,7 +904,7 @@ TableOfContents 2F5A48CE0B756D650052B0C1 - 2F9020DC0B7BBFD1004FF42C + 2F18D5FB0B7C5F9400149D44 1C78EAAC065D492600B07095 WindowString diff --git a/PmpMyApp.xcodeproj/tyler.pbxuser b/PmpMyApp.xcodeproj/tyler.pbxuser index e70d627..82a8099 100644 --- a/PmpMyApp.xcodeproj/tyler.pbxuser +++ b/PmpMyApp.xcodeproj/tyler.pbxuser @@ -28,7 +28,7 @@ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, - 625, + 712, 20, 48, 43, @@ -53,7 +53,7 @@ 200, 350, 20, - 48.1626, + 48, 43, 43, ); @@ -71,72 +71,106 @@ PBXWorkspaceStateSaveDate = 192695317; }; perUserProjectItems = { - 2F18D5530B7C4C1900149D44 /* PBXTextBookmark */ = 2F18D5530B7C4C1900149D44 /* PBXTextBookmark */; - 2F18D55E0B7C4E5500149D44 /* PBXTextBookmark */ = 2F18D55E0B7C4E5500149D44 /* PBXTextBookmark */; - 2F18D5640B7C4E9B00149D44 /* PBXTextBookmark */ = 2F18D5640B7C4E9B00149D44 /* PBXTextBookmark */; - 2F18D5670B7C4F3B00149D44 /* PBXTextBookmark */ = 2F18D5670B7C4F3B00149D44 /* PBXTextBookmark */; - 2F5A489C0B7565AE0052B0C1 = 2F5A489C0B7565AE0052B0C1 /* PBXTextBookmark */; - 2F5A489D0B7565AE0052B0C1 = 2F5A489D0B7565AE0052B0C1 /* PBXTextBookmark */; - 2F5A48A00B7565AE0052B0C1 = 2F5A48A00B7565AE0052B0C1 /* PBXTextBookmark */; - 2F5A48A10B7565AE0052B0C1 = 2F5A48A10B7565AE0052B0C1 /* PBXTextBookmark */; - 2F5A48A20B7565AE0052B0C1 = 2F5A48A20B7565AE0052B0C1 /* PBXTextBookmark */; - 2F5A49370B7575010052B0C1 = 2F5A49370B7575010052B0C1 /* PBXTextBookmark */; - 2F901EC10B7AED84004FF42C = 2F901EC10B7AED84004FF42C /* PBXTextBookmark */; - 2F901EC50B7AED84004FF42C = 2F901EC50B7AED84004FF42C /* PBXTextBookmark */; - 2F901ED80B7AEDBC004FF42C = 2F901ED80B7AEDBC004FF42C /* PBXTextBookmark */; - 2F901EE10B7AEE09004FF42C = 2F901EE10B7AEE09004FF42C /* PBXTextBookmark */; - 2F901EF70B7AEED5004FF42C = 2F901EF70B7AEED5004FF42C /* PBXTextBookmark */; - 2F9021510B7BE0FB004FF42C = 2F9021510B7BE0FB004FF42C /* PBXTextBookmark */; - 2F9021520B7BE0FB004FF42C = 2F9021520B7BE0FB004FF42C /* PBXTextBookmark */; - 2F9021530B7BE0FB004FF42C = 2F9021530B7BE0FB004FF42C /* PBXTextBookmark */; - 2F9021540B7BE0FB004FF42C = 2F9021540B7BE0FB004FF42C /* PBXTextBookmark */; - 2F9021550B7BE0FB004FF42C = 2F9021550B7BE0FB004FF42C /* PBXTextBookmark */; - 2F9021560B7BE0FB004FF42C = 2F9021560B7BE0FB004FF42C /* PBXTextBookmark */; - 2F9021760B7C1179004FF42C = 2F9021760B7C1179004FF42C /* PBXTextBookmark */; + 2F18D5750B7C51B000149D44 /* PBXTextBookmark */ = 2F18D5750B7C51B000149D44 /* PBXTextBookmark */; + 2F18D5770B7C51B000149D44 /* PBXTextBookmark */ = 2F18D5770B7C51B000149D44 /* PBXTextBookmark */; + 2F18D60F0B7C60BE00149D44 /* PBXTextBookmark */ = 2F18D60F0B7C60BE00149D44 /* PBXTextBookmark */; + 2F18D62D0B7C661600149D44 /* PBXTextBookmark */ = 2F18D62D0B7C661600149D44 /* PBXTextBookmark */; + 2F18D62E0B7C661600149D44 /* PBXTextBookmark */ = 2F18D62E0B7C661600149D44 /* PBXTextBookmark */; + 2F18D62F0B7C661600149D44 /* PBXTextBookmark */ = 2F18D62F0B7C661600149D44 /* PBXTextBookmark */; + 2F18D65A0B7C688B00149D44 /* PBXTextBookmark */ = 2F18D65A0B7C688B00149D44 /* PBXTextBookmark */; + 2F5A489C0B7565AE0052B0C1 /* PBXTextBookmark */ = 2F5A489C0B7565AE0052B0C1 /* PBXTextBookmark */; + 2F5A489D0B7565AE0052B0C1 /* PBXTextBookmark */ = 2F5A489D0B7565AE0052B0C1 /* PBXTextBookmark */; + 2F5A48A00B7565AE0052B0C1 /* PBXTextBookmark */ = 2F5A48A00B7565AE0052B0C1 /* PBXTextBookmark */; + 2F5A48A10B7565AE0052B0C1 /* PBXTextBookmark */ = 2F5A48A10B7565AE0052B0C1 /* PBXTextBookmark */; + 2F5A48A20B7565AE0052B0C1 /* PBXTextBookmark */ = 2F5A48A20B7565AE0052B0C1 /* PBXTextBookmark */; + 2F5A49370B7575010052B0C1 /* PBXTextBookmark */ = 2F5A49370B7575010052B0C1 /* PBXTextBookmark */; + 2F901EC10B7AED84004FF42C /* PBXTextBookmark */ = 2F901EC10B7AED84004FF42C /* PBXTextBookmark */; + 2F901EC50B7AED84004FF42C /* PBXTextBookmark */ = 2F901EC50B7AED84004FF42C /* PBXTextBookmark */; + 2F901ED80B7AEDBC004FF42C /* PBXTextBookmark */ = 2F901ED80B7AEDBC004FF42C /* PBXTextBookmark */; + 2F901EE10B7AEE09004FF42C /* PBXTextBookmark */ = 2F901EE10B7AEE09004FF42C /* PBXTextBookmark */; + 2F901EF70B7AEED5004FF42C /* PBXTextBookmark */ = 2F901EF70B7AEED5004FF42C /* PBXTextBookmark */; + 2F9021510B7BE0FB004FF42C /* PBXTextBookmark */ = 2F9021510B7BE0FB004FF42C /* PBXTextBookmark */; }; sourceControlManager = 2F5A48590B75586F0052B0C1 /* Source Control */; userBuildSettings = { }; }; - 2F18D5530B7C4C1900149D44 /* PBXTextBookmark */ = { + 2F18D56B0B7C516D00149D44 /* draft-cheshire-nat-pmp.rtf */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {817, 16254}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRect = "{{0, 0}, {817, 598}}"; + }; + }; + 2F18D5750B7C51B000149D44 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = "pmpmapper.c: pmp_get_public"; + fRef = 2F18D56B0B7C516D00149D44 /* draft-cheshire-nat-pmp.rtf */; + name = "draft-cheshire-nat-pmp.rtf: 1"; rLen = 0; - rLoc = 1111; + rLoc = 0; rType = 0; - vrLen = 1697; + vrLen = 1930; vrLoc = 0; }; - 2F18D55E0B7C4E5500149D44 /* PBXTextBookmark */ = { + 2F18D5770B7C51B000149D44 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = "pmpmapper.c: 99"; + fRef = 2F18D56B0B7C516D00149D44 /* draft-cheshire-nat-pmp.rtf */; + name = "draft-cheshire-nat-pmp.rtf: 1"; rLen = 0; - rLoc = 2552; + rLoc = 0; rType = 0; - vrLen = 1858; - vrLoc = 2111; + vrLen = 1930; + vrLoc = 0; }; - 2F18D5640B7C4E9B00149D44 /* PBXTextBookmark */ = { + 2F18D60F0B7C60BE00149D44 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = "pmpmapper.c: 105"; + name = "pmpmapper.c: 151"; rLen = 0; - rLoc = 3086; + rLoc = 4269; rType = 0; - vrLen = 1881; - vrLoc = 1769; + vrLen = 754; + vrLoc = 3859; }; - 2F18D5670B7C4F3B00149D44 /* PBXTextBookmark */ = { + 2F18D62D0B7C661600149D44 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2F5A48700B75598F0052B0C1 /* pmpmapper.h */; + name = "pmpmapper.h: "; + rLen = 0; + rLoc = 1128; + rType = 0; + vrLen = 1117; + vrLoc = 201; + }; + 2F18D62E0B7C661600149D44 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = "pmpmapper.c: sendfd"; + name = "pmpmapper.c: 151"; rLen = 0; - rLoc = 1118; + rLoc = 4269; rType = 0; - vrLen = 1551; - vrLoc = 2316; + vrLen = 1951; + vrLoc = 3397; + }; + 2F18D62F0B7C661600149D44 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2F5A48700B75598F0052B0C1 /* pmpmapper.h */; + name = "pmpmapper.h: "; + rLen = 0; + rLoc = 1128; + rType = 0; + vrLen = 1117; + vrLoc = 201; + }; + 2F18D65A0B7C688B00149D44 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; + name = "pmpmapper.c: 279"; + rLen = 0; + rLoc = 8097; + rType = 0; + vrLen = 1588; + vrLoc = 0; }; 2F5A484B0B7558670052B0C1 /* PmpMyApp */ = { isa = PBXExecutable; @@ -175,17 +209,17 @@ }; 2F5A48700B75598F0052B0C1 /* pmpmapper.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {817, 846}}"; - sepNavSelRange = "{529, 0}"; - sepNavVisRect = "{{0, 0}, {817, 846}}"; + sepNavIntBoundsRect = "{{0, 0}, {904, 1036}}"; + sepNavSelRange = "{1128, 0}"; + sepNavVisRect = "{{0, 190}, {904, 846}}"; sepNavWindowFrame = "{{1954, -14}, {939, 979}}"; }; }; 2F5A48710B75598F0052B0C1 /* pmpmapper.c */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {817, 2128}}"; - sepNavSelRange = "{1118, 0}"; - sepNavVisRect = "{{0, 1107}, {817, 846}}"; + sepNavIntBoundsRect = "{{0, 0}, {904, 4102}}"; + sepNavSelRange = "{8097, 0}"; + sepNavVisRect = "{{0, 0}, {904, 847}}"; }; }; 2F5A48890B7565810052B0C1 /* PMPMapper */ = { @@ -283,7 +317,7 @@ fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; name = "PMPMapper.c: 29"; rLen = 0; - rLoc = 3670; + rLoc = 7302; rType = 0; vrLen = 951; vrLoc = 0; @@ -376,66 +410,6 @@ vrLen = 1178; vrLoc = 0; }; - 2F9021520B7BE0FB004FF42C /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2F5A48700B75598F0052B0C1 /* pmpmapper.h */; - name = "pmpmapper.h: PMP_TIMEOUT"; - rLen = 0; - rLoc = 529; - rType = 0; - vrLen = 867; - vrLoc = 0; - }; - 2F9021530B7BE0FB004FF42C /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = r; - rLen = 1; - rLoc = 1682; - rType = 0; - vrLen = 2025; - vrLoc = 1394; - }; - 2F9021540B7BE0FB004FF42C /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = r; - rLen = 1; - rLoc = 1682; - rType = 0; - vrLen = 2025; - vrLoc = 1394; - }; - 2F9021550B7BE0FB004FF42C /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2F901ECF0B7AEDB5004FF42C /* route.c */; - name = "route.c: 61"; - rLen = 0; - rLoc = 1177; - rType = 0; - vrLen = 1178; - vrLoc = 0; - }; - 2F9021560B7BE0FB004FF42C /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2F5A48700B75598F0052B0C1 /* pmpmapper.h */; - name = "pmpmapper.h: PMP_TIMEOUT"; - rLen = 0; - rLoc = 529; - rType = 0; - vrLen = 867; - vrLoc = 0; - }; - 2F9021760B7C1179004FF42C /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2F5A48710B75598F0052B0C1 /* pmpmapper.c */; - name = "pmpmapper.c: pmp_get_public"; - rLen = 0; - rLoc = 1111; - rType = 0; - vrLen = 1841; - vrLoc = 163; - }; 8D1107260486CEB800E47090 /* PmpMyApp */ = { activeExec = 0; executables = ( diff --git a/source/pmpmapper.c b/source/pmpmapper.c index 871fa9c..4cf57e3 100644 --- a/source/pmpmapper.c +++ b/source/pmpmapper.c @@ -40,6 +40,10 @@ struct sockaddr_in *pmp_get_public(struct sockaddr_in *gateway) fprintf(stderr, "Cannot request public IP from a NULL gateway!\n"); return NULL; } + if (gateway->sin_port != PMP_PORT) + { + gateway->sin_port = htons(PMP_PORT); // Default port for NAT-PMP is 5351 + } int sendfd; int req_attempts = 1; @@ -50,9 +54,7 @@ struct sockaddr_in *pmp_get_public(struct sockaddr_in *gateway) req_timeout.tv_sec = 0; req_timeout.tv_usec = PMP_TIMEOUT; - - gateway->sin_port = htons(PMP_PORT); // Default port for NAT-PMP is 5351 - + sendfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Clean out both req and resp structures @@ -99,6 +101,7 @@ struct sockaddr_in *pmp_get_public(struct sockaddr_in *gateway) if (addr.sin_addr.s_addr != gateway->sin_addr.s_addr) { fprintf(stderr, "Response was not received from our gateway! Instead from: %s\n", inet_ntoa(addr.sin_addr)); + goto iterate; } else { @@ -118,8 +121,8 @@ iterate: fprintf(stderr, "Response received from NAT-PMP device:\n"); fprintf(stderr, "version: %d\n", resp.version); fprintf(stderr, "opcode: %d\n", resp.opcode); - fprintf(stderr, "resultcode: %d\n", resp.resultcode); - fprintf(stderr, "epoch: %d\n", resp.epoch); + fprintf(stderr, "resultcode: %d\n", ntohs(resp.resultcode)); + fprintf(stderr, "epoch: %d\n", ntohl(resp.epoch)); struct in_addr in; in.s_addr = resp.address; fprintf(stderr, "address: %s\n", inet_ntoa(in)); @@ -130,22 +133,160 @@ iterate: return publicsockaddr; } +/*! + * pmp_create_map(struct sockaddr_in *,uint8_t,uint16_t,uint16_t,uint32_t) + * will return NULL on error, or a pointer to the pmp_map_response_t type + */ +pmp_map_response_t *pmp_create_map(struct sockaddr_in *gateway, uint8_t type, uint16_t privateport, uint16_t publicport, uint32_t lifetime) +{ + if (gateway == NULL) + { + fprintf(stderr, "Cannot create mapping on a NULL gateway!\n"); + return NULL; + } + if (gateway->sin_port != PMP_PORT) + { + gateway->sin_port = htons(PMP_PORT); // Default port for NAT-PMP is 5351 + } + + int sendfd; + int req_attempts = 1; + struct timeval req_timeout; + pmp_map_request_t req; + pmp_map_response_t *resp = (pmp_map_response_t *)(malloc(sizeof(pmp_map_response_t))); + + req_timeout.tv_sec = 0; + req_timeout.tv_usec = PMP_TIMEOUT; + + sendfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + // Clean out both req and resp structures + bzero(&req, sizeof(pmp_map_request_t)); + bzero(resp, sizeof(pmp_map_response_t)); + req.version = 0; + req.opcode = type; + req.privateport = htons(privateport); // What a difference byte ordering makes...d'oh! + req.publicport = htons(publicport); + req.lifetime = htonl(lifetime); + + // Attempt to contact NAT-PMP device 9 times as per: draft-cheshire-nat-pmp-02.txt + while (req_attempts < 10) + { +#ifdef PMP_DEBUG + fprintf(stderr, "Attempting to create a NAT-PMP mapping the private port %d, and the public port %d\n", privateport, publicport); + fprintf(stderr, "\tTimeout: %ds %dus, Request #: %d\n", req_timeout.tv_sec, req_timeout.tv_usec, req_attempts); +#endif + + if (sendto(sendfd, &req, sizeof(req), 0, (struct sockaddr *)(gateway), sizeof(struct sockaddr)) < 0) + { + fprintf(stderr, "There was an error sending the NAT-PMP mapping request! (%s)\n", strerror(errno)); + return NULL; + } + + if (setsockopt(sendfd, SOL_SOCKET, SO_RCVTIMEO, &req_timeout, sizeof(req_timeout)) < 0) + { + fprintf(stderr, "There was an error setting the socket's options! (%s)\n", strerror(errno)); + return NULL; + } + + if (recvfrom(sendfd, resp, sizeof(pmp_map_response_t), 0, NULL, NULL) < 0) + { + if ( (errno != EAGAIN) || (req_attempts == 9) ) + { + fprintf(stderr, "There was an error receiving the response from the NAT-PMP device! (%s)\n", strerror(errno)); + return NULL; + } + else + { + goto iterate; + } + } + + if (resp->opcode != (req.opcode + 128)) + { + fprintf(stderr, "The opcode for the response from the NAT device does not match the request opcode!\n"); + goto iterate; + } + + break; + +iterate: + ++req_attempts; + double_timeout(&req_timeout); + } + +#ifdef PMP_DEBUG + fprintf(stderr, "Response received from NAT-PMP device:\n"); + fprintf(stderr, "version: %d\n", resp->version); + fprintf(stderr, "opcode: %d\n", resp->opcode); + fprintf(stderr, "resultcode: %d\n", ntohs(resp->resultcode)); + fprintf(stderr, "epoch: %d\n", ntohl(resp->epoch)); + fprintf(stderr, "privateport: %d\n", ntohs(resp->privateport)); + fprintf(stderr, "publicport: %d\n", ntohs(resp->publicport)); + fprintf(stderr, "lifetime: %d\n", ntohl(resp->lifetime)); +#endif + + return resp; +} + +/*! + * pmp_destroy_map(struct sockaddr_in *,uint8_t,uint16_t) + * will return NULL on error, or a pointer to the pmp_map_response_t type + */ +pmp_map_response_t *pmp_destroy_map(struct sockaddr_in *gateway, uint8_t type, uint16_t privateport) +{ + pmp_map_response_t *response = NULL; + + if ((response = pmp_create_map(gateway, type, privateport, 0, 0)) == NULL) + { + fprintf(stderr, "Failed to properly destroy mapping for %d!\n", privateport); + return NULL; + } + else + { + return response; + } +} + #ifdef PMP_DEBUG int main(int argc, char **argv) { struct sockaddr_in *gw = NULL; struct sockaddr_in *pub = NULL; + pmp_map_response_t *map_response = NULL; printf("Acquiring the default gateway: "); if ((gw = default_gw()) == NULL) { printf("Failed to acquire the default gateway address!\n"); return EXIT_FAILURE; - } - + } printf("%s\n", inet_ntoa(gw->sin_addr)); + pub = pmp_get_public(gw); + // Attempt to create a port mapping... + if ((map_response = pmp_create_map(gw, PMP_MAP_TCP, 21, 5021, PMP_LIFETIME)) == NULL) + { + fprintf(stderr, "Failed to create port mapping!\n"); + return EXIT_FAILURE; + } + else + { + printf("Created port mapping for: %s:%d\n", inet_ntoa(pub->sin_addr), ntohs(map_response->publicport)); + } + + sleep(60); // Take a minute to think about what you've done + + if (pmp_destroy_map(gw, (map_response->opcode-128), 21) == NULL) + { + fprintf(stderr, "Failed to destroy port mapping!\n"); + return EXIT_FAILURE; + } + else + { + printf("Destroyed port mapping for: %s:%d\n", inet_ntoa(pub->sin_addr), ntohs(map_response->publicport)); + } return EXIT_SUCCESS; } diff --git a/source/pmpmapper.h b/source/pmpmapper.h index 3c3a40b..7eb79f6 100644 --- a/source/pmpmapper.h +++ b/source/pmpmapper.h @@ -27,7 +27,11 @@ #define PMP_VERSION 0 #define PMP_PORT 5351 -#define PMP_TIMEOUT 250000 +#define PMP_TIMEOUT 250000 // 250000 useconds +#define PMP_LIFETIME 3600 // 3600 seconds + +#define PMP_MAP_UDP 1 +#define PMP_MAP_TCP 2 /* * uint8_t: version, opcodes @@ -48,4 +52,27 @@ typedef struct { uint32_t address; } pmp_ip_response_t; +typedef struct { + uint8_t version; + uint8_t opcode; + char reserved[2]; + uint16_t privateport; + uint16_t publicport; + uint32_t lifetime; +} pmp_map_request_t; + +typedef struct { + uint8_t version; + uint8_t opcode; + uint16_t resultcode; + uint32_t epoch; + uint16_t privateport; + uint16_t publicport; + uint32_t lifetime; +} pmp_map_response_t; + +struct sockaddr_in *pmp_get_public(struct sockaddr_in *gateway); +pmp_map_response_t *pmp_create_map(struct sockaddr_in *gateway, uint8_t type, uint16_t privateport, uint16_t publicport, uint32_t lifetime); +pmp_map_response_t *pmp_destroy_map(struct sockaddr_in *gateway, uint8_t type, uint16_t privateport); + #endif \ No newline at end of file