diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/Contents.json b/Kwazii/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d84b3b4 --- /dev/null +++ b/Kwazii/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon128-1.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon256-1.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon512-1.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon@1x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/icon128-1.png b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon128-1.png new file mode 100644 index 0000000..2dffa44 Binary files /dev/null and b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon128-1.png differ diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/icon256-1.png b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon256-1.png new file mode 100644 index 0000000..7efd82e Binary files /dev/null and b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon256-1.png differ diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/icon256.png b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon256.png new file mode 100644 index 0000000..7efd82e Binary files /dev/null and b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon256.png differ diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/icon512-1.png b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon512-1.png new file mode 100644 index 0000000..8c07490 Binary files /dev/null and b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon512-1.png differ diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/icon512.png b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon512.png new file mode 100644 index 0000000..8c07490 Binary files /dev/null and b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon512.png differ diff --git a/Kwazii/Assets.xcassets/AppIcon.appiconset/icon@1x.png b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon@1x.png new file mode 100644 index 0000000..e1f5b92 Binary files /dev/null and b/Kwazii/Assets.xcassets/AppIcon.appiconset/icon@1x.png differ diff --git a/Kwazii/Assets.xcassets/Contents.json b/Kwazii/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Kwazii/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Kwazii/Assets.xcassets/Proxy.imageset/Contents.json b/Kwazii/Assets.xcassets/Proxy.imageset/Contents.json new file mode 100644 index 0000000..c4769dd --- /dev/null +++ b/Kwazii/Assets.xcassets/Proxy.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Proxy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Kwazii/Assets.xcassets/Proxy.imageset/Proxy@2x.png b/Kwazii/Assets.xcassets/Proxy.imageset/Proxy@2x.png new file mode 100644 index 0000000..5208fbe Binary files /dev/null and b/Kwazii/Assets.xcassets/Proxy.imageset/Proxy@2x.png differ diff --git a/Kwazii/Base.lproj/Main.storyboard b/Kwazii/Base.lproj/Main.storyboard new file mode 100644 index 0000000..e3b85c8 --- /dev/null +++ b/Kwazii/Base.lproj/Main.storyboard @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kwazii/HelpWindow.xib b/Kwazii/HelpWindow.xib new file mode 100644 index 0000000..de2ae5a --- /dev/null +++ b/Kwazii/HelpWindow.xib @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kwazii/HelpWindowController.swift b/Kwazii/HelpWindowController.swift new file mode 100644 index 0000000..d8a51ce --- /dev/null +++ b/Kwazii/HelpWindowController.swift @@ -0,0 +1,20 @@ +// +// HelpWindowController.swift +// Kwazii +// +// Created by abigt on 2018/1/18. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa + +class HelpWindowController: NSWindowController { + + @IBOutlet weak var textView: NSTextView! + override func windowDidLoad() { + super.windowDidLoad() + //self.textView.textStorage?.string = "test" + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + +} diff --git a/Kwazii/Info.plist b/Kwazii/Info.plist new file mode 100644 index 0000000..a27446e --- /dev/null +++ b/Kwazii/Info.plist @@ -0,0 +1,48 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + AppIcon.icons + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 6 + Fabric + + APIKey + + Kits + + + KitInfo + + KitName + Crashlytics + + + + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2018年 A.BIG.T. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + SUFeedURL + https://abigt.net/appupdate.xml + + diff --git a/Kwazii/Kwazii.entitlements b/Kwazii/Kwazii.entitlements new file mode 100644 index 0000000..19ba818 --- /dev/null +++ b/Kwazii/Kwazii.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + 745WQDK4L7.com.abigt.Surf + + + diff --git a/Kwazii/KwaziiAppDelegate.swift b/Kwazii/KwaziiAppDelegate.swift new file mode 100644 index 0000000..c412fa0 --- /dev/null +++ b/Kwazii/KwaziiAppDelegate.swift @@ -0,0 +1,198 @@ +// +// AppDelegate.swift +// Kwazii +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa +let appgroup = "745WQDK4L7.com.abigt.Surf" +import XRuler +import Xcon +import Sparkle +import Fabric +import Crashlytics +@NSApplicationMain +class KwaziiAppDelegate: NSObject, NSApplicationDelegate,NSMenuDelegate { + + var configWindow:PreferencesWindowController! + var helpWindow:HelpWindowController! + var updateWindows:UpdateWindowController! + var serversMenuItem:NSMenu! + @IBAction func addProxy(_ sender:Any){ + if configWindow == nil { + configWindow = PreferencesWindowController(windowNibName: NSNib.Name(rawValue: "PreferencesWindowController")) + } + configWindow.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + configWindow.window?.makeKeyAndOrderFront(self) + } + + @IBAction func openHelp(_ sender: Any) { + if helpWindow == nil { + helpWindow = HelpWindowController(windowNibName: NSNib.Name(rawValue: "HelpWindow")) + } + helpWindow.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + helpWindow.window?.makeKeyAndOrderFront(self) + } + func applicationDidFinishLaunching(_ aNotification: Notification) { + Fabric.with([Crashlytics.self]) + + // Fabric.with([Answers.self]) + Answers.logCustomEvent(withName: "Kwazii", + customAttributes: [ + "Started": "", + + ]) + // Insert code here to initialize your application + var url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appgroup)! + + if !FileManager.default.fileExists(atPath: url.path){ + try! FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) + + }else { + print("exist \(url)") + } + + + url.appendPathComponent("abigt.conf") + if !FileManager.default.fileExists(atPath: url.path){ + let p = Bundle.main.path(forResource: "abigt.conf", ofType: nil) + try! FileManager.default.copyItem(at: URL.init(fileURLWithPath: p!), to: url) + }else { + print("\(url)") + } + XRuler.groupIdentifier = appgroup + SFSettingModule.setting.config(url.path) + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + + func menuNeedsUpdate(_ menu: NSMenu){ + if serversMenuItem == nil{ + serversMenuItem = menu + } + self.updateServersMenu(true) + } + + + func updateServersMenu(_ update:Bool) { + + + + guard let menu = serversMenuItem else {return} + menu.removeAllItems() + var index = 0 + let profile = ProxyGroupSettings.share + for p in profile.proxys { + var title = "" + if profile.showCountry { + + if !p.serverIP.isEmpty{ + let rusult = Country.setting.geoIPRule(ipString: p.serverIP) + + p.countryFlag = rusult.emoji + p.isoCode = rusult.isoCode + title += p.countryFlag + }else { + hostToIP(proxy: p) + } + + + } + if p.proxyName.isEmpty { + title += p.serverAddress + ":" + p.serverPort + + }else { + title += p.proxyName + "(" + p.serverAddress + ":" + p.serverPort + ")" + } + let em = NSMenuItem(title: title, action: #selector(KwaziiAppDelegate.selectServer(_:)), keyEquivalent: "") + em.tag = index + if ProxyGroupSettings.share.selectIndex == index { + em.state = NSControl.StateValue(rawValue: 1) + + }else { + em.state = NSControl.StateValue(rawValue: 0) + } + index += 1 + menu.addItem(em) + } + menu.addItem(NSMenuItem.separator()) + // menu.addItem(withTitle: "Open Server Preferences ...", action: #selector(AppDelegate.openProxySConfig(_:)), keyEquivalent: "c") + } + @objc func selectServer(_ sender:NSMenuItem){ + let index = sender.tag + print("-----\(sender.tag)") + ProxyGroupSettings.share.selectIndex = index + + } + func hostToIP(proxy:SFProxy) { + dnsqueue.async(execute:{ [weak self ] in + guard let strong = self else {return} + + guard let hostInfo = gethostbyname2((proxy.serverAddress as NSString).utf8String, AF_INET)else { + return + } + + + + + let len = hostInfo.pointee.h_length + let aa = hostInfo.pointee.h_addr_list[0] + var ip = "" + + for i in 0 ..< len { + let x = (aa! + Int(i)).pointee + if i == (len - 1) { + ip += "\(strong.toUint(signed: x))" + break + } + ip += "\(strong.toUint(signed: x))." + + } + proxy.serverIP = ip + DispatchQueue.main.async(execute: { + self!.updateServersMenu(false) + }) + + }) + + + //return ip + } + func toUint(signed: Int8) -> UInt8 { + + let unsigned = signed >= 0 ? + UInt8(signed) : + UInt8(signed - Int8.min) + UInt8(Int8.max) + 1 + + return unsigned + } + let dnsqueue:DispatchQueue = DispatchQueue(label:"com.abigt.dns") + @IBAction func openRule(_ sender:Any){ + let url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)!.appendingPathComponent("abigt.conf") + + NSWorkspace.shared.open(url) + } + @IBAction func openCheckUpdate(_ sender:Any){ + if updateWindows == nil { + updateWindows = UpdateWindowController(windowNibName: NSNib.Name(rawValue: "SUUpdateSettingsWindowController")) + } + updateWindows.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + updateWindows.window?.makeKeyAndOrderFront(self) + } + var updater: SUUpdater! + @IBAction func checkUpdate(_ sender:Any){ + if updater == nil { + updater = SUUpdater() + } + updater.checkForUpdates(nil) + } +} + diff --git a/Kwazii/MainWindow.swift b/Kwazii/MainWindow.swift new file mode 100644 index 0000000..1e7840e --- /dev/null +++ b/Kwazii/MainWindow.swift @@ -0,0 +1,38 @@ +// +// MainWindow.swift +// Kwazii +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa + +class MainWindow: NSWindowController { + + override func windowDidLoad() { + super.windowDidLoad() + + //window?.titleVisibility = .hidden + //window?.titlebarAppearsTransparent = true + + // window?.styleMask.insert(.fullSizeContentView) + //disable close + window?.styleMask.remove(.closable) + //window?.styleMask.remove(.fullScreen) + //window?.styleMask.remove(.miniaturizable) + //window?.styleMask.remove(.resizable) + //NSWindow.StyleMask(rawValue: NSWindow.StyleMask.RawValue(~(UInt8(NSClosableWindowMask.rawValue) | UInt8(NSMiniaturizableWindowMask.rawValue) | UInt8(NSResizableWindowMask.rawValue)))) +// let st = NSStoryboard.init(name: NSStoryboard.Name(rawValue: "RequestBasic"), bundle:nil) +// let vc = self.storyboard?.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "request")) as! RequestsVC +// //let vc = st.instantiateInitialController() as! RequestsVC +// self.window!.contentView?.addSubview(vc.view) + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + @IBAction func addProxy(_ sender:Any){ + + } + @IBAction func cancel(_ sender: NSButton) { + //window?.performClose(self) + } +} diff --git a/Kwazii/RequestBasic.storyboard b/Kwazii/RequestBasic.storyboard new file mode 100644 index 0000000..845b2de --- /dev/null +++ b/Kwazii/RequestBasic.storyboard @@ -0,0 +1,438 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kwazii/RequestDetailView.swift b/Kwazii/RequestDetailView.swift new file mode 100644 index 0000000..73e6483 --- /dev/null +++ b/Kwazii/RequestDetailView.swift @@ -0,0 +1,24 @@ +// +// RequestDetailView.swift +// Kwazii +// +// Created by abigt on 2018/1/18. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa +import Xcon +import XProxy +class RequestDetailView: NSView { + + var request:SFRequestInfo! + required init?(coder decoder: NSCoder) { + super.init(coder: decoder) + } + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + // Drawing code here. + } + +} diff --git a/Kwazii/RequestTabVC.swift b/Kwazii/RequestTabVC.swift new file mode 100644 index 0000000..3625c2c --- /dev/null +++ b/Kwazii/RequestTabVC.swift @@ -0,0 +1,18 @@ +// +// RequestTabVC.swift +// Kwazii +// +// Created by abigt on 2018/1/18. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa + +class RequestTabVC: NSTabViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do view setup here. + } + +} diff --git a/Kwazii/RequestsVC.swift b/Kwazii/RequestsVC.swift new file mode 100644 index 0000000..18a0842 --- /dev/null +++ b/Kwazii/RequestsVC.swift @@ -0,0 +1,59 @@ +// +// RequestsVC.swift +// Kwazii +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa +import XDataService +import SFSocket +import AxLogger +import XRuler +import XProxy +final class RequestsVC: RequestsBasic { + @IBOutlet weak var detail:NSView! + let report:SFVPNStatistics = SFVPNStatistics.shared + var refreshTime = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags(rawValue: 0), queue: DispatchQueue.main) + func startProxy(){ + SKit.startGCDProxy(port: 10081, dispatchQueue: DispatchQueue.init(label: "Kwazii.dispatch"), socketQueue: DispatchQueue.init(label: "Kwazii.dispatch.socket")) + } + + public override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { + print("load....") + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + override func loadView() { + super.loadView() + } + func installTimer(){ + refreshTime.schedule(deadline: .now(), repeating: DispatchTimeInterval.seconds(1), leeway: DispatchTimeInterval.seconds(1)) + refreshTime.setEventHandler { + [weak self] in + let data = SFTCPConnectionManager.shared.recentRequestData() + self?.processData(data: data) + //self?.reportTask() + + } + refreshTime.setCancelHandler { + print("timer cancel......") + } + refreshTime.resume() + } + @objc required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + startProxy() + print("load coder....") + installTimer() + } + + override func viewDidLoad() { + tableView.delegate = self + tableView.dataSource = self + super.viewDidLoad() + + // Do view setup here. + } + +} diff --git a/Kwazii/SUUpdateSettingsWindowController.xib b/Kwazii/SUUpdateSettingsWindowController.xib new file mode 100644 index 0000000..ad902db --- /dev/null +++ b/Kwazii/SUUpdateSettingsWindowController.xib @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kwazii/UpdateWindowController.swift b/Kwazii/UpdateWindowController.swift new file mode 100644 index 0000000..7e260c1 --- /dev/null +++ b/Kwazii/UpdateWindowController.swift @@ -0,0 +1,20 @@ +// +// UpdateWindowController.swift +// Kwazii +// +// Created by abigt on 2018/1/19. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa +import Sparkle +class UpdateWindowController: NSWindowController { + + @IBOutlet var updater: SUUpdater! + override func windowDidLoad() { + super.windowDidLoad() + + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + +} diff --git a/Kwazii/ViewController.swift b/Kwazii/ViewController.swift new file mode 100644 index 0000000..15e139f --- /dev/null +++ b/Kwazii/ViewController.swift @@ -0,0 +1,27 @@ +// +// ViewController.swift +// Kwazii +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa + +class ViewController: NSViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + override var representedObject: Any? { + didSet { + // Update the view, if already loaded. + } + } + + +} + diff --git a/Kwazii/abigt.conf b/Kwazii/abigt.conf new file mode 100644 index 0000000..4ecaaae --- /dev/null +++ b/Kwazii/abigt.conf @@ -0,0 +1,807 @@ +[General] +skip-proxy = 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 127.0.0.0/8,100.64.0.0/10, localhost, *.local, e.crashlytics.com +bypass-tun = 192.168.0.0/16,10.0.0.0/8, 172.16.0.0/12,169.254.0.0/16,,119.29.29.29/32,223.6.6.6/32, 223.5.5.5/32 + +dns-server = system +loglevel = debug + +[Rule] + + +DOMAIN-SUFFIX,appldnld.apple.com,DIRECT +DOMAIN-SUFFIX,mesu.apple.com,DIRECT + +#USER-AGENT,CriOS,Proxy +USER-AGENT,ph.telegra.Telegraph,Proxy + +DOMAIN,beta.itunes.apple.com,Proxy +DOMAIN,init.itunes.apple.com,DIRECT +DOMAIN,audio.itunes.apple.com,DIRECT +DOMAIN,iosapps.itunes.apple.com,DIRECT +DOMAIN,play.itunes.apple.com,DIRECT +DOMAIN,aod.itune.apple.com,DIRECT +DOMAIN,126.net,DIRECT +# Apple PACKAGE DIRECT +DOMAIN-SUFFIX,appldnld.apple.com,DIRECT +DOMAIN-SUFFIX,adcdownload.apple.com,DIRECT +DOMAIN-SUFFIX,lcdn-registration.apple.com,DIRECT +DOMAIN-SUFFIX,swcdn.apple.com,DIRECT +DOMAIN-SUFFIX,phobos.apple.com,DIRECT +DOMAIN-SUFFIX,ls.apple.com,DIRECT +DOMAIN-SUFFIX,cdn-apple.com,DIRECT +DOMAIN-SUFFIX,gstatic.com,Proxy +DOMAIN,g.co,Proxy +# Apple PACKAGE PROXY-B +# 建议直连,较高要求可以改变连接方式 +DOMAIN-SUFFIX,icloud.com,DIRECT +DOMAIN-SUFFIX,me.com,DIRECT +DOMAIN-SUFFIX,apple.com,DIRECT +DOMAIN-SUFFIX,itunes.apple.com,DIRECT +DOMAIN-SUFFIX,mzstatic.com,DIRECT + + +DOMAIN,github.com,Proxy +DOMAIN,golang.org,Proxy +# SpeedTest +DOMAIN,ads.ookla.com,REJECT +DOMAIN,cdn.ads.ookla.com,REJECT + +# App Laugh Skin +DOMAIN,u1.img.mobile.sina.cn,REJECT + +# Qiushibaike +DOMAIN,mi.gdt.qq.com,REJECT + +# Sina +DOMAIN,sax.sina.cn,REJECT + +# Xunfei +DOMAIN,bj.imp.voiceads.cn,REJECT + +# Systemav +DOMAIN,m.madthumbs.com,REJECT + +# Google +DOMAIN,csi.gstatic.com,REJECT +DOMAIN,static.googleadsserving.cn,REJECT +DOMAIN,ads.google.com,REJECT +DOMAIN,account.google.com,Proxy +DOMAIN,afd.l.google.com,REJECT +DOMAIN,mobileads.google.com,REJECT +DOMAIN,pagead-tpc.l.google.com,REJECT +DOMAIN,pagead.google.com,REJECT +DOMAIN,pagead.l.google.com,REJECT +DOMAIN,partnerad.l.google.com,REJECT +DOMAIN,ads.youtube.com,REJECT +DOMAIN,ads.gmodules.com,REJECT +DOMAIN,badad.googleplex.com,REJECT +DOMAIN,www.googlecommerce.com,REJECT +DOMAIN,www.googletagmanager.com,REJECT +DOMAIN,service.urchin.com,REJECT + +# AutoHome +DOMAIN,adm3.autoimg.cn,REJECT +DOMAIN,adm0.autoimg.cn,REJECT +DOMAIN,img2.autoimg.cn,REJECT + +# Dropbox +DOMAIN,d.dropbox.com,REJECT +DOMAIN,dl-debug.dropbox.com,REJECT + +# Twitter +DOMAIN,syndication.twitter.com,REJECT +DOMAIN-SUFFIX,twitter.com,Proxy +# DSP +DOMAIN,dsp.lomark.cn,REJECT + +# VIU By +DOMAIN,stream-hk.viu.com,Proxy +DOMAIN,global.adserver.yahoo.com,REJECT + + +# CDN +DOMAIN,init.icloud-analysis.com, REJECT +DOMAIN,zhihu-analytics.zhihu.com,REJECT +DOMAIN,log.cmbchina.com,REJECT +DOMAIN,api.segment.io,REJECT +DOMAIN,api.instabug.com,REJECT +DOMAIN,adlog.flurry.com,REJECT +DOMAIN,ads.flurry.com,REJECT + + + +DOMAIN,r1.ykimg.com,REJECT +DOMAIN,v.gdt.qq.com,REJECT +DOMAIN,sd.domob.cn,REJECT + + + + + + + + + +# Taobao +DOMAIN,h5.m.taobao.com,DIRECT + +# Duolinguo +DOMAIN,api.mixpanel.com,DIRECT +DOMAIN,d2pur3iezf4d1j.cloudfront.net,DIRECT + +DOMAIN,wscdns.com,DIRECT + +# Synology +DOMAIN-SUFFIX,QuickConnect.to,DIRECT + +# Alipay +DOMAIN-SUFFIX,alipaylog.com,DIRECT + +# Taobao +DOMAIN-SUFFIX,taobaocdn.com,DIRECT +DOMAIN-SUFFIX,alicdn.com,DIRECT + +# 12306 +DOMAIN-SUFFIX,12306.cn,DIRECT + +# 17APP +DOMAIN-SUFFIX,17app.co,DIRECT + +# 126 +DOMAIN-SUFFIX,126.net,DIRECT +DOMAIN-SUFFIX,163.com,DIRECT +DOMAIN-SUFFIX,netnease.com,DIRECT + +# 360buy +DOMAIN-SUFFIX,360buyimg.com,DIRECT +#DOMAIN-SUFFIX,jd.com,DIRECT + +# ICBC +DOMAIN-SUFFIX,icbc.com,DIRECT + +# 10010 By ސސސސސސސސސސ +DOMAIN-SUFFIX,6-10010.com,DIRECT + + +# iMuzo +DOMAIN-SUFFIX,iheart.com,DIRECT +DOMAIN-SUFFIX,dongting.com,DIRECT +DOMAIN-SUFFIX,iyyin.com,DIRECT +DOMAIN-SUFFIX,openspeech.cn,DIRECT + + +# CDN +DOMAIN-SUFFIX,yunjiasu-cdn.net,DIRECT +DOMAIN-SUFFIX,8686c.com,DIRECT +DOMAIN-SUFFIX,ourdvs.com,DIRECT +DOMAIN-SUFFIX,spotilocal.com,DIRECT + +# CN DIRECT +DOMAIN-SUFFIX,cn,DIRECT + +# CHINA WHITE LIST +DOMAIN-SUFFIX,com.cn,DIRECT +DOMAIN-SUFFIX,edu.cn,DIRECT +DOMAIN-SUFFIX,org.cn,DIRECT +DOMAIN-SUFFIX,net.cn,DIRECT +DOMAIN-SUFFIX,gov.cn,DIRECT +DOMAIN-SUFFIX,weibo.cn,DIRECT +DOMAIN-SUFFIX,sina.cn,DIRECT +DOMAIN-SUFFIX,tbcdn.cn,DIRECT +DOMAIN-SUFFIX,sinajs.cn,DIRECT +DOMAIN-SUFFIX,amazon.cn,DIRECT +DOMAIN-SUFFIX,360.cn,DIRECT +DOMAIN-SUFFIX,flyme.cn,DIRECT +DOMAIN-SUFFIX,mtime.cn,DIRECT +DOMAIN-SUFFIX,ifanr.cn,DIRECT +DOMAIN-SUFFIX,kuwo.cn,DIRECT +DOMAIN-SUFFIX,kuaipan.cn,DIRECT +DOMAIN-SUFFIX,3g.cn,DIRECT +DOMAIN-SUFFIX,tianya.cn,DIRECT +DOMAIN-SUFFIX,url.cn,DIRECT +DOMAIN-SUFFIX,blued.cn,DIRECT +DOMAIN-SUFFIX,189.cn,DIRECT +DOMAIN-SUFFIX,10086.cn,DIRECT +DOMAIN-SUFFIX,10010.cn,DIRECT +DOMAIN-SUFFIX,uc.cn,DIRECT +DOMAIN-SUFFIX,damai.cn,DIRECT +DOMAIN-SUFFIX,suning.cn,DIRECT +DOMAIN-SUFFIX,liebao.cn,DIRECT +DOMAIN-SUFFIX,mifile.cn,DIRECT +DOMAIN-SUFFIX,voicecloud.cn,DIRECT +DOMAIN-SUFFIX,wps.cn,DIRECT +DOMAIN-SUFFIX,8684.cn,DIRECT +DOMAIN-SUFFIX,uniqlo.cn,DIRECT +DOMAIN-SUFFIX,ifeng.com,DIRECT +DOMAIN-SUFFIX,ifengimg.com,DIRECT +DOMAIN-SUFFIX,bbwc.cn,DIRECT +DOMAIN-SUFFIX,3.cn,DIRECT +DOMAIN-SUFFIX,maxthon.cn,DIRECT +DOMAIN-SUFFIX,xda.cn,DIRECT +DOMAIN-SUFFIX,cntv.cn,DIRECT +DOMAIN-SUFFIX,6.cn,DIRECT +DOMAIN-SUFFIX,meizu.cn,DIRECT +DOMAIN-SUFFIX,360doc.cn,DIRECT +DOMAIN-SUFFIX,sto.cn,DIRECT +DOMAIN-SUFFIX,xiaomi.cn,DIRECT +DOMAIN-SUFFIX,ccb.cn,DIRECT +DOMAIN-SUFFIX,macx.cn,DIRECT +DOMAIN-SUFFIX,d.cn,DIRECT +DOMAIN-SUFFIX,m1905.cn,DIRECT +DOMAIN-SUFFIX,t.cn,DIRECT +DOMAIN-SUFFIX,sh.cn,DIRECT +DOMAIN-SUFFIX,bong.cn,DIRECT +DOMAIN-SUFFIX,mafengwo.cn,DIRECT +DOMAIN-SUFFIX,ucloud.cn,DIRECT +DOMAIN-SUFFIX,xdf.cn,DIRECT +DOMAIN-SUFFIX,china.cn,DIRECT +DOMAIN-SUFFIX,ip.cn,DIRECT +DOMAIN-SUFFIX,news.cn,DIRECT +DOMAIN-SUFFIX,linux.cn,DIRECT +DOMAIN-SUFFIX,dict.cn,DIRECT +DOMAIN-SUFFIX,windowsazure.cn,DIRECT +DOMAIN-SUFFIX,dwz.cn,DIRECT +DOMAIN-SUFFIX,10010.com,DIRECT +DOMAIN-SUFFIX,115.com,DIRECT +DOMAIN-SUFFIX,123u.com,DIRECT +DOMAIN-SUFFIX,126.com,DIRECT +DOMAIN-SUFFIX,17173.com,DIRECT +DOMAIN-SUFFIX,178.com,DIRECT +DOMAIN-SUFFIX,17cdn.com,DIRECT +DOMAIN-SUFFIX,21cn.com,DIRECT +DOMAIN-SUFFIX,2288.org,DIRECT +DOMAIN-SUFFIX,3322.org,DIRECT +DOMAIN-SUFFIX,360doc.com,DIRECT +DOMAIN-SUFFIX,360safe.com,DIRECT +DOMAIN-SUFFIX,36kr.com,DIRECT +DOMAIN-SUFFIX,400gb.com,DIRECT +DOMAIN-SUFFIX,4399.com,DIRECT +DOMAIN-SUFFIX,51.la,DIRECT +DOMAIN-SUFFIX,51buy.com,DIRECT +DOMAIN-SUFFIX,51cto.com,DIRECT +DOMAIN-SUFFIX,51job.com,DIRECT +DOMAIN-SUFFIX,51jobcdn.com,DIRECT +DOMAIN-SUFFIX,5d6d.com,DIRECT +DOMAIN-SUFFIX,5d6d.net,DIRECT +DOMAIN-SUFFIX,61.com,DIRECT +DOMAIN-SUFFIX,6600.org,DIRECT +DOMAIN-SUFFIX,6rooms.com,DIRECT +DOMAIN-SUFFIX,7766.org,DIRECT +DOMAIN-SUFFIX,7k7k.com,DIRECT +DOMAIN-SUFFIX,8800.org,DIRECT +DOMAIN-SUFFIX,8866.org,DIRECT +DOMAIN-SUFFIX,90g.org,DIRECT +DOMAIN-SUFFIX,91.com,DIRECT +DOMAIN-SUFFIX,9966.org,DIRECT +DOMAIN-SUFFIX,acfun.tv,DIRECT +DOMAIN-SUFFIX,aicdn.com,DIRECT +DOMAIN-SUFFIX,ali213.net,DIRECT +DOMAIN-SUFFIX,alibaba.com,DIRECT +DOMAIN-SUFFIX,aliexpress.com,DIRECT +DOMAIN-SUFFIX,aliimg.com,DIRECT +DOMAIN-SUFFIX,alikunlun.com,DIRECT +DOMAIN-SUFFIX,alisoft.com,DIRECT +DOMAIN-SUFFIX,aliyun.com,DIRECT +DOMAIN-SUFFIX,aliyuncdn.com,DIRECT +DOMAIN-SUFFIX,aliyuncs.com,DIRECT +DOMAIN-SUFFIX,anzhi.com,DIRECT +DOMAIN-SUFFIX,appinn.com,DIRECT +DOMAIN-SUFFIX,apple.com,DIRECT +DOMAIN-SUFFIX,appsina.com,DIRECT +DOMAIN-SUFFIX,archlinuxcn.org,DIRECT +DOMAIN-SUFFIX,atpanel.com,DIRECT +DOMAIN-SUFFIX,baifendian.com,DIRECT +DOMAIN-SUFFIX,baihe.com,DIRECT +DOMAIN-SUFFIX,baixing.com,DIRECT +DOMAIN-SUFFIX,bdimg.com,DIRECT +DOMAIN-SUFFIX,bdstatic.com,DIRECT +DOMAIN-SUFFIX,bilibili.tv,DIRECT +DOMAIN-SUFFIX,blogbus.com,DIRECT +DOMAIN-SUFFIX,blueidea.com,DIRECT +DOMAIN-SUFFIX,ccb.com,DIRECT +DOMAIN-SUFFIX,cctv.com,DIRECT +DOMAIN-SUFFIX,cctvpic.com,DIRECT +DOMAIN-SUFFIX,cdn20.com,DIRECT +DOMAIN-SUFFIX,china.com,DIRECT +DOMAIN-SUFFIX,chinabyte.com,DIRECT +DOMAIN-SUFFIX,chinacache.com,DIRECT +DOMAIN-SUFFIX,chinacache.net,DIRECT +DOMAIN-SUFFIX,chinacaipu.com,DIRECT +DOMAIN-SUFFIX,chinagba.com,DIRECT +DOMAIN-SUFFIX,chinahr.com,DIRECT +DOMAIN-SUFFIX,chinajoy.net,DIRECT +DOMAIN-SUFFIX,chinamobile.com,DIRECT +DOMAIN-SUFFIX,chinanetcenter.com,DIRECT +DOMAIN-SUFFIX,chinanews.com,DIRECT +DOMAIN-SUFFIX,chinapnr.com,DIRECT +DOMAIN-SUFFIX,chinaren.com,DIRECT +DOMAIN-SUFFIX,chinaspeeds.net,DIRECT +DOMAIN-SUFFIX,chinaunix.net,DIRECT +DOMAIN-SUFFIX,chinaz.com,DIRECT +DOMAIN-SUFFIX,chint.com,DIRECT +DOMAIN-SUFFIX,chiphell.com,DIRECT +DOMAIN-SUFFIX,chuangxin.com,DIRECT +DOMAIN-SUFFIX,ci123.com,DIRECT +DOMAIN-SUFFIX,ciku5.com,DIRECT +DOMAIN-SUFFIX,citysbs.com,DIRECT +DOMAIN-SUFFIX,class.coursera.org,DIRECT +DOMAIN-SUFFIX,cloudcdn.net,DIRECT +DOMAIN-SUFFIX,cmbchina.com,DIRECT +DOMAIN-SUFFIX,cmfu.com,DIRECT +DOMAIN-SUFFIX,cmread.com,DIRECT +DOMAIN-SUFFIX,cmwb.com,DIRECT +DOMAIN-SUFFIX,cn.archive.ubuntu.com,DIRECT +DOMAIN-SUFFIX,cn.bing.com,DIRECT +DOMAIN-SUFFIX,cn.coremetrics.com,DIRECT +DOMAIN-SUFFIX,cn.debian.org,DIRECT +DOMAIN-SUFFIX,cn.msn.com,DIRECT +DOMAIN-SUFFIX,cnak2.englishtown.com,DIRECT +DOMAIN-SUFFIX,cnbeta.com,DIRECT +DOMAIN-SUFFIX,cnbetacdn.com,DIRECT +DOMAIN-SUFFIX,cnblogs.com,DIRECT +DOMAIN-SUFFIX,cnepub.com,DIRECT +DOMAIN-SUFFIX,cnzz.com,DIRECT +DOMAIN-SUFFIX,comsenz.com,DIRECT +DOMAIN-SUFFIX,csdn.net,DIRECT +DOMAIN-SUFFIX,ct10000.com,DIRECT +DOMAIN-SUFFIX,ctdisk.com,DIRECT +DOMAIN-SUFFIX,dangdang.com,DIRECT +DOMAIN-SUFFIX,dbank.com,DIRECT +DOMAIN-SUFFIX,dedecms.com,DIRECT +DOMAIN-SUFFIX,diandian.com,DIRECT +DOMAIN-SUFFIX,dianping.com,DIRECT +DOMAIN-SUFFIX,discuz.com,DIRECT +DOMAIN-SUFFIX,discuz.net,DIRECT +DOMAIN-SUFFIX,docin.com,DIRECT +DOMAIN-SUFFIX,donews.com,DIRECT +DOMAIN-SUFFIX,dospy.com,DIRECT +DOMAIN-SUFFIX,douban.com,DIRECT +DOMAIN-SUFFIX,douban.fm,DIRECT +DOMAIN-SUFFIX,duapp.com,DIRECT +DOMAIN-SUFFIX,duba.net,DIRECT +DOMAIN-SUFFIX,duomi.com,DIRECT +DOMAIN-SUFFIX,duote.com,DIRECT +DOMAIN-SUFFIX,duowan.com,DIRECT +DOMAIN-SUFFIX,egou.com,DIRECT +DOMAIN-SUFFIX,et8.org,DIRECT +DOMAIN-SUFFIX,etao.com,DIRECT +DOMAIN-SUFFIX,f3322.org,DIRECT +DOMAIN-SUFFIX,fantong.com,DIRECT +DOMAIN-SUFFIX,fenzhi.com,DIRECT +DOMAIN-SUFFIX,fhldns.com,DIRECT +DOMAIN-SUFFIX,ganji.com,DIRECT +DOMAIN-SUFFIX,gaopeng.com,DIRECT +DOMAIN-SUFFIX,geekpark.net,DIRECT +DOMAIN-SUFFIX,gfan.com,DIRECT +DOMAIN-SUFFIX,hacdn.net,DIRECT +DOMAIN-SUFFIX,hadns.net,DIRECT +DOMAIN-SUFFIX,hao123.com,DIRECT +DOMAIN-SUFFIX,hao123img.com,DIRECT +DOMAIN-SUFFIX,hc360.com,DIRECT +DOMAIN-SUFFIX,hdslb.com,DIRECT +DOMAIN-SUFFIX,hexun.com,DIRECT +DOMAIN-SUFFIX,hiapk.com,DIRECT +DOMAIN-SUFFIX,hichina.com,DIRECT +DOMAIN-SUFFIX,hoopchina.com,DIRECT +DOMAIN-SUFFIX,huanqiu.com,DIRECT +DOMAIN-SUFFIX,hudong.com,DIRECT +DOMAIN-SUFFIX,huochepiao.com,DIRECT +DOMAIN-SUFFIX,hupu.com,DIRECT +DOMAIN-SUFFIX,iask.com,DIRECT +DOMAIN-SUFFIX,iciba.com,DIRECT +DOMAIN-SUFFIX,idqqimg.com,DIRECT +DOMAIN-SUFFIX,ifanr.com,DIRECT +DOMAIN-SUFFIX,ijinshan.com,DIRECT +DOMAIN-SUFFIX,iqiyi.com,DIRECT +DOMAIN-SUFFIX,it168.com,DIRECT +DOMAIN-SUFFIX,itcpn.net,DIRECT +DOMAIN-SUFFIX,iteye.com,DIRECT +DOMAIN-SUFFIX,itouzi.com,DIRECT +DOMAIN-SUFFIX,jandan.net,DIRECT +DOMAIN-SUFFIX,jiashule.com,DIRECT +DOMAIN-SUFFIX,jiasule.com,DIRECT +DOMAIN-SUFFIX,jiathis.com,DIRECT +DOMAIN-SUFFIX,jiayuan.com,DIRECT +DOMAIN-SUFFIX,jiepang.com,DIRECT +DOMAIN-SUFFIX,jing.fm,DIRECT +DOMAIN-SUFFIX,jobbole.com,DIRECT +DOMAIN-SUFFIX,jstv.com,DIRECT +DOMAIN-SUFFIX,jumei.com,DIRECT +DOMAIN-SUFFIX,kaixin001.com,DIRECT +DOMAIN-SUFFIX,kandian.com,DIRECT +DOMAIN-SUFFIX,kandian.net,DIRECT +DOMAIN-SUFFIX,kanimg.com,DIRECT +DOMAIN-SUFFIX,kankanews.com,DIRECT +DOMAIN-SUFFIX,kdnet.net,DIRECT +DOMAIN-SUFFIX,koudai8.com,DIRECT +DOMAIN-SUFFIX,ku6.com,DIRECT +DOMAIN-SUFFIX,ku6cdn.com,DIRECT +DOMAIN-SUFFIX,ku6img.com,DIRECT +DOMAIN-SUFFIX,kuaidi100.com,DIRECT +DOMAIN-SUFFIX,kugou.com,DIRECT +DOMAIN-SUFFIX,lashou.com,DIRECT +DOMAIN-SUFFIX,letao.com,DIRECT +DOMAIN-SUFFIX,letv.com,DIRECT +DOMAIN-SUFFIX,lietou.com,DIRECT +DOMAIN-SUFFIX,linezing.com,DIRECT +DOMAIN-SUFFIX,loli.mg,DIRECT +DOMAIN-SUFFIX,loli.vg,DIRECT +DOMAIN-SUFFIX,lvping.com,DIRECT +DOMAIN-SUFFIX,lxdns.com,DIRECT +DOMAIN-SUFFIX,dns.weixin.qq.com,DIRECT +DOMAIN-SUFFIX,mangocity.com,DIRECT +DOMAIN-SUFFIX,mapbar.com,DIRECT +DOMAIN-SUFFIX,mcbbs.net,DIRECT +DOMAIN-SUFFIX,meilishuo.com,DIRECT +DOMAIN-SUFFIX,meituan.com,DIRECT +DOMAIN-SUFFIX,meituan.net,DIRECT +DOMAIN-SUFFIX,meizu.com,DIRECT +DOMAIN-SUFFIX,microsoft.com,DIRECT +DOMAIN-SUFFIX,miui.com,DIRECT +DOMAIN-SUFFIX,moe123.com,DIRECT +DOMAIN-SUFFIX,moegirl.org,DIRECT +DOMAIN-SUFFIX,mop.com,DIRECT +DOMAIN-SUFFIX,mtime.com,DIRECT +DOMAIN-SUFFIX,my-card.in,DIRECT +DOMAIN-SUFFIX,mydrivers.com,DIRECT +DOMAIN-SUFFIX,mzstatic.com,DIRECT +DOMAIN-SUFFIX,newsmth.net,DIRECT +DOMAIN-SUFFIX,ngacn.cc,DIRECT +DOMAIN-SUFFIX,nuomi.com,DIRECT +DOMAIN-SUFFIX,okbuy.com,DIRECT +DOMAIN-SUFFIX,optaim.com,DIRECT +DOMAIN-SUFFIX,oschina.net,DIRECT +DOMAIN-SUFFIX,paipai.com,DIRECT +DOMAIN-SUFFIX,pcbeta.com,DIRECT +DOMAIN-SUFFIX,pchome.net,DIRECT +DOMAIN-SUFFIX,pcpop.com,DIRECT +DOMAIN-SUFFIX,pengyou.com,DIRECT +DOMAIN-SUFFIX,phoenixlzx.com,DIRECT +DOMAIN-SUFFIX,phpwind.net,DIRECT +DOMAIN-SUFFIX,pingan.com,DIRECT +DOMAIN-SUFFIX,pool.ntp.org,DIRECT +DOMAIN-SUFFIX,pplive.com,DIRECT +DOMAIN-SUFFIX,pps.tv,DIRECT +DOMAIN-SUFFIX,ppstream.com,DIRECT +DOMAIN-SUFFIX,pptv.com,DIRECT +DOMAIN-SUFFIX,pubyun.com,DIRECT +DOMAIN-SUFFIX,qhimg.com,DIRECT +DOMAIN-SUFFIX,qianlong.com,DIRECT +DOMAIN-SUFFIX,qidian.com,DIRECT +DOMAIN-SUFFIX,qingdaonews.com,DIRECT +DOMAIN-SUFFIX,qiniu.com,DIRECT +DOMAIN-SUFFIX,qiniudn.com,DIRECT +DOMAIN-SUFFIX,qiushibaike.com,DIRECT +DOMAIN-SUFFIX,qiyi.com,DIRECT +DOMAIN-SUFFIX,qiyipic.com,DIRECT +DOMAIN-SUFFIX,qqmail.com,DIRECT +DOMAIN-SUFFIX,qstatic.com,DIRECT +DOMAIN-SUFFIX,qunar.com,DIRECT +DOMAIN-SUFFIX,qunarzz.com,DIRECT +DOMAIN-SUFFIX,qvbuy.com,DIRECT +DOMAIN-SUFFIX,renren.com,DIRECT +DOMAIN-SUFFIX,renrendai.com,DIRECT +DOMAIN-SUFFIX,rrfmn.com,DIRECT +DOMAIN-SUFFIX,rrimg.com,DIRECT +DOMAIN-SUFFIX,sanguosha.com,DIRECT +DOMAIN-SUFFIX,sdo.com,DIRECT +DOMAIN-SUFFIX,sina.com,DIRECT +DOMAIN-SUFFIX,sinaapp.com,DIRECT +DOMAIN-SUFFIX,sinaedge.com,DIRECT +DOMAIN-SUFFIX,sinajs.com,DIRECT +DOMAIN-SUFFIX,skycn.com,DIRECT +DOMAIN-SUFFIX,smzdm.com,DIRECT +DOMAIN-SUFFIX,sogou.com,DIRECT +DOMAIN-SUFFIX,sohu.com,DIRECT +DOMAIN-SUFFIX,soku.com,DIRECT +DOMAIN-SUFFIX,solidot.org,DIRECT +DOMAIN-SUFFIX,soso.com,DIRECT +DOMAIN-SUFFIX,soufun.com,DIRECT +DOMAIN-SUFFIX,soufunimg.com,DIRECT +DOMAIN-SUFFIX,staticfile.org,DIRECT +DOMAIN-SUFFIX,staticsdo.com,DIRECT +DOMAIN-SUFFIX,suning.com,DIRECT +DOMAIN-SUFFIX,szzfgjj.com,DIRECT +DOMAIN-SUFFIX,tanx.com,DIRECT +DOMAIN-SUFFIX,tbcache.com,DIRECT +DOMAIN-SUFFIX,tdimg.com,DIRECT +DOMAIN-SUFFIX,tencent.com,DIRECT +DOMAIN-SUFFIX,tenpay.com,DIRECT +DOMAIN-SUFFIX,tgbus.com,DIRECT +DOMAIN-SUFFIX,thawte.com,DIRECT +DOMAIN-SUFFIX,tiancity.com,DIRECT +DOMAIN-SUFFIX,tianyaui.com,DIRECT +DOMAIN-SUFFIX,tiexue.net,DIRECT +DOMAIN-SUFFIX,tmall.com,DIRECT +DOMAIN-SUFFIX,tmcdn.net,DIRECT +DOMAIN-SUFFIX,tom.com,DIRECT +DOMAIN-SUFFIX,tomonline-inc.com,DIRECT +DOMAIN-SUFFIX,tuan800.com,DIRECT +DOMAIN-SUFFIX,tuan800.net,DIRECT +DOMAIN-SUFFIX,tuanimg.com,DIRECT +DOMAIN-SUFFIX,tudou.com,DIRECT +DOMAIN-SUFFIX,tudouui.com,DIRECT +DOMAIN-SUFFIX,tuniu.com,DIRECT +DOMAIN-SUFFIX,u148.net,DIRECT +DOMAIN-SUFFIX,u17.com,DIRECT +DOMAIN-SUFFIX,ubuntu.com,DIRECT +DOMAIN-SUFFIX,ucjoy.com,DIRECT +DOMAIN-SUFFIX,uni-marketers.com,DIRECT +DOMAIN-SUFFIX,unionpay.com,DIRECT +DOMAIN-SUFFIX,unionpaysecure.com,DIRECT +DOMAIN-SUFFIX,upaiyun.com,DIRECT +DOMAIN-SUFFIX,upyun.com,DIRECT +DOMAIN-SUFFIX,uusee.com,DIRECT +DOMAIN-SUFFIX,uuu9.com,DIRECT +DOMAIN-SUFFIX,vaikan.com,DIRECT +DOMAIN-SUFFIX,vancl.com,DIRECT +DOMAIN-SUFFIX,vcimg.com,DIRECT +DOMAIN-SUFFIX,verycd.com,DIRECT +DOMAIN-SUFFIX,wandoujia.com,DIRECT +DOMAIN-SUFFIX,wdjimg.com,DIRECT +DOMAIN-SUFFIX,weibo.com,DIRECT +DOMAIN-SUFFIX,weiphone.com,DIRECT +DOMAIN-SUFFIX,weiyun.com,DIRECT +DOMAIN-SUFFIX,west263.com,DIRECT +DOMAIN-SUFFIX,wrating.com,DIRECT +DOMAIN-SUFFIX,wumii.com,DIRECT +DOMAIN-SUFFIX,xdcdn.net,DIRECT +DOMAIN-SUFFIX,xiachufang.com,DIRECT +DOMAIN-SUFFIX,xiami.com,DIRECT +DOMAIN-SUFFIX,xiami.net,DIRECT +DOMAIN-SUFFIX,xiaomi.com,DIRECT +DOMAIN-SUFFIX,xiaonei.com,DIRECT +DOMAIN-SUFFIX,xiazaiba.com,DIRECT +DOMAIN-SUFFIX,xici.net,DIRECT +DOMAIN-SUFFIX,xilu.com,DIRECT +DOMAIN-SUFFIX,xinhuanet.com,DIRECT +DOMAIN-SUFFIX,xinnet.com,DIRECT +DOMAIN-SUFFIX,xlpan.com,DIRECT +DOMAIN-SUFFIX,xnpic.com,DIRECT +DOMAIN-SUFFIX,xungou.com,DIRECT +DOMAIN-SUFFIX,xunlei.com,DIRECT +DOMAIN-SUFFIX,ydstatic.com,DIRECT +DOMAIN-SUFFIX,yesky.com,DIRECT +DOMAIN-SUFFIX,yeyou.com,DIRECT +DOMAIN-SUFFIX,yihaodian.com,DIRECT +DOMAIN-SUFFIX,yihaodianimg.com,DIRECT +DOMAIN-SUFFIX,yingjiesheng.com,DIRECT +DOMAIN-SUFFIX,yintai.com,DIRECT +DOMAIN-SUFFIX,yinyuetai.com,DIRECT +DOMAIN-SUFFIX,yiqifa.com,DIRECT +DOMAIN-SUFFIX,qingjie.me,DIRECT +DOMAIN-SUFFIX,yixun.com,DIRECT +DOMAIN-SUFFIX,ykimg.com,DIRECT +DOMAIN-SUFFIX,ynet.com,DIRECT +DOMAIN-SUFFIX,youdao.com,DIRECT +DOMAIN-SUFFIX,eqxiu.com,DIRECT +DOMAIN-SUFFIX,yougou.com,DIRECT +DOMAIN-SUFFIX,youku.com,DIRECT +DOMAIN-SUFFIX,yupoo.com,DIRECT +DOMAIN-SUFFIX,yy.com,DIRECT +DOMAIN-SUFFIX,zbjimg.com,DIRECT +DOMAIN-SUFFIX,zhaopin.com,DIRECT +DOMAIN-SUFFIX,zhi.hu,DIRECT +DOMAIN-SUFFIX,zhihu.com,DIRECT +DOMAIN-SUFFIX,zhimg.com,DIRECT +DOMAIN-SUFFIX,zhubajie.com,DIRECT +DOMAIN-SUFFIX,zongheng.com,DIRECT +DOMAIN-SUFFIX,v2ex.com,DIRECT +DOMAIN-SUFFIX,hi-pda.com,DIRECT +DOMAIN-SUFFIX,yhd.com,DIRECT +DOMAIN-SUFFIX,58cdn.com,DIRECT +DOMAIN-SUFFIX,avosapps.com,DIRECT +DOMAIN-SUFFIX,mob.com,DIRECT +DOMAIN-SUFFIX,same.com,DIRECT +DOMAIN-SUFFIX,toutiao.com,DIRECT +DOMAIN-SUFFIX,zaih.com,DIRECT +DOMAIN-SUFFIX,lantouzi.com,DIRECT +DOMAIN-SUFFIX,amap.com,DIRECT +DOMAIN-SUFFIX,haosou.com,DIRECT +DOMAIN-SUFFIX,huofu.com,DIRECT +DOMAIN-SUFFIX,5wei.com,DIRECT +DOMAIN-SUFFIX,travelrely.com,DIRECT +DOMAIN-SUFFIX,seekingalpha.com,DIRECT +DOMAIN-SUFFIX,appsflyer.com,DIRECT +DOMAIN-SUFFIX,nyt.com,Proxy +DOMAIN-SUFFIX,nytco.com,Proxy +DOMAIN-SUFFIX,nytimes.com,Proxy +DOMAIN-SUFFIX,nytimg.com,Proxy +DOMAIN-SUFFIX,nytstyle.com,Proxy +DOMAIN-SUFFIX,doubleclick.net,REJECT +DOMAIN-SUFFIX,googleadservices.com,REJECT + +DOMAIN-SUFFIX,actives.youku.com,REJECT +DOMAIN-SUFFIX,ad.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,atm.youku.com,REJECT +DOMAIN-SUFFIX,c.yes.youku.com,REJECT +DOMAIN-SUFFIX,lstat.youku.com,REJECT +DOMAIN-SUFFIX,lvip.youku.com,REJECT +DOMAIN-SUFFIX,p.l.youku.com,REJECT +DOMAIN-SUFFIX,r.l.youku.com,REJECT +DOMAIN-SUFFIX,stat.youku.com,REJECT +DOMAIN-SUFFIX,static.lstat.youku.com,REJECT +DOMAIN-SUFFIX,atm.youku.com,REJECT +DOMAIN-SUFFIX,ad.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,statis.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,ad.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,count.atm.youku.com,REJECT + + +#DOMAIN-SUFFIX,gtimg.com,DIRECT + + +# Toutiao +#DOMAIN,ic.snssdk.com,REJECT + + +# Zhuishu +DOMAIN-SUFFIX,zhuishushenqi.com,DIRECT + +# Appzapp By @冯冯ryan_ +DOMAIN-KEYWORD,appzapp,DIRECT + +# CDN +DOMAIN-KEYWORD,ccgslb,DIRECT +DOMAIN-KEYWORD,chinacache,DIRECT + +# Duolinguo +DOMAIN-KEYWORD,duolingo,DIRECT + +# Synology +DOMAIN-KEYWORD,0x,DIRECT + +# Moke +DOMAIN-KEYWORD,moke,DIRECT +DOMAIN-KEYWORD,sinaimg,DIRECT + +# 12306 +DOMAIN-KEYWORD,steam,DIRECT +DOMAIN-KEYWORD,alipay,DIRECT +DOMAIN-KEYWORD,360buy,DIRECT +DOMAIN-KEYWORD,alimama,DIRECT + + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + + +DOMAIN,g.co,Proxy +DOMAIN,goo.gl,Proxy + + +DOMAIN,app.adjust.com,Proxy +DOMAIN,api.weather.com,Proxy + +# Snapchat +DOMAIN,data.flurry.com,Proxy +DOMAIN,app.snapchat.com,Proxy + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! +DOMAIN-SUFFIX,ggpht.com,Proxy +DOMAIN-SUFFIX,fb.com,Proxy + +# Amazon +DOMAIN-SUFFIX,amazon.com,Proxy +DOMAIN-SUFFIX,amazonaws.com,Proxy +DOMAIN-SUFFIX,glue-static.s3-external-3.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3-eu-west-1.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3.amazonaws.com,Proxy +DOMAIN-SUFFIX,images-amazon.com,Proxy +DOMAIN-SUFFIX,ssl-images-amazon.com,Proxy + +# TWITCH +DOMAIN-SUFFIX,ioam.de,Proxy + + +# KUVVA +DOMAIN-SUFFIX,kuvva.com,Proxy +DOMAIN-SUFFIX,twimg.com,Proxy +DOMAIN-SUFFIX,edgekey.net,Proxy + +# Line By @pikatse +DOMAIN-SUFFIX,line-cdn.net,Proxy +DOMAIN-SUFFIX,line.me,Proxy,force-remote-dns +DOMAIN-SUFFIX,line.naver.jp,Proxy,force-remote-dns +DOMAIN-SUFFIX,line-apps.com,Proxy,force-remote-dns + +# VOA +DOMAIN-SUFFIX,voacantonese.com,Proxy +DOMAIN-SUFFIX,voachinese.com,Proxy +DOMAIN-SUFFIX,voachineseblog.com,Proxy +DOMAIN-SUFFIX,voagd.com,Proxy +DOMAIN-SUFFIX,voanews.com,Proxy +DOMAIN-SUFFIX,voatibetan.com,Proxy +DOMAIN-SUFFIX,cn.voa.mobi,Proxy + +#FB +DOMAIN-SUFFIX,fbcdn.net,Proxy +DOMAIN-SUFFIX,t.co,Proxy +DOMAIN-SUFFIX,ggpht,Proxy +DOMAIN-SUFFIX,googleapis.com,Proxy +DOMAIN-SUFFIX,cdninstagram.com,Proxy +DOMAIN-SUFFIX,instagram.com,Proxy +DOMAIN-SUFFIX,tumblr,Proxy +DOMAIN-SUFFIX,yahoo.com,Proxy +DOMAIN-SUFFIX,wikipedia.org,Proxy +# Spotify By @LUDOVICFM +DOMAIN-SUFFIX,scorecardresearch.com,Proxy +DOMAIN-KEYWORD,scdn,Proxy +DOMAIN-KEYWORD,moatads,Proxy + +DOMAIN-KEYWORD,akamaistream,Proxy + +# TVB +DOMAIN-KEYWORD,tvb.com,Proxy + +# OTH +DOMAIN-KEYWORD,wikileaks,Proxy +DOMAIN-KEYWORD,wikimapia,Proxy +DOMAIN-KEYWORD,epochtimes,Proxy +DOMAIN-KEYWORD,uncyclopedia,Proxy +DOMAIN-KEYWORD,tibet,Proxy +DOMAIN-KEYWORD,fgmtv,Proxy +DOMAIN-KEYWORD,geocities,Proxy +DOMAIN-KEYWORD,savetibet,Proxy +DOMAIN-KEYWORD,ntdtv,Proxy +DOMAIN-KEYWORD,falundafa,Proxy +DOMAIN-KEYWORD,taiwannation,Proxy +DOMAIN-KEYWORD,rangzen,Proxy +DOMAIN-KEYWORD,bbc,Proxy +DOMAIN-KEYWORD,bloomberg,Proxy +DOMAIN-KEYWORD,appledaily,Proxy +DOMAIN-KEYWORD,chinaaid,Proxy +DOMAIN-KEYWORD,popyard,Proxy +DOMAIN-KEYWORD,raidcall,Proxy +DOMAIN,qq.com,DIRECT + +# BLOGSPOT +DOMAIN-KEYWORD,blogspot,Proxy + + +DOMAIN-KEYWORD,akamaihd,Proxy,no-resolve +DOMAIN-KEYWORD,google,Proxy,force-remote-dns +DOMAIN-KEYWORD,facebook,Proxy,force-remote-dns +DOMAIN-KEYWORD,youtube,Proxy,force-remote-dns +DOMAIN-SUFFIX,ytimg.com,Prpxy +DOMAIN-KEYWORD,twitter,Proxy,force-remote-dns +DOMAIN-KEYWORD,gmail,Proxy,force-remote-dns +DOMAIN-KEYWORD,instagram,Proxy,force-remote-dns +DOMAIN-KEYWORD,vimeo,Proxy,force-remote-dns +DOMAIN-KEYWORD,deviantart,Proxy,force-remote-dns +DOMAIN-KEYWORD,twitch,Proxy,force-remote-dns +DOMAIN-KEYWORD,jtvnw,Proxy,force-remote-dns +DOMAIN-KEYWORD,ttvnw,Proxy,force-remote-dns +DOMAIN-KEYWORD,dropbox,Proxy,force-remote-dns +DOMAIN-KEYWORD,telegram,Proxy,force-remote-dns +DOMAIN-KEYWORD,spotify,Proxy,force-remote-dns + +DOMAIN,dc.letv.com,REJECT +DOMAIN,ark.letv.com,REJECT +# Telegram +IP-CIDR,91.108.56.0/22,Proxy,no-resolve +IP-CIDR,91.108.4.0/22,Proxy,no-resolve +IP-CIDR,109.239.140.0/24,Proxy,no-resolve +IP-CIDR,149.154.160.0/20,Proxy,no-resolve +IP-CIDR,101.227.14.0/24,REJECT,no-resolve +IP-CIDR,101.227.12.0/24,REJECT,no-resolve +IP-CIDR,111.63.135.146/32,REJECT,no-resolve +IP-CIDR,111.206.22.0/24,REJECT,no-resolve +IP-CIDR,121.251.255.237/32,REJECT,no-resolve +IP-CIDR,123.125.117.0/24,REJECT,no-resolve +IP-CIDR,123.125.118.0/24,REJECT,no-resolve +#IP-CIDR,111.206.13.0/24,REJECT,no-resolve + + +# LAN +IP-CIDR,10.0.0.0/8,DIRECT +IP-CIDR,100.64.0.0/10,DIRECT +IP-CIDR,127.0.0.0/8,DIRECT +IP-CIDR,172.16.0.0/12,DIRECT +IP-CIDR,192.168.0.0/16,DIRECT +IP-CIDR,169.254.0.0.0/16,DIRECT +IP-CIDR,17.0.0.0/8,DIRECT +GEOIP, CN, DIRECT +GEOIP, US, Proxy +FINAL, Proxy diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6b28717 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2016, networkextension +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of SSencrypt nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/PacketTunnel/ENV.swift b/PacketTunnel/ENV.swift new file mode 100644 index 0000000..f6d6dde --- /dev/null +++ b/PacketTunnel/ENV.swift @@ -0,0 +1,55 @@ +// +// ENV.swift +// Surf +// +// Created by abigt on 2018/1/3. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Foundation +import XRuler +import SFSocket +import Xcon +import XProxy +import AxLogger +func prepare() { + // + NSLog("init ################2222") + SKit.proxyIpAddr = "240.7.1.10" + SKit.vpnServer = "240.89.6.4" + SKit.dnsAddr = "218.75.4.130" + SKit.proxyHTTPSIpAddr = "240.7.1.11" + SKit.xxIpAddr = "240.7.1.12" + SKit.tunIP = "240.7.1.9" + SFSettingModule.setting.mode = .socket + XRuler.kProxyGroupFile = ".ProxyGroup" + AxLogger.logleve = .Debug + #if os(iOS) + + if !SKit.prepare("group.com.abigt.Surf", app: "xxxx", config: "surf.con"){ + fatalError("framework init error!") + } + NSLog("init ################333") + #elseif os(macOS) + + if !SKit.prepare("745WQDK4L7.com.abigt.Surf", app: "xxxx", config: "abigt.conf"){ + fatalError("framework init error!") + } + #endif + +} +func test() { + if let _ = SFSettingModule.setting.findRuleByString("www.google.com", useragent: ""){ + + } + let _ = ProxyGroupSettings.share.findProxy("Proxy") + +} +func prepareApp() { + Xcon.debugEnable = true + XProxy.debugEanble = true + + XRuler.kProxyGroupFile = ".ProxyGroup" + XRuler.groupIdentifier = "group.com.abigt.Surf" + SKit.groupIdentifier = "group.com.abigt.Surf" +} diff --git a/PacketTunnel/Mac/Info.plist b/PacketTunnel/Mac/Info.plist new file mode 100644 index 0000000..3ba6685 --- /dev/null +++ b/PacketTunnel/Mac/Info.plist @@ -0,0 +1,37 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + PacketTunnel-Mac + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 2.0.2 + CFBundleSignature + ???? + CFBundleVersion + 100 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + NSHumanReadableCopyright + Copyright © 2015年 abigt. All rights reserved. + + diff --git a/PacketTunnel/Mac/PacketTunnel-Mac-Bridging-Header.h b/PacketTunnel/Mac/PacketTunnel-Mac-Bridging-Header.h new file mode 100644 index 0000000..1855154 --- /dev/null +++ b/PacketTunnel/Mac/PacketTunnel-Mac-Bridging-Header.h @@ -0,0 +1,38 @@ +// +// PacketTunnel-Bridging-Header.h +// Surf +// +// Created by 孔祥波 on 15/12/3. +// Copyright © 2015年 abigt. All rights reserved. +// + +#ifndef PacketTunnel_Bridging_Header_h +#define PacketTunnel_Bridging_Header_h +//#import "SFHeader.h" + +#include +//#import "ServerUtils.h" +//#import +////#include +//#ifdef TCP_MSS +//#undef TCP_MSS +//#define TCP_MSS 0x05b4 +//#endif +//#import "ICMPForwarder.h" +//#import "SFHeader.h" + + +#include + +#ifdef DEBUG +#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#else +#define DLog(...) +#endif +#import +#import + +//#define USE_CRYPTO_OPENSSL=1 +#endif /* PacketTunnel_Bridging_Header_h */ + + diff --git a/PacketTunnel/Mac/PacketTunnel_Mac-Swift.h b/PacketTunnel/Mac/PacketTunnel_Mac-Swift.h new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/PacketTunnel/Mac/PacketTunnel_Mac-Swift.h @@ -0,0 +1 @@ + diff --git a/PacketTunnel/Mac/PacketTunnel_Mac.entitlements b/PacketTunnel/Mac/PacketTunnel_Mac.entitlements new file mode 100644 index 0000000..0ab7b90 --- /dev/null +++ b/PacketTunnel/Mac/PacketTunnel_Mac.entitlements @@ -0,0 +1,33 @@ + + + + + com.apple.application-identifier + 745WQDK4L7.com.abigt.Surf.mac.extension + com.apple.developer.networking.networkextension + + app-proxy-provider + packet-tunnel-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + com.apple.developer.team-identifier + 745WQDK4L7 + com.apple.security.app-sandbox + + com.apple.security.application-groups + + 745WQDK4L7.com.abigt.Surf + + com.apple.security.network.client + + com.apple.security.network.server + + keychain-access-groups + + 745WQDK4L7.* + + + diff --git a/PacketTunnel/PacketTunnel-Bridging-Header.h b/PacketTunnel/PacketTunnel-Bridging-Header.h new file mode 100644 index 0000000..358c07d --- /dev/null +++ b/PacketTunnel/PacketTunnel-Bridging-Header.h @@ -0,0 +1,16 @@ +// +// PacketTunnel-Bridging-Header.h +// Surf +// +// Created by 孔祥波 on 15/12/3. +// Copyright © 2015年 yarshure. All rights reserved. +// + +#ifndef PacketTunnel_Bridging_Header_h +#define PacketTunnel_Bridging_Header_h + +#import "SFHeader" + + +#endif /* PacketTunnel_Bridging_Header_h */ + diff --git a/PacketTunnel/PacketTunnel-Mac.xcconfig b/PacketTunnel/PacketTunnel-Mac.xcconfig new file mode 100644 index 0000000..65eb5d4 --- /dev/null +++ b/PacketTunnel/PacketTunnel-Mac.xcconfig @@ -0,0 +1,23 @@ +// +// PacketTunnel.xcconfig +// Surf +// +// Created by abigt on 16/1/4. +// Copyright © 2016年 abigt. All rights reserved. +// +//ALWAYS_SEARCH_USER_PATHS = YES +//FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/Surf-Mac" +//HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/Shared/header" "$(SRCROOT)/MMDB" "$(SRCROOT)/shared/lwip/badvpn" "$(SRCROOT)/libsodium-ios/include" "$(SRCROOT)/lib" +//USER_HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/Shared/header" "$(SRCROOT)/shared/lwip/src/include/"** "$(SRCROOT)/shared/lwip/custom" "$(SRCROOT)/Shared/proxy/ss" +//OTHER_CFLAGS = $(inherited) -isystem +//OTHER_LDFLAGS = $(inherited) -lsodium -lmbedcrypto +//LIBRARY_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)" + +FRAMEWORK_SEARCH_PATHS = $(inherited) //"$(PROJECT_DIR)/Surf-Mac" +HEADER_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/share/include" "$(SRCROOT)/share/include/sodium" "$(SRCROOT)/Shared/header" "$(SRCROOT)/MMDB" "$(SRCROOT)/shared/lwip/badvpn" +USER_HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/Shared/header" "$(SRCROOT)/shared/lwip/src/include/"** "$(SRCROOT)/shared/lwip/custom" "$(SRCROOT)/Shared/proxy/ss" +OTHER_CFLAGS = $(inherited) -isystem +OTHER_LDFLAGS = $(inherited) //-lsodium -lcrypto//-mbedcrypto // -lcrypto // +LIBRARY_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)" +//SSL_LIB_DEFINE = USE_CRYPTO_OPENSSL=1 TCP_MSS=1460 +SSL_LIB_DEFINE = TCP_MSS=1460 diff --git a/PacketTunnel/PacketTunnelProvider.swift b/PacketTunnel/PacketTunnelProvider.swift new file mode 100644 index 0000000..ecbea0e --- /dev/null +++ b/PacketTunnel/PacketTunnelProvider.swift @@ -0,0 +1,40 @@ + +// +// PacketTunnelProvider.swift +// PacketTunnel +// +// Created by kiwi on 15/11/23. +// Copyright © 2015年 abigt. All rights reserved. +// + +import NetworkExtension +import SwiftyJSON +import SFSocket +import AxLogger +import Crashlytics +import Fabric +import Xcon +import XRuler + +class PacketTunnelProvider: SFPacketTunnelProvider{ + + override func startTunnel(options: [String : NSObject]? = nil, completionHandler: @escaping (Error?) -> Void) { + prepare() + #if os(iOS) + + DispatchQueue.main.async { + autoreleasepool { + Fabric.with([Crashlytics.self]) + Fabric.with([Answers.self]) + Answers.logCustomEvent(withName: "VPN", + customAttributes: [ + "Started": "", + + ]) + } + + } + #endif + super.start(options: options, completionHandler: completionHandler) + } +} diff --git a/PacketTunnel/Surf-Swift.h b/PacketTunnel/Surf-Swift.h new file mode 100644 index 0000000..3e3c858 --- /dev/null +++ b/PacketTunnel/Surf-Swift.h @@ -0,0 +1,359 @@ +// Generated by Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76) +#pragma clang diagnostic push + +#if defined(__has_include) && __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#include +#include +#include +#include + +#if defined(__has_include) && __has_include() +# include +#elif !defined(__cplusplus) || __cplusplus < 201103L +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +#endif + +typedef struct _NSZone NSZone; + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif + +#if defined(__has_attribute) && __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +#else +# define SWIFT_RUNTIME_NAME(X) +#endif +#if defined(__has_attribute) && __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +#else +# define SWIFT_COMPILE_NAME(X) +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif + +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif + +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif + +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if defined(__has_attribute) && __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type +#endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +#if defined(__has_feature) && __has_feature(modules) +@import UIKit; +@import AVFoundation; +@import ObjectiveC; +@import Foundation; +#endif + +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +@class NSBundle; +@class NSCoder; + +SWIFT_CLASS("_TtC4Surf25AcknowledgeViewController") +@interface AcknowledgeViewController : UIViewController +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class BarcodeScanViewController; + + +/// The tunnel delegate protocol. +SWIFT_PROTOCOL("_TtP4Surf19BarcodeScanDelegate_") +@protocol BarcodeScanDelegate +- (void)barcodeScanDidScan:(BarcodeScanViewController * __nonnull)controller configString:(NSString * __nonnull)configString; +- (void)barcodeScanCancelScan:(BarcodeScanViewController * __nonnull)controller; +@end + +@class KKSocks; +@protocol AddEditDelegate; +@class NSMutableArray; +@class UISegmentedControl; +@class UIStoryboardSegue; +@class TextFieldCell; + +SWIFT_CLASS("_TtC4Surf17AddEditController") +@interface AddEditController : UITableViewController +@property (nonatomic) NSInteger numberOfSetting; +@property (nonatomic) BOOL useCamera; +@property (nonatomic, strong) KKSocks * __nonnull config; +@property (nonatomic, strong) id __nullable delegate; +@property (nonatomic) BOOL typeHttp; +@property (nonatomic, strong) NSMutableArray * __nonnull textFields; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified nameCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified addressCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified portCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified passwdCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified methodCell; +- (void)viewDidLoad; +- (void)loadConfig; +- (void)valueChanged:(UISegmentedControl * __nonnull)sender; +- (void)saveConfig:(id __nonnull)sender; +- (IBAction)useBarcode:(id __nonnull)sender; +- (void)barcodeScanDidScan:(BarcodeScanViewController * __nonnull)controller configString:(NSString * __nonnull)configString; +- (void)barcodeScanCancelScan:(BarcodeScanViewController * __nonnull)controller; +- (void)prepareForSegue:(UIStoryboardSegue * __nonnull)segue sender:(id __nullable)sender; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + + +/// The tunnel delegate protocol. +SWIFT_PROTOCOL("_TtP4Surf15AddEditDelegate_") +@protocol AddEditDelegate +- (void)addConfig:(AddEditController * __nonnull)controller config:(KKSocks * __nonnull)config; +@end + +@class UIWindow; +@class UIApplication; +@class NSObject; + +SWIFT_CLASS("_TtC4Surf11AppDelegate") +@interface AppDelegate : UIResponder +@property (nonatomic, strong) UIWindow * __nullable window; +- (BOOL)application:(UIApplication * __nonnull)application didFinishLaunchingWithOptions:(NSDictionary * __nullable)launchOptions; +- (void)applicationWillResignActive:(UIApplication * __nonnull)application; +- (void)applicationDidEnterBackground:(UIApplication * __nonnull)application; +- (void)applicationWillEnterForeground:(UIApplication * __nonnull)application; +- (void)applicationDidBecomeActive:(UIApplication * __nonnull)application; +- (void)applicationWillTerminate:(UIApplication * __nonnull)application; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +@class AVCaptureSession; +@class AVCaptureVideoPreviewLayer; +@class AVCaptureOutput; +@class AVCaptureConnection; + +SWIFT_CLASS("_TtC4Surf25BarcodeScanViewController") +@interface BarcodeScanViewController : UIViewController +@property (nonatomic, readonly, copy) NSString * __nonnull kScanQRCodeQueueName; +@property (nonatomic, strong) AVCaptureSession * __nullable captureSession; +@property (nonatomic, strong) AVCaptureVideoPreviewLayer * __nullable videoPreviewLayer; +@property (nonatomic) BOOL useCamera; +@property (nonatomic, strong) id __nullable delegate; +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (IBAction)cancleAction:(id __nonnull)sender; +- (BOOL)startReading; +- (void)stopReading; +- (void)captureOutput:(AVCaptureOutput * __null_unspecified)captureOutput didOutputMetadataObjects:(NSArray * __null_unspecified)metadataObjects fromConnection:(AVCaptureConnection * __null_unspecified)connection; +- (void)reportScanResult:(NSString * __null_unspecified)result; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC4Surf9DataShare") +@interface DataShare : NSObject ++ (BOOL)save:(KKSocks * __nonnull)sock; ++ (NSString * __nonnull)configPath; ++ (KKSocks * __nonnull)readConfig; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC4Surf23HelpTableViewController") +@interface HelpTableViewController : UITableViewController +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class NSURL; +@class UITextView; + +SWIFT_CLASS("_TtC4Surf21LogFileViewController") +@interface LogFileViewController : UIViewController +@property (nonatomic, strong) NSURL * __nullable filePath; +@property (nonatomic, weak) IBOutlet UITextView * __nullable textView; +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class UITableView; +@class NSIndexPath; +@class UITableViewCell; + +SWIFT_CLASS("_TtC4Surf26LogListTableViewController") +@interface LogListTableViewController : UITableViewController +@property (nonatomic, copy) NSArray * __nonnull fileList; +- (void)viewDidLoad; +- (void)viewWillAppear:(BOOL)animated; +- (void)viewDidAppear:(BOOL)animated; +- (void)findFiles; +- (void)didReceiveMemoryWarning; +- (NSInteger)numberOfSectionsInTableView:(UITableView * __nonnull)tableView; +- (NSInteger)tableView:(UITableView * __nonnull)tableView numberOfRowsInSection:(NSInteger)section; +- (UITableViewCell * __nonnull)tableView:(UITableView * __nonnull)tableView cellForRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)prepareForSegue:(UIStoryboardSegue * __nonnull)segue sender:(id __nullable)sender; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class NEVPNManager; +@class UIButton; + +SWIFT_CLASS("_TtC4Surf23ProxyListViewController") +@interface ProxyListViewController : UITableViewController + +/// The target VPN configuration. +@property (nonatomic, strong) NEVPNManager * __nonnull targetManager; +@property (nonatomic, strong) NEVPNManager * __nullable configManage; + +/// A list of NEVPNManager objects for the packet tunnel configurations. +@property (nonatomic, copy) NSArray * __nonnull managers; +@property (nonatomic, weak) UIButton * __nullable startStopButton; +@property (nonatomic, strong) NSMutableArray * __nonnull proxyList; +@property (nonatomic, strong) NSIndexPath * __nullable selectPath; +@property (nonatomic, strong) NSURL * __nonnull applicationDocumentsDirectory; +- (void)loadProxys; + +/// Unwind segue handler. +- (IBAction)handleUnwind:(UIStoryboardSegue * __nonnull)sender; +- (void)saveProxys; + +/// Handle the event where the view is being hidden. +- (void)viewWillDisappear:(BOOL)animated; +- (void)viewDidLoad; +- (void)findUsedConfig; + +/// Handle the event of the view being displayed. +- (void)viewWillAppear:(BOOL)animated; +- (void)didReceiveMemoryWarning; +- (void)setEditing:(BOOL)editing animated:(BOOL)animated; +- (NSInteger)numberOfSectionsInTableView:(UITableView * __nonnull)tableView; +- (NSInteger)tableView:(UITableView * __nonnull)tableView numberOfRowsInSection:(NSInteger)section; +- (IBAction)startConnect:(id __nonnull)sender; +- (UITableViewCell * __nonnull)tableView:(UITableView * __nonnull)tableView cellForRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)updateCell:(UITableViewCell * __nonnull)cell indexPath:(NSIndexPath * __nonnull)indexPath; +- (BOOL)tableView:(UITableView * __nonnull)tableView canEditRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (UITableViewCellEditingStyle)tableView:(UITableView * __nonnull)tableView editingStyleForRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)tableView:(UITableView * __nonnull)tableView didSelectRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)saveConfig; +- (void)tableView:(UITableView * __nonnull)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)addConfig:(AddEditController * __nonnull)controller config:(KKSocks * __nonnull)config; +- (void)prepareForSegue:(UIStoryboardSegue * __nonnull)segue sender:(id __nullable)sender; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +@interface ProxyListViewController (SWIFT_EXTENSION(Surf)) +- (void)setTargetManager:(NEVPNManager * __nullable)manager title:(NSString * __nullable)title; + +/// Re-load all of the packet tunnel configurations from the Network Extension preferences +- (void)reloadManagers; + +/// Register for configuration change notifications. +- (void)registerStatus; +- (void)observeStatus; + +/// De-register for configuration change notifications. +- (void)stopObservingStatus; +- (void)xpc; + +/// Handle the user toggling the "enabled" switch. +- (IBAction)enabledToggled; + +/// Handle the user toggling the "VPN" switch. +- (IBAction)startStopToggled:(id __nonnull)sender; +@end + + +SWIFT_CLASS("_TtC4Surf20SecondViewController") +@interface SecondViewController : UIViewController +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS_NAMED("Socks") +@interface KKSocks : NSObject +@property (nonatomic, copy) NSString * __nullable proxyName; +@property (nonatomic, copy) NSString * __nullable serverAddress; +@property (nonatomic, copy) NSString * __nullable serverPort; +@property (nonatomic, copy) NSString * __nullable password; +@property (nonatomic, copy) NSString * __nullable method; +@property (nonatomic, copy) NSString * __nullable serverType; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)encodeWithCoder:(NSCoder * __nonnull)aCoder; +@end + +@class UITextField; +@class UILabel; + +SWIFT_CLASS("_TtC4Surf13TextFieldCell") +@interface TextFieldCell : UITableViewCell +@property (nonatomic, weak) IBOutlet UITextField * __null_unspecified textField; +@property (nonatomic, weak) IBOutlet UILabel * __null_unspecified cellLabel; +@property (nonatomic, copy) void (^ __nullable valueChanged)(UITextField * __nonnull); +- (void)textFieldDidEndEditing:(UITextField * __nonnull)textField; +- (BOOL)textFieldShouldReturn:(UITextField * __nonnull)textField; +- (nonnull instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString * __nullable)reuseIdentifier OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +#pragma clang diagnostic pop diff --git a/PacketTunnel/config.pac.js b/PacketTunnel/config.pac.js new file mode 100644 index 0000000..5082d47 --- /dev/null +++ b/PacketTunnel/config.pac.js @@ -0,0 +1,133 @@ +var tunnel = "SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT;"; +var direct = "DIRECT"; +var proxyList = "cdninstagram.com|squarespace.com|aka|licdn.com|gstatic.com|githubusercontent.com|imgur.com|dropboxstatic.com|bitbucket.org|github.com|mzstatic.com|pinboard.in|box.net|gravatar.com|jshint.com|twitch.tv|dropboxusercontent.com|engadget.com|amazon.com|openvpn.net|crashlytics.com|symauth.com|edgecastcdn.net|wikimedia.org|wsj.com|ow.ly|tumblr.com|itunes.com|github.io|lithium.com|wsj.net|openwrt.org|ift.tt|blogspot|t.co|fc2.com|goo.gl|blogcdn.com|twitter.com|linkedin.com|blogsmithmedia.com|instagram|twimg.com|cloudfront.net|docker.com|linode.com|symcd.com|fastly.net|ubnt.com|twitter|fbcdn.net|imageshack.us|fabric.io|wikipedia.com|dnsimple.com|eurekavpt.com|ytimg.com|nytimes.com|megaupload.com|blog.com|akamaihd.net|google|duckduckgo.com|symcb.com|youtube|ssl-images-amazon.com|mobile01.com|sstatic.net|ggpht.com|kenengba.com|me.com|j.mp|dropbox.com|fb.me|staticflickr.com|thepiratebay.org|stackoverflow.com|gmail|bloomberg.com|youtu.be|golang.org|feedburner.com|godaddy.com|facebook|flickr.com|modmyi.com|bit.ly|name.com|appspot.com|vimeo.com|chromium.org|kat.cr|wikipedia.org|wp.com|cloudflare.com|cocoapods.org|dribbble.com|wordpress.com|blogger.com|android.com|digicert.com|tapbots.com|amazonaws.com|cl.ly|akamai.net|angularjs.org".split("|").reduce(function(a, b) { + return a[b] = 1, a; +}, {}); +var directList = "360buy|apple.com|sohu.com|bdimg.com|icloud.com|hao123.com|analytics.126.net|qhimg.com|amap.com|cn|xunlei.com|cnbeta.com|api.smoot.apple.com|baidu.com|taobao.com|alipay|soso.com|lcdn-registration.apple.com|configuration.apple.com|youku.com|suning.com|netease.com|akadns.net|sogou.com|weibo.com|163.com|guzzoni.apple.com|douban.com|xp.apple.com|126.net|ess.apple.com|jd.com|captive.apple.com|cnzz.com|outlook.com|medium.com|tudou.com|ifeng.com|bdstatic.com|haosou.com|alicdn.com|tmall.com|ls.apple.com|smp-device-content.apple.com|iqiyi.com|ykimg.com|qq.com|zhihu.com|push.apple.com|gtimg.com|weather.com".split("|").reduce(function(a, b) { + return a[b] = 1, a; +}, {}); +var rejectList = "duomeng.net|adzerk.net|advertising.com|mobads.baidu.com|googeadsserving.cn|appads.com|adwhirl.com|js-agent.newrelic.com|ads|cr-nielsen.com|stat.ws.126.net|adcome.cn|wooboo.com.cn|admaster.com.cn|guomob.com|asimgs.pplive.cn|simaba.taobao.com|immob.cn|wiyun.com|mmstat.com|domob.com.cn|analytics|smartadserver.com|flurry.com|zhiziyun.com|temp.163.com|cmcore.com|sax.sina.cn|duomeng.cn|adsage.cn|wqmobile.com|aduu.cn|umeng.co|doubleclick.net|cnzz.com|stat.m.jd.com|ark.letv.com|uyunad.com|g.163.com|flurry.co|adxmi.com|monitor.uu.qq.com|tajs.qq.com|localytics.com|baidustatic.com|pos.baidu.com|umeng.com|eclick.baidu.com|m.simaba.taobao.com|inmobi.com|miaozhen.com|umeng.net|ads.mopub.com|waps.cn|mobads-logs.baidu.com|adview.cn|cbjs.baidu.com|adjust.com|acjs.aliyun.com|51.la|iadsdk.apple.com|anquan.org|counter.kingsoft.com|atm.youku.com|lh8.ggpht.com|ad.unimhk.com|adash.m.taobao.com|mob.c|pingtcss.qq.com|duomeng.org|x.jd.com|baifendian.com|adsmogo|cpro.baidu.com|lh7.ggpht.com|track|acs86.com|adwo.com|lh6.ggpht.com|bam.nr-data.net|msga.71.am|dsp.youdao.com|report.qq.com|pingma.qq.com|lh5.ggpht.com|msg.71.am|kejet.net|adinfuse.com|lives.l.qq.com|beacon.sina.com.cn|ad.api.3g.youku.com|adsage.com|traffic|adsmogo.org|nsclick.baidu.com|admob.com|appsflyer.com|lh4.ggpht.com|ads.mobclix.com|applifier.com|www.panoramio.com|beacon.qq.com|duomeng|youmi.net|pagead2.googlesyndication.com|csi.gstatic.com|lh3.ggpht.com|mtj.baidu.com|domob.org|ad.api.3g.tudou.com|coremetrics.com|pixel.wp.com|intely.cn|irs01.com|lh2.ggpht.com|adchina.com|ushaqi.com|tiqcdn.com|mixpanel.com|pingjs.qq.com|lh1.ggpht.com|127.net|union.youdao.com|hm.baidu.com|tapjoyads.com|umtrack.com|madmini.com|wrating.com|tanx.com".split("|").reduce(function(a, b) { + return a[b] = 1, a; +}, {}); +var ipRange = [ + "17.0.0.0\/8\/DIRECT", + "91.108.56.0\/22\/PROXY", + "91.108.4.0\/22\/PROXY", + "109.239.140.0\/24\/PROXY", + "149.154.160.0\/20\/PROXY", + "192.168.0.0\/16\/DIRECT", + "10.0.0.0\/8\/DIRECT", + "172.16.0.0\/12\/DIRECT", + "127.0.0.0\/8\/DIRECT" +]; +var finallyRule = "PROXY"; +var cidrToSubnetMask = { + "0": "0.0.0.0", + "1": "128.0.0.0", + "2": "192.0.0.0", + "3": "224.0.0.0", + "4": "240.0.0.0", + "5": "248.0.0.0", + "6": "252.0.0.0", + "7": "254.0.0.0", + "8": "255.0.0.0", + "9": "255.128.0.0", + "10": "255.192.0.0", + "11": "255.224.0.0", + "12": "255.240.0.0", + "13": "255.248.0.0", + "14": "255.252.0.0", + "15": "255.254.0.0", + "16": "255.255.0.0", + "17": "255.255.128.0", + "18": "255.255.192.0", + "19": "255.255.224.0", + "20": "255.255.240.0", + "21": "255.255.248.0", + "22": "255.255.252.0", + "23": "255.255.254.0", + "24": "255.255.255.0", + "25": "255.255.255.128", + "26": "255.255.255.192", + "27": "255.255.255.224", + "28": "255.255.255.240", + "29": "255.255.255.248", + "30": "255.255.255.252", + "31": "255.255.255.254", + "32": "255.255.255.255" +}; + +ipRange = ipRange.contact( + "0.0.0.0/8/DIRECT", + "10.0.0.0/8/DIRECT", + "100.64.0.0/10/DIRECT", + "127.0.0.0/8/DIRECT", + "169.254.0.0/16/DIRECT", + "172.16.0.0/12/DIRECT", + "192.0.0.0/24/DIRECT", + "192.0.2.0/24/DIRECT", + "192.168.0.0/16/DIRECT", + "198.18.0.0/15/DIRECT", + "198.51.100.0/24/DIRECT", + "203.0.113.0/24/DIRECT", + "224.0.0.0/4/DIRECT", + "240.0.0.0/4/DIRECT", + "255.255.255.255/32/DIRECT" +); + +function FindProxyForURL(url, host) { + if (isPlainHostName(host)) { + return direct; + } + + var domain = host; + var pos = 0; + var idx = 0; + + do { + if (directList.hasOwnProperty(domain)) { + return direct; + } + + if (proxyList.hasOwnProperty(domain) || rejectList.hasOwnProperty(domain)) { + return tunnel; + } + + idx = pos; + pos = host.indexOf(".", pos) + 1; + + if (idx < pos - 1) { + var key = host.substring(idx, pos - 1); + if (directList.hasOwnProperty(key)) { + return direct; + } + if (proxyList.hasOwnProperty(key) || rejectList.hasOwnProperty(key)) { + return tunnel; + } + } + + domain = host.substring(pos); + } while (pos > 0); + + var ip = dnsResolve(host); + + if (!ip) { + return tunnel; + } + + for (var i in ipRange) { + var parts = ipRange[i].split('/'); + if (isInNet(ip, parts[0], cidrToSubnetMask[parts[1]])) { + if (parts[2] == 'DIRECT') { + return direct; + } + return tunnel; + } + } + + if (finallyRule == 'PROXY') { + return tunnel; + } + + return direct; +} \ No newline at end of file diff --git a/PacketTunnel/iOS/.adblock b/PacketTunnel/iOS/.adblock new file mode 100644 index 0000000..7fbbb23 --- /dev/null +++ b/PacketTunnel/iOS/.adblock @@ -0,0 +1,259 @@ +ad.sina.com.cn#Adblock +adm.leju.sina.com.cn#Adblock +atm.sina.com#Adblock +beacon.sina.com.cn#Adblock +dcads.sina.com.cn#Adblock +sax.sina.cn#Adblock +sax.sina.com.cn#Adblock +tjs.sjs.sinajs.cn#Adblock +act.qq.com#Adblock +adsfile.qq.com#Adblock +beacon.qq.com#Adblock +e.qq.com#Adblock +gdt.qq.com#Adblock +l.qq.com#Adblock +monitor.uu.qq.com#Adblock +pgdt.gtimg.cn#Adblock +pingjs.qq.com#Adblock +pingma.qq.com#Adblock +pingtcss.qq.com#Adblock +report.qq.com#Adblock +tajs.qq.com#Adblock +tcss.qq.com#Adblock +3600.com#Adblock +dev.tg.wan.360.cn#Adblock +f.360.cn#Adblock +kuaikan.netmon.360safe.com#Adblock +leak.360.cn#Adblock +openbox.mobilem.360.cn#Adblock +pub.se.360.cn#Adblock +soft.data.weather.360.cn#Adblock +stat.360safe.com#Adblock +stat.m.360.cn#Adblock +update.360safe.com#Adblock +adgeo.163.com#Adblock +bobo.163.com#Adblock +fa.163.com#Adblock +g.163.com#Adblock +gb.corp.163.com#Adblock +oadz.com#Adblock +oimagea2.ydstatic.com#Adblock +pagechoice.net#Adblock +prom.gome.com.cn#Adblock +rlogs.youdao.com#Adblock +static.flv.uuzuonline.com#Adblock +wanproxy.127.net#Adblock +ws.126.net#Adblock +actives.youku.com#Adblock +ad.api.3g.tudou.com#Adblock +ad.api.3g.youku.com#Adblock +ad.m.iqiyi.com#Adblock +adcontrol.tudou.com#Adblock +adplay.tudou.com#Adblock +afp.qiyi.com#Adblock +agn.aty.sohu.com#Adblock +ark.letv.com#Adblock +asimgs.pplive.cn#Adblock +atanx.alicdn.com#Adblock +atm.youku.com#Adblock +c.yes.youku.com#Adblock +cc.xtgreat.com#Adblock +cm.zhiziyun.com#Adblock +cupid.iqiyi.com#Adblock +cupid.qiyi.com#Adblock +d.dsp.imageter.com#Adblock +dc.letv.com#Adblock +de.as.pptv.com#Adblock +g.uusee.com#Adblock +gug.ku6cdn.com#Adblock +ifacelog.iqiyi.com#Adblock +iwstat.tudou.com#Adblock +kwflvcdn.000dn.com#Adblock +lives.l.qq.com#Adblock +logger.baofeng.com#Adblock +logstat.t.sfht.com#Adblock +lstat.youku.com#Adblock +lvip.youku.com#Adblock +m.aty.sohu.com#Adblock +msg.71.am#Adblock +match.rtbidder.net#Adblock +n-st.vip.com#Adblock +n.mark.letv.com#Adblock +nstat.tudou.com#Adblock +p-log.ykimg.com#Adblock +p.l.qq.com#Adblock +p.l.ykimg.com#Adblock +p.l.youku.com#Adblock +pics.taobaocdn.com#Adblock +pop.uusee.com#Adblock +pq.stat.ku6.com#Adblock +pv.sohu.com#Adblock +r.l.youku.com#Adblock +rcd.iqiyi.com#Adblock +rtb.behe.com#Adblock +show.re.taobao.com#Adblock +shrek.6.cn#Adblock +simba.6.cn#Adblock +st.vq.ku6.cn#Adblock +stat.tudou.com#Adblock +stat.youku.com#Adblock +static.g.ppstream.com#Adblock +static.ku6.com#Adblock +static.lstat.youku.com#Adblock +stats.tudou.com#Adblock +strip.taobaocdn.com#Adblock +stuff.cdn.biddingx.com#Adblock +t.cr-nielsen.com#Adblock +tns.simba.taobao.com#Adblock +traffic.uusee.com#Adblock +union.6.cn#Adblock +duomeng.net#Adblock +adzerk.net#Adblock +advertising.com#Adblock +mobads.baidu.com#Adblock +googeadsserving.cn#Adblock +appads.com#Adblock +adwhirl.com#Adblock +js-agent.newrelic.com#Adblock +cr-nielsen.com#Adblock +stat.ws.126.net#Adblock +adcome.cn#Adblock +wooboo.com.cn#Adblock +admaster.com.cn#Adblock +guomob.com#Adblock +asimgs.pplive.cn#Adblock +simaba.taobao.com#Adblock +immob.cn#Adblock +wiyun.com#Adblock +mmstat.com#Adblock +domob.com.cn#Adblock +analytics#Adblock +smartadserver.com#Adblock +flurry.com#Adblock +zhiziyun.com#Adblock +temp.163.com#Adblock +cmcore.com#Adblock +sax.sina.cn#Adblock +duomeng.cn#Adblock +adsage.cn#Adblock +wqmobile.com#Adblock +aduu.cn#Adblock +umeng.co#Adblock +doubleclick.net#Adblock +cnzz.com#Adblock +stat.m.jd.com#Adblock +ark.letv.com#Adblock +uyunad.com#Adblock +g.163.com#Adblock +flurry.co#Adblock +adxmi.com#Adblock +monitor.uu.qq.com#Adblock +tajs.qq.com#Adblock +localytics.com#Adblock +pos.baidu.com#Adblock +umeng.com#Adblock +eclick.baidu.com#Adblock +m.simaba.taobao.com#Adblock +inmobi.com#Adblock +miaozhen.com#Adblock +umeng.net#Adblock +ads.mopub.com#Adblock +waps.cn#Adblock +mobads-logs.baidu.com#Adblock +adview.cn#Adblock +cbjs.baidu.com#Adblock +adjust.com#Adblock +acjs.aliyun.com#Adblock +51.la#Adblock +iadsdk.apple.com#Adblock +anquan.org#Adblock +counter.kingsoft.com#Adblock +atm.youku.com#Adblock +lh8.ggpht.com#Adblock +ad.unimhk.com#Adblock +adash.m.taobao.com#Adblock +mob.c#Adblock +pingtcss.qq.com#Adblock +duomeng.org#Adblock +x.jd.com#Adblock +baifendian.com#Adblock +adsmogo#Adblock +cpro.baidu.com#Adblock +lh7.ggpht.com#Adblock +track#Adblock +acs86.com#Adblock +adwo.com#Adblock +lh6.ggpht.com#Adblock +bam.nr-data.net#Adblock +msga.71.am#Adblock +dsp.youdao.com#Adblock +report.qq.com#Adblock +pingma.qq.com#Adblock +lh5.ggpht.com#Adblock +msg.71.am#Adblock +kejet.net#Adblock +adinfuse.com#Adblock +lives.l.qq.com#Adblock +beacon.sina.com.cn#Adblock +ad.api.3g.youku.com#Adblock +adsage.com#Adblock +traffic#Adblock +adsmogo.org#Adblock +nsclick.baidu.com#Adblock +admob.com#Adblock +appsflyer.com#Adblock +lh4.ggpht.com#Adblock +ads.mobclix.com#Adblock +applifier.com#Adblock +www.panoramio.com#Adblock +beacon.qq.com#Adblock +duomeng#Adblock +youmi.net#Adblock +pagead2.googlesyndication.com#Adblock +csi.gstatic.com#Adblock +lh3.ggpht.com#Adblock +mtj.baidu.com#Adblock +domob.org#Adblock +ad.api.3g.tudou.com#Adblock +coremetrics.com#Adblock +pixel.wp.com#Adblock +intely.cn#Adblock +irs01.com#Adblock +lh2.ggpht.com#Adblock +adchina.com#Adblock +ushaqi.com#Adblock +tiqcdn.com#Adblock +mixpanel.com#Adblock +pingjs.qq.com#Adblock +lh1.ggpht.com#Adblock +127.net#Adblock +union.youdao.com#Adblock +hm.baidu.com#Adblock +tapjoyads.com#Adblock +umtrack.com#Adblock +madmini.com#Adblock +wrating.com#Adblock +tanx.com#Adblock +yes1.feng.com#Adblock +statis.api.3g.youku.com#Adblock +ad\.api\.3g\.youku\.com#优酷土豆 +count.atm.youku.com#优酷土豆 +atm\.youku\.com#优酷土豆 +ad\.api\.3g\.tudou\.com#优酷土豆 +lives\.l\.qq\.com#腾讯视频 +ark\.letv\.com#乐视 +asimgs\.pplive\.cn#PPTV +agn\.aty\.sohu\.com#搜狐视频 +x\.da\.hunantv\.com#芒果tv +124.160.194.11:8080#联通DNS +miaozhen\.com#秒针 +^(.*)?ads(.*)?\.baidu\.com#百度 +^(.*)ads\.g\.doubleclick\.net#Google_AdMob +^([^/:]*\.)?inmob\.com#Inmobi +^amob\.acs86\.com#易传媒 +^([^/:]*\.)?domob(cdn)?\.[cn|com]#多盟 +^([^/:]*\.)?duomeng\.[net|cn|org]#多盟 +^([^/:]*\.)?ads\.mopub\.[com|cn]#MoPub +^impact\.applifier\.com#Unity +^(.*)?gdt\.qq\.com#腾讯广点通 +^(.*)?litchix\.com#Onlinetime \ No newline at end of file diff --git a/PacketTunnel/iOS/Info.plist b/PacketTunnel/iOS/Info.plist new file mode 100644 index 0000000..a1d78f9 --- /dev/null +++ b/PacketTunnel/iOS/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + PacketTunnel + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 4.0 + CFBundleSignature + ???? + CFBundleVersion + 805 + Fabric + + APIKey + + Kits + + + KitInfo + + KitName + Crashlytics + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + + diff --git a/PacketTunnel/iOS/PacketTunnel-Bridging-Header.h b/PacketTunnel/iOS/PacketTunnel-Bridging-Header.h new file mode 100644 index 0000000..8f0d744 --- /dev/null +++ b/PacketTunnel/iOS/PacketTunnel-Bridging-Header.h @@ -0,0 +1,33 @@ +// +// PacketTunnel-Bridging-Header.h +// Surf +// +// Created by 孔祥波 on 15/12/3. +// Copyright © 2015年 abigt. All rights reserved. +// + +#ifndef PacketTunnel_Bridging_Header_h +#define PacketTunnel_Bridging_Header_h + +//#import "ICMPForwarder.h" +//#import "SFHeader.h" +//#import "MMDB.h" + +#include +//#import "GCDAsyncSocket.h" +//#import "GCDAsyncUdpSocket.h" + +//#import "SFVPNSession.h" +//#include "HTTPProxyServer.h" +//#ifdef DEBUG +//#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +//#else +//#define DLog(fmt, ...) {} +//NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); + +//#define DLog(...) +//#endif +//#import +//#import +#endif /* PacketTunnel_Bridging_Header_h */ + diff --git a/PacketTunnel/iOS/PacketTunnel-Swift.h b/PacketTunnel/iOS/PacketTunnel-Swift.h new file mode 100644 index 0000000..9ec9b51 --- /dev/null +++ b/PacketTunnel/iOS/PacketTunnel-Swift.h @@ -0,0 +1,797 @@ +// Generated by Apple Swift version 2.3 (swiftlang-800.10.11 clang-800.0.36) +#pragma clang diagnostic push + +#if defined(__has_include) && __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#include +#include +#include +#include + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if defined(__has_include) && __has_include() +# include +# elif !defined(__cplusplus) || __cplusplus < 201103L +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif + +#if defined(__has_attribute) && __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +#else +# define SWIFT_RUNTIME_NAME(X) +#endif +#if defined(__has_attribute) && __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +#else +# define SWIFT_COMPILE_NAME(X) +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif + +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif + +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif + +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if defined(__has_attribute) && __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type +# if defined(__has_feature) && __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) SWIFT_ENUM(_type, _name) +# endif +#endif +#if defined(__has_feature) && __has_feature(modules) +@import ObjectiveC; +@import Dispatch; +@import Foundation; +@import Security; +@import NetworkExtension; +@import SystemConfiguration; +#endif + +#import "/Users/abigt/github/surf/PacketTunnel/iOS/PacketTunnel-Bridging-Header.h" + +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +@class Reachability; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS11AxEnvHelper") +@interface AxEnvHelper : NSObject ++ (Reachability * _Nonnull)reachAiblity; ++ (void)setReachAiblity:(Reachability * _Nonnull)value; ++ (NSString * _Nonnull)platform; ++ (NSString * _Nonnull)systemName; ++ (NSString * _Nonnull)deviceName; ++ (NSString * _Nonnull)systemVersion; ++ (NSString * _Nonnull)appVersion; ++ (NSString * _Nonnull)appBuild; ++ (NSString * _Nonnull)deviceModel; ++ (NSString * _Nonnull)deviceLocalizedModel; ++ (NSString * _Nonnull)phoneIdentifier; ++ (NSString * _Nonnull)appIdentifier; ++ (NSString * _Nonnull)screenSize; ++ (NSString * _Nonnull)carrier; ++ (NSString * _Nonnull)networkType; ++ (NSDictionary * _Nonnull)infoDict; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + +@class NSURL; +@class NSDate; +enum AxLoggerLevel : NSInteger; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS8AxLogger") +@interface AxLogger : NSObject ++ (NSURL * _Nonnull)groupURL; ++ (void)setGroupURL:(NSURL * _Nonnull)value; ++ (void)closeLogging; ++ (void)resetLogFile; ++ (void)openLogging:(NSDate * _Nonnull)date; ++ (enum AxLoggerLevel)logleve; ++ (void)setLogleve:(enum AxLoggerLevel)value; ++ (void)log:(NSString * _Nonnull)msg level:(enum AxLoggerLevel)level category:(NSString * _Nonnull)category file:(NSString * _Nonnull)file line:(NSInteger)line ud:(NSDictionary * _Nonnull)ud tags:(NSArray * _Nonnull)tags time:(NSDate * _Nonnull)time; ++ (void)enableConsole:(BOOL)enable; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + +typedef SWIFT_ENUM(NSInteger, AxLoggerLevel) { + AxLoggerLevelInfo = 0, + AxLoggerLevelNotify = 1, + AxLoggerLevelError = 2, + AxLoggerLevelWarning = 3, + AxLoggerLevelTrace = 4, + AxLoggerLevelVerbose = 5, + AxLoggerLevelDebug = 6, +}; + +@class GCDAsyncSocket; +@class NSError; +@class NSData; +@protocol ConnectorDelegate; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS9Connector") +@interface Connector : NSObject +@property (nonatomic, weak) id _Nullable delegate; +@property (nonatomic, copy) NSString * _Nonnull targetHost; +@property (nonatomic) uint16_t targetPort; +@property (nonatomic, copy) NSString * _Nonnull remoteIPaddress; +@property (nonatomic, strong) GCDAsyncSocket * _Nullable socket; +@property (nonatomic) BOOL socks_reading; +@property (nonatomic) BOOL socks_writing; +@property (nonatomic, strong) dispatch_queue_t _Nullable socket_Queue; +@property (nonatomic) NSInteger connectTime; +- (NSString * _Nullable)interfaceAddr; +@property (nonatomic) BOOL shoudClose; +@property (nonatomic) NSInteger cID; +@property (nonatomic, copy) NSString * _Nonnull cIDString; +@property (nonatomic) BOOL isConnected; +@property (nonatomic) BOOL isDisconnected; +- (dispatch_queue_t _Nullable)socketQueue; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithPolicy:(NSString * _Nonnull)policy OBJC_DESIGNATED_INITIALIZER; +- (void)cIDFunc; +- (BOOL)socketDead; +- (void)disconnectWithError:(NSError * _Nonnull)error; +- (void)socketDidDisconnect:(GCDAsyncSocket * _Nonnull)sock withError:(NSError * _Nullable)err; +- (void)writeData:(NSData * _Nonnull)d timeout:(double)timeout tag:(int64_t)tag; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didWriteDataWithTag:(NSInteger)tag; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didReadData:(NSData * _Nonnull)data withTag:(NSInteger)tag; +- (void)start; +- (void)readDataWithTimeout:(double)timeout length:(NSUInteger)length tag:(long)tag; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didConnectToHost:(NSString * _Nonnull)host port:(uint16_t)port; +- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(NSInteger)tag; +- (NSTimeInterval)socket:(GCDAsyncSocket * _Nonnull)sock shouldTimeoutReadWithTag:(NSInteger)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length; +- (NSTimeInterval)socket:(GCDAsyncSocket * _Nonnull)sock shouldTimeoutWriteWithTag:(NSInteger)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length; +@end + + +SWIFT_PROTOCOL("_TtP16PacketTunnel_iOS17ConnectorDelegate_") +@protocol ConnectorDelegate +- (void)connector:(Connector * _Nonnull)connector didReadData:(NSData * _Nonnull)data withTag:(int64_t)tag; +- (void)connectorDidDisconnect:(Connector * _Nonnull)connector withError:(NSError * _Nonnull)withError; +- (void)connector:(Connector * _Nonnull)connector didWriteDataWithTag:(int64_t)tag; +- (void)connectorDidSetupFailed:(Connector * _Nonnull)connector withError:(NSError * _Nonnull)withError; +- (void)connectorDidBecomeAvailable:(Connector * _Nonnull)connector; +- (NSTimeInterval)connector:(Connector * _Nonnull)connector shouldTimeoutReadWithTag:(NSInteger)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS9DNSPacket") +@interface DNSPacket : NSObject +@property (nonatomic) uint16_t identifier; +@property (nonatomic, copy) NSArray * _Nonnull queryDomains; +@property (nonatomic, copy) NSDictionary * _Nonnull answerDomains; +@property (nonatomic, strong) NSData * _Nonnull rawData; +@property (nonatomic) char qr; +@property (nonatomic) uint16_t count; +@property (nonatomic) uint16_t qType; +@property (nonatomic) uint16_t qClass; +@property (nonatomic) uint16_t reqCount; +@property (nonatomic) uint16_t answerCount; +@property (nonatomic, copy) NSArray * _Nonnull ipString; +@property (nonatomic) BOOL finished; +- (nonnull instancetype)initWithData:(NSData * _Nonnull)data OBJC_DESIGNATED_INITIALIZER; ++ (NSString * _Nonnull)findLabel:(uint8_t const * _Null_unspecified)ptr0; ++ (NSData * _Nonnull)genPacketData:(NSString * _Nonnull)ip domain:(NSString * _Nonnull)domain identifier:(uint16_t)identifier; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS15DirectConnector") +@interface DirectConnector : Connector +@property (nonatomic, copy) NSString * _Nullable interfaceName; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didReadData:(NSData * _Nonnull)data withTag:(NSInteger)tag; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didWriteDataWithTag:(NSInteger)tag; +- (void)beginRead; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(NSInteger)tag; +- (void)socketDidCloseReadStream:(GCDAsyncSocket * _Null_unspecified)sock; +- (void)socketDidDisconnect:(GCDAsyncSocket * _Nonnull)sock withError:(NSError * _Null_unspecified)err; +- (void)start; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithPolicy:(NSString * _Nonnull)policy OBJC_DESIGNATED_INITIALIZER; +@end + +@class NSNumber; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS14ProxyConnector") +@interface ProxyConnector : Connector +@property (nonatomic) BOOL tlsSupport; +@property (nonatomic, readonly, copy) NSArray * _Nonnull acceptableCipherSuites; +@property (nonatomic, copy) NSString * _Nonnull pFrontAddress; +@property (nonatomic) uint16_t pFrontPort; +- (void)startTLS; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didReceiveTrust:(SecTrustRef _Null_unspecified)trust completionHandler:(void (^ _Null_unspecified)(BOOL))completionHandler; +- (void)start; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didConnectToHost:(NSString * _Null_unspecified)host port:(uint16_t)port; +@end + +@class NSMutableData; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS21HTTPAesProxyConnector") +@interface HTTPAesProxyConnector : ProxyConnector +@property (nonatomic, copy) NSString * _Nullable interfaceName; +@property (nonatomic) BOOL httpConnected; +@property (nonatomic, strong) NSMutableData * _Nonnull headerData; +- (void)start; +- (void)sendReq; +- (NSInteger)recvHeaderData:(NSData * _Nonnull)data; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didReadData:(NSData * _Nonnull)data withTag:(NSInteger)tag; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didConnectToHost:(NSString * _Null_unspecified)host port:(uint16_t)port; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didWriteDataWithTag:(NSInteger)tag; +- (void)beginRead; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(NSInteger)tag; +- (void)socketDidCloseReadStream:(GCDAsyncSocket * _Null_unspecified)sock; +- (void)writeData:(NSData * _Nonnull)d timeout:(double)timeout tag:(int64_t)tag; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS18HTTPProxyConnector") +@interface HTTPProxyConnector : ProxyConnector +@property (nonatomic) BOOL httpConnected; +@property (nonatomic, strong) NSMutableData * _Nonnull headerData; +- (void)start; +- (void)sendReq; +- (NSInteger)recvHeaderData:(NSData * _Nonnull)data; +- (void)socketDidSecure:(GCDAsyncSocket * _Null_unspecified)sock; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didReadData:(NSData * _Nonnull)data withTag:(NSInteger)tag; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didConnectToHost:(NSString * _Null_unspecified)host port:(uint16_t)port; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didWriteDataWithTag:(NSInteger)tag; +- (void)beginRead; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(NSInteger)tag; +- (void)socketDidCloseReadStream:(GCDAsyncSocket * _Null_unspecified)sock; +- (void)writeData:(NSData * _Nonnull)d timeout:(double)timeout tag:(int64_t)tag; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS10IPv4Packet") +@interface IPv4Packet : NSObject +@property (nonatomic) uint8_t proto; +@property (nonatomic, readonly, strong) NSData * _Nullable srcIP; +@property (nonatomic, readonly, strong) NSData * _Nonnull _rawData; +@property (nonatomic, readonly, strong) NSData * _Nullable destinationIP; +@property (nonatomic) int32_t headerLength; +@property (nonatomic, readonly) int32_t payloadLength; +- (nonnull instancetype)initWithPacketData:(NSData * _Nonnull)PacketData OBJC_DESIGNATED_INITIALIZER; +- (NSData * _Nonnull)payloadData; +@property (nonatomic, readonly, copy) NSString * _Nonnull debugDescription; +@end + + +@interface NSData (SWIFT_EXTENSION(PacketTunnel_iOS)) +- (NSData * _Nonnull)hmacsha1:(NSData * _Nonnull)keyData; +@end + + +@interface NSData (SWIFT_EXTENSION(PacketTunnel_iOS)) +@property (nonatomic, readonly, strong) NSData * _Null_unspecified md5; +@end + + +@interface NSData (SWIFT_EXTENSION(PacketTunnel_iOS)) +@property (nonatomic, readonly, strong) NSData * _Nonnull md5x; +@property (nonatomic, readonly, strong) NSData * _Nonnull sha1; +@property (nonatomic, readonly, strong) NSData * _Nonnull sha224; +@property (nonatomic, readonly, strong) NSData * _Nonnull sha256; +@property (nonatomic, readonly, strong) NSData * _Nonnull sha384; +@property (nonatomic, readonly, strong) NSData * _Nonnull sha512; +@end + + +@interface NSMutableData (SWIFT_EXTENSION(PacketTunnel_iOS)) +@end + + +@interface NSNumber (SWIFT_EXTENSION(PacketTunnel_iOS)) +@property (nonatomic, readonly) BOOL isBool; +@end + + +@interface NSString (SWIFT_EXTENSION(PacketTunnel_iOS)) +- (uint64_t)fileSize; +- (BOOL)fileExist; +- (BOOL)dirCreate; +- (BOOL)fileDelete; +@end + +@class UDPPacket; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS17OutgoingConnector") +@interface OutgoingConnector : NSObject +@property (nonatomic, copy) NSString * _Nullable identifier; +@property (nonatomic, strong) NSData * _Nullable clientAddress; +@property (nonatomic, strong) NSData * _Nullable dstAddress; +@property (nonatomic, strong) NSDate * _Nonnull activeTime; +@property (nonatomic, readonly) NSTimeInterval idel; +- (BOOL)idleTooLong; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithConnectionIdentifier:(NSString * _Nonnull)connectionIdentifier OBJC_DESIGNATED_INITIALIZER; +- (void)addQueryWithPacket:(UDPPacket * _Null_unspecified)p; +@end + +@class NWPath; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS20PacketTunnelProvider") +@interface PacketTunnelProvider : NEPacketTunnelProvider +@property (nonatomic, copy) NSString * _Nullable dnsServer; +@property (nonatomic, copy) void (^ _Nullable pendingStartCompletion)(NSError * _Nullable); +@property (nonatomic, readonly, strong) dispatch_queue_t _Nonnull tunQueue; +@property (nonatomic, copy) void (^ _Nullable pendingStopCompletion)(void); +@property (nonatomic, strong) NWPath * _Nullable lastPath; +@property (nonatomic) NSInteger startTimes; +@property (nonatomic, strong) NSDate * _Nonnull startDate; +- (NSString * _Nullable)getPasswordWithPersistentReference:(NSData * _Nonnull)persistentReference; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (void)cancel; +- (void)resume; +- (void)startWithInterval:(double)interval; +- (NSString * _Nonnull)ipString:(uint32_t)ip; +- (void)prepareTunnelNetworkSettings:(BOOL)reset; +- (void)vpnStartFinish; +- (void)observeValueForKeyPath:(NSString * _Nullable)keyPath ofObject:(id _Nullable)object change:(NSDictionary * _Nullable)change context:(void * _Null_unspecified)context; +- (void)networkchanged; +- (void)writestart; +- (void)loadConfig; +- (void)startTunnelWithOptions:(NSDictionary * _Nullable)options completionHandler:(void (^ _Nonnull)(NSError * _Nullable))completionHandler; +- (void)startHandlingPackets; +- (void)handlePackets:(NSArray * _Nonnull)packets protocols:(NSArray * _Nonnull)protocols; + +/// Write packets and associated protocols to the UTUN interface. +- (void)processPackets:(NSArray * _Nonnull)packets protocols:(NSArray * _Nonnull)protocols; +- (void)stopABigT; +- (void)stopTunnelWithReason:(NEProviderStopReason)reason completionHandler:(void (^ _Nonnull)(void))completionHandler; +- (void)logStopReason:(NEProviderStopReason)reason; +- (void)sleepWithCompletionHandler:(void (^ _Nonnull)(void))completionHandler; +- (void)wake; + +/// Handle IPC messages from the app. +- (void)handleAppMessage:(NSData * _Nonnull)messageData completionHandler:(void (^ _Nullable)(NSData * _Nullable))completionHandler; +- (void)serverDidQuery:(OutgoingConnector * _Nonnull)targetTunnel data:(NSData * _Nonnull)data close:(BOOL)close; +- (void)serverDidClose:(OutgoingConnector * _Nonnull)targetTunnel; +- (void)writeDatagrams:(NSData * _Nonnull)packets proto:(int32_t)proto; +@end + + +@class NSNotificationCenter; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS12Reachability") +@interface Reachability : NSObject +@property (nonatomic, copy) void (^ _Nullable whenReachable)(Reachability * _Nonnull); +@property (nonatomic, copy) void (^ _Nullable whenUnreachable)(Reachability * _Nonnull); +@property (nonatomic) BOOL reachableOnWWAN; +@property (nonatomic, strong) NSNotificationCenter * _Nonnull notificationCenter; +@property (nonatomic, readonly, copy) NSString * _Nonnull currentReachabilityString; +- (nonnull instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef _Nonnull)reachabilityRef OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithHostname:(NSString * _Nonnull)hostname error:(NSError * _Nullable * _Null_unspecified)error; ++ (Reachability * _Nullable)reachabilityForInternetConnectionAndReturnError:(NSError * _Nullable * _Null_unspecified)error; ++ (Reachability * _Nullable)reachabilityForLocalWiFiAndReturnError:(NSError * _Nullable * _Null_unspecified)error; +- (BOOL)startNotifierAndReturnError:(NSError * _Nullable * _Null_unspecified)error; +- (void)stopNotifier; +- (BOOL)isReachable; +- (BOOL)isReachableViaWWAN; +- (BOOL)isReachableViaWiFi; +- (BOOL)isConnectionOnTrafficOrDemand:(SCNetworkReachabilityFlags)flags; +@property (nonatomic, readonly, copy) NSString * _Nonnull description; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS13TUNConnection") +@interface TUNConnection : NSObject +@property (nonatomic) BOOL forceSend; +@property (nonatomic) BOOL closeSocketAfterRead; +@end + +@class NSLock; +@class SFTCPConnectionManager; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS12SFConnection") +@interface SFConnection : TUNConnection +@property (nonatomic) SFPcb _Null_unspecified pcb; +@property (nonatomic, readonly, strong) NSLock * _Nonnull critLock; +@property (nonatomic, weak) SFTCPConnectionManager * _Nullable manager; +@property (nonatomic, strong) Connector * _Nullable connector; +@property (nonatomic, copy) NSArray * _Nonnull bufArray; +@property (nonatomic, strong) NSMutableData * _Nonnull socks_recv_bufArray; +@property (nonatomic) NSInteger socks_sendout_length; +@property (nonatomic) BOOL connectorReading; +@property (nonatomic) BOOL pendingConnection; +@property (nonatomic) int64_t tag; +@property (nonatomic) NSInteger buf_used; +@property (nonatomic) NSInteger rTag; +@property (nonatomic, copy) NSString * _Nonnull cIDString; +@property (nonatomic) int64_t sendingTag; +@property (nonatomic) BOOL forceClose; +- (NSInteger)sendBufferSize; +- (nonnull instancetype)initWithTcp:(SFPcb _Null_unspecified)tcp host:(uint32_t)host port:(uint16_t)port m:(SFTCPConnectionManager * _Nonnull)m OBJC_DESIGNATED_INITIALIZER; +- (void)cIDFunc; +- (BOOL)shouldRemovDeadClient; +- (void)showLog; +- (dispatch_queue_t _Nonnull)socketQueue; +- (dispatch_queue_t _Nonnull)delegateQueue; +- (BOOL)genPolicy:(NSString * _Nonnull)dest useragent:(NSString * _Nonnull)useragent; +- (void)findIPaddress; +- (void)findIPAddress2; +- (void)findIPRule:(NSString * _Nonnull)ip; +- (void)checkStatus; +- (void)configConnection; +- (void)findProxy; +- (void)configLwip; +- (void)setUpConnector; +- (void)connection:(NSTimeInterval)timeout; +- (void)byebyeRequest; +- (void)connector:(Connector * _Nonnull)connector didReadData:(NSData * _Nonnull)data withTag:(int64_t)tag; +- (void)connectorDidDisconnect:(Connector * _Nonnull)connector withError:(NSError * _Nonnull)withError; +- (void)connector:(Connector * _Nonnull)connector didWriteDataWithTag:(int64_t)_tag; +- (NSTimeInterval)connector:(Connector * _Nonnull)connector shouldTimeoutReadWithTag:(NSInteger)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length; +- (void)connectorDidSetupFailed:(Connector * _Nonnull)connector withError:(NSError * _Nonnull)withError; +- (void)connectorDidBecomeAvailable:(Connector * _Nonnull)connector; +- (void)client_tcp_output; +- (void)client_tcp_received:(NSInteger)len; +- (void)client_socks_recv_initiate; +- (NSInteger)client_socks_recv_send_out; +- (void)client_sent_func; +- (void)client_socks_recv_handler_done:(NSInteger)len; +- (void)client_socks_send_handler_done:(NSInteger)len; +- (void)incomingData:(NSData * _Nonnull)d len:(NSInteger)len; +- (void)client_free_socks; +- (void)client_dealloc; +- (void)client_send_to_socks; +- (void)client_handle_freed_client; +- (NSString * _Nonnull)pcbStatus; +- (void)client_abort_client; +- (void)client_free_client; +- (void)close_lwip_pcb:(BOOL)abort; +- (void)client_murder; +@end + +@class GCDAsyncUdpSocket; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS14SFDNSForwarder") +@interface SFDNSForwarder : OutgoingConnector +@property (nonatomic, copy) NSArray * _Nonnull domains; +@property (nonatomic, strong) DNSPacket * _Nullable packet; +@property (nonatomic, strong) GCDAsyncUdpSocket * _Nullable socket; +@property (nonatomic, copy) NSArray * _Nonnull queries; +@property (nonatomic) uint16_t queryIDCounter; +@property (nonatomic, copy) NSString * _Nonnull targetHost; +@property (nonatomic, readonly) uint16_t targetPort; +@property (nonatomic) BOOL connected; +@property (nonatomic, strong) NSDate * _Nonnull startTime; +@property (nonatomic, strong) NSMutableData * _Nullable cacheData; +- (nonnull instancetype)initWithServer:(NSString * _Nonnull)server OBJC_DESIGNATED_INITIALIZER; +- (BOOL)config; +- (NSData * _Nonnull)buildHead; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (void)start; +- (void)addQueryWithPacket:(UDPPacket * _Null_unspecified)udp; +- (void)processQuery; +- (void)udpSocket:(GCDAsyncUdpSocket * _Nonnull)sock didReceiveData:(NSData * _Nonnull)tempdata fromAddress:(NSData * _Nonnull)address withFilterContext:(id _Nullable)filterContext; +- (void)writeDNSPacketData:(NSData * _Nonnull)data cache:(BOOL)cache; +- (void)udpSocket:(GCDAsyncUdpSocket * _Nonnull)sock didNotConnect:(NSError * _Nonnull)error; +- (void)udpSocket:(GCDAsyncUdpSocket * _Nonnull)sock didSendDataWithTag:(NSInteger)tag; +- (void)udpSocketDidClose:(GCDAsyncUdpSocket * _Nonnull)sock withError:(NSError * _Nonnull)error; +- (void)udpSocket:(GCDAsyncUdpSocket * _Nonnull)sock didNotSendDataWithTag:(NSInteger)tag dueToError:(NSError * _Nonnull)error; +- (void)shutdownSocket; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS13SFHTTPRequest") +@interface SFHTTPRequest : SFConnection +@property (nonatomic, strong) NSMutableData * _Nonnull headerData; +- (nonnull instancetype)initWithTcp:(SFPcb _Null_unspecified)tcp host:(uint32_t)host port:(uint16_t)port m:(SFTCPConnectionManager * _Nonnull)m OBJC_DESIGNATED_INITIALIZER; +- (void)processData:(NSString * _Nonnull)reason; +- (BOOL)httpArgu; +- (void)configConnector; +- (void)setUpConnector; +- (void)connector:(Connector * _Nonnull)connector didWriteDataWithTag:(int64_t)_tag; +- (void)sendCONNECTResponse; +- (BOOL)sendFakeCONNECTResponse; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS16SFHTTPConnection") +@interface SFHTTPConnection : SFHTTPRequest +@property (nonatomic) NSInteger requestIndex; +@property (nonatomic, strong) NSMutableData * _Nonnull recvHeaderData; +@property (nonatomic) NSUInteger currentBodyLength; +@property (nonatomic) NSUInteger totalRecvLength; +@property (nonatomic) NSUInteger currentBobyReadLength; +@property (nonatomic, readonly, copy) NSString * _Nonnull statusString; +- (void)configLwip; +- (void)incomingData:(NSData * _Nonnull)d len:(NSInteger)len; +- (void)connect; +- (void)processData:(NSString * _Nonnull)reason; +- (void)client_send_to_socks; +- (void)connector:(Connector * _Nonnull)connector didReadData:(NSData * _Nonnull)data withTag:(int64_t)tag; +- (void)connector:(Connector * _Nonnull)connector didWriteDataWithTag:(int64_t)_tag; +- (void)client_socks_recv_initiate; +- (void)showLog; +- (void)checkStatus; +- (nonnull instancetype)initWithTcp:(SFPcb _Null_unspecified)tcp host:(uint32_t)host port:(uint16_t)port m:(SFTCPConnectionManager * _Nonnull)m OBJC_DESIGNATED_INITIALIZER; +@end + + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS17SFHTTPSConnection") +@interface SFHTTPSConnection : SFHTTPRequest +- (void)configLwip; +- (void)incomingData:(NSData * _Nonnull)d len:(NSInteger)len; +- (void)connect; +- (void)processData:(NSString * _Nonnull)reason; +- (void)client_send_to_socks; +- (void)connector:(Connector * _Nonnull)connector didReadData:(NSData * _Nonnull)data withTag:(int64_t)tag; +- (nonnull instancetype)initWithTcp:(SFPcb _Null_unspecified)tcp host:(uint32_t)host port:(uint16_t)port m:(SFTCPConnectionManager * _Nonnull)m OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS25SFNetworkInterfaceManager") +@interface SFNetworkInterfaceManager : NSObject +@property (nonatomic, copy) NSString * _Nonnull defaultIPAddress; +@property (nonatomic, copy) NSString * _Nonnull WiFiIPAddress; +@property (nonatomic, copy) NSString * _Nonnull WWANIPAddress; ++ (SFNetworkInterfaceManager * _Nonnull)instances; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (void)updateIPAddress; +- (void)showRouter; +- (NSInteger)interfaceMTUWithName:(NSString * _Nonnull)name; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS15SFTCPConnection") +@interface SFTCPConnection : SFConnection +@property (nonatomic, strong) NSMutableData * _Nonnull headerData; +- (nonnull instancetype)initWithTcp:(SFPcb _Null_unspecified)tcp host:(uint32_t)host port:(uint16_t)port m:(SFTCPConnectionManager * _Nonnull)m OBJC_DESIGNATED_INITIALIZER; +- (void)configLwip; +- (void)configConnection; +- (void)setUpConnector; +- (void)incomingData:(NSData * _Nonnull)d len:(NSInteger)len; +- (void)processData:(NSString * _Nonnull)reason; +- (void)client_send_to_socks; +- (void)connector:(Connector * _Nonnull)connector didWriteDataWithTag:(int64_t)_tag; +- (void)connector:(Connector * _Nonnull)connector didReadData:(NSData * _Nonnull)data withTag:(int64_t)tag; +@end + +@class SFUDPConnection; + +SWIFT_CLASS("_TtC16PacketTunnel_iOS22SFTCPConnectionManager") +@interface SFTCPConnectionManager : NSObject ++ (SFTCPConnectionManager * _Nonnull)manager; ++ (SFTCPConnectionManager * _Nonnull)shared; +@property (nonatomic, strong) dispatch_queue_t _Nonnull dispatchQueue; +@property (nonatomic, strong) dispatch_queue_t _Nonnull socketQueue; +@property (nonatomic) dispatch_source_memorypressure_flags_t memoryWarninglevel; +@property (nonatomic, strong) NSDate * _Nonnull lastMemeoryWarningDate; +@property (nonatomic, weak) PacketTunnelProvider * _Nullable provider; +@property (nonatomic, copy) NSArray * _Nonnull udp_connections; +@property (nonatomic) BOOL tcpOperating; +@property (nonatomic) BOOL lwip_init_finished; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (void)start; +- (void)checkConnectionStatus; +- (void)closeAllConnection; +- (void)setMTU:(NSInteger)mtu; +- (void)saveConnectionInfo:(SFConnection * _Nonnull)ref; +- (void)removeConnectionRef:(SFConnection * _Nonnull)ref; +- (void)writeDatagrams:(NSData * _Nonnull)data; +@end + + +@interface SFTCPConnectionManager (SWIFT_EXTENSION(PacketTunnel_iOS)) +- (void)startProxyServer; +@end + + +@interface SFTCPConnectionManager (SWIFT_EXTENSION(PacketTunnel_iOS)) +- (void)configUDP; +- (void)addUDPConnection:(SFUDPConnection * _Nonnull)c; +- (void)deleteUDP:(SFUDPConnection * _Nonnull)c; +- (void)incomingUDP:(SFUPcb _Null_unspecified)udp; +@end + +@class NSTimer; + +@interface SFTCPConnectionManager (SWIFT_EXTENSION(PacketTunnel_iOS)) +- (void)installMemoryWarning; +- (void)recvMemoryWarning:(dispatch_source_memorypressure_flags_t)level; +- (void)cleanMemory; +- (void)incomingTCP:(SFPcb _Null_unspecified)tcp; +- (void)tcp_timer_handler:(NSTimer * _Nonnull)t; +- (void)cleanConnection; +- (void)cancel; +- (void)resume; +- (void)startWithInterval:(double)interval; +- (void)device_read_handler_sendPackets3:(void const * _Null_unspecified)unused packets:(NSArray * _Nonnull)packets complete:(void (^ _Nonnull)(NSError * _Nullable))complete; +- (void)device_read_handler_sendPackets:(void const * _Null_unspecified)unused packets:(NSArray * _Nonnull)packets; +- (void)clearRule; +- (void)device_read_handler_send:(void const * _Null_unspecified)unused data:(NSData * _Nonnull)data len:(NSInteger)len sport:(uint16_t)sport; +- (NSData * _Nonnull)recentRequestData; +- (NSData * _Nonnull)ruleResultData; +- (void)test; +- (BOOL)shouldReadPacket; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS15SFUDPConnection") +@interface SFUDPConnection : TUNConnection +@property (nonatomic) SFUPcb _Null_unspecified pcb; +- (nonnull instancetype)initWithP:(SFUPcb _Null_unspecified)p host:(uint32_t)host port:(uint16_t)port OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS14SFUDPConnector") +@interface SFUDPConnector : NSObject +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS20SFUDPDirectConnector") +@interface SFUDPDirectConnector : SFUDPConnector +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS19SFUDPProxyConnector") +@interface SFUDPProxyConnector : SFUDPConnector +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS12SFVPNSession") +@interface SFVPNSession : NSObject ++ (SFVPNSession * _Nonnull)session; +@property (nonatomic, strong) NSDate * _Nonnull startTime; +@property (nonatomic, strong) NSDate * _Nonnull endTime; +- (nonnull instancetype)initWithPath:(NSString * _Nonnull)path OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (NSString * _Nonnull)idenString; +@end + + +SWIFT_PROTOCOL("_TtP16PacketTunnel_iOS14SocketDelegate_") +@protocol SocketDelegate +- (void)connector:(Connector * _Nonnull)connector didReadData:(NSData * _Nonnull)data withTag:(int64_t)tag; +- (void)connectorDidDisconnect:(Connector * _Nonnull)connector withError:(NSError * _Nonnull)withError; +- (void)connector:(Connector * _Nonnull)connector didWriteDataWithTag:(int64_t)tag; +- (void)connectorDidSetupFailed:(Connector * _Nonnull)connector withError:(NSError * _Nonnull)withError; +- (void)connectorDidBecomeAvailable:(Connector * _Nonnull)connector; +- (NSTimeInterval)connector:(Connector * _Nonnull)connector shouldTimeoutReadWithTag:(NSInteger)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS15Socks5Connector") +@interface Socks5Connector : ProxyConnector +@property (nonatomic, copy) NSString * _Nullable host; +@property (nonatomic) uint16_t port; +@property (nonatomic, strong) NSMutableData * _Nullable recvBuffer; +- (void)sendAuth; +- (void)sendUserAndPassword; +- (void)sendBind; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didConnectToHost:(NSString * _Null_unspecified)host port:(uint16_t)port; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didReadData:(NSData * _Nonnull)data withTag:(NSInteger)tag; +- (void)sock5connected; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didWriteDataWithTag:(NSInteger)tag; +- (void)socketDidCloseReadStream:(GCDAsyncSocket * _Null_unspecified)sock; +- (void)start; +- (void)writeData:(NSData * _Nonnull)d timemout:(double)timemout tag:(long)tag; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS9TCPPacket") +@interface TCPPacket : NSObject +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS14TCPSSConnector") +@interface TCPSSConnector : ProxyConnector +@property (nonatomic) BOOL ota; +@property (nonatomic) BOOL headSent; +- (BOOL)config; +- (NSData * _Nonnull)buildHead; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didConnectToHost:(NSString * _Null_unspecified)host port:(uint16_t)port; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didReadData:(NSData * _Nonnull)data withTag:(NSInteger)tag; +- (void)socket:(GCDAsyncSocket * _Nonnull)sock didWriteDataWithTag:(NSInteger)tag; +- (void)beginRead; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(NSInteger)tag; +- (void)socketDidCloseReadStream:(GCDAsyncSocket * _Null_unspecified)sock; +- (void)start; +- (void)writeData:(NSData * _Nonnull)d timeout:(double)timeout tag:(int64_t)tag; +@end + + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS9UDPPacket") +@interface UDPPacket : NSObject +@property (nonatomic) uint16_t sourcePort; +@property (nonatomic) uint16_t destinationPort; +@property (nonatomic, strong) NSData * _Nullable _rawData; +- (nonnull instancetype)initWithPacketData:(NSData * _Nonnull)PacketData OBJC_DESIGNATED_INITIALIZER; +- (NSData * _Nonnull)payloadData; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS10UDPRelayer") +@interface UDPRelayer : OutgoingConnector +@property (nonatomic, copy) NSArray * _Nonnull domains; +@property (nonatomic, strong) DNSPacket * _Nullable packet; +@property (nonatomic, strong) GCDAsyncUdpSocket * _Nullable socket; +@property (nonatomic, copy) NSArray * _Nonnull queries; +@property (nonatomic) uint16_t queryIDCounter; +@property (nonatomic, copy) NSString * _Nonnull targetHost; +@property (nonatomic) uint16_t targetPort; +@property (nonatomic) BOOL connected; +@property (nonatomic, strong) NSMutableData * _Nullable cacheData; +- (BOOL)setupSS; +- (BOOL)config; +- (NSData * _Nonnull)buildHead; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (void)start; +- (void)addQueryWithPacket:(UDPPacket * _Null_unspecified)udp; +- (void)processQuery; +- (void)udpSocket:(GCDAsyncUdpSocket * _Null_unspecified)sock didReceiveData:(NSData * _Null_unspecified)tempdata fromAddress:(NSData * _Null_unspecified)address withFilterContext:(id _Null_unspecified)filterContext; +- (void)writeDNSPacketData:(NSData * _Nonnull)data; +- (void)udpSocket:(GCDAsyncUdpSocket * _Nonnull)sock didNotConnect:(NSError * _Nonnull)error; +- (void)udpSocket:(GCDAsyncUdpSocket * _Nonnull)sock didSendDataWithTag:(NSInteger)tag; +- (void)udpSocketDidClose:(GCDAsyncUdpSocket * _Nonnull)sock withError:(NSError * _Nonnull)error; +- (void)udpSocket:(GCDAsyncUdpSocket * _Null_unspecified)sock didNotSendDataWithTag:(NSInteger)tag dueToError:(NSError * _Null_unspecified)error; +- (void)shutdownSocket; +@end + + +SWIFT_CLASS("_TtC16PacketTunnel_iOS14VmessConnector") +@interface VmessConnector : ProxyConnector +- (BOOL)config; +- (void)writeData:(NSData * _Nonnull)d timeout:(double)timeout tag:(int64_t)tag; +- (void)socket:(GCDAsyncSocket * _Null_unspecified)sock didReadData:(NSData * _Null_unspecified)data withTag:(NSInteger)tag; +@end + +#pragma clang diagnostic pop diff --git a/PacketTunnel/iOS/PacketTunnel-iOS.xcconfig b/PacketTunnel/iOS/PacketTunnel-iOS.xcconfig new file mode 100644 index 0000000..69b3799 --- /dev/null +++ b/PacketTunnel/iOS/PacketTunnel-iOS.xcconfig @@ -0,0 +1,22 @@ +// +// PacketTunnel-iOS.xcconfig +// Surf +// +// Created by abigt on 16/1/12. +// Copyright © 2016年 abigt. All rights reserved. +// + +HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/share/include" "$(SRCROOT)/Shared/header" "$(SRCROOT)/MMDB" "$(SRCROOT)/shared/lwip/badvpn" +USER_HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/Shared/header" "$(SRCROOT)/Shared/lwip/src/include/"** +OTHER_CFLAGS = $(inherited) -isystem -I "$(PROJECT_DIR)/iosLib" +OTHER_LDFLAGS = $(inherited) -framework Crashlytics -framework Fabric//-lsodium //-mbedcrypto//lcrypto // - //mbedcrypto + +SSL_LIB_DEFINE = TCP_MSS=1460//USE_CRYPTO_MBEDTLS=1 + + +//OTHER_LDFLAGS = $(inherited) -framework Crypto -framework Sodium -framework IDZSwiftCommonCrypto -framework CocoaAsyncSocket -framework SwiftyJSON -framework MMDB -weak_framework kcp -framework XSocket -framework ObjectMapper -framework Xcon -framework CommonCrypto -framework AxLogger +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/iosLib" "$(PROJECT_DIR)/Carthage/Build/iOS/" +LIBRARY_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/iosLib" "$(PROJECT_DIR)/Carthage/Build/iOS/" + +//USE_CRYPTO_OPENSSL USE_CRYPTO_MBEDTLS +//USE_CRYPTO_MBEDTLS=1 diff --git a/PacketTunnel/iOS/PacketTunnel.entitlements b/PacketTunnel/iOS/PacketTunnel.entitlements new file mode 100644 index 0000000..96286b5 --- /dev/null +++ b/PacketTunnel/iOS/PacketTunnel.entitlements @@ -0,0 +1,20 @@ + + + + + com.apple.developer.networking.networkextension + + app-proxy-provider + content-filter-provider + packet-tunnel-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + com.apple.security.application-groups + + group.com.abigt.Surf + + + diff --git a/PacketTunnel/socks5.js b/PacketTunnel/socks5.js new file mode 100644 index 0000000..3c60aae --- /dev/null +++ b/PacketTunnel/socks5.js @@ -0,0 +1,5 @@ +var tunnel = "SOCKS5 240.7.1.10:10082; ";//SOCKS 127.0.0.1:1080; DIRECT; +var direct = "DIRECT"; +function FindProxyForURL(url, host) { + return tunnel +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6d35ba5 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Surf project memo # + +这是一个利用Network extension framework 的项目 + +### 使用技术 ### + +* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo) + +### target 包含说明 ### +* ... +* ... +* ... +* Deployment instructions + +### Contribution guidelines ### + +* + + +### Who do I talk to? ### + +*none +### todo list #### +.... diff --git a/Shared/header/SFUtil.h b/Shared/header/SFUtil.h new file mode 100644 index 0000000..1722907 --- /dev/null +++ b/Shared/header/SFUtil.h @@ -0,0 +1,12 @@ +// +// SFUtil.h +// Surf +// +// Created by yarshure on 15/12/25. +// Copyright © 2015年 yarshure. All rights reserved. +// + +#ifndef SFUtil_h +#define SFUtil_h + +#endif /* SFUtil_h */ diff --git a/Shared/lwip/CHANGELOG b/Shared/lwip/CHANGELOG new file mode 100644 index 0000000..685b568 --- /dev/null +++ b/Shared/lwip/CHANGELOG @@ -0,0 +1,3396 @@ +HISTORY + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ New features: + + 2012-03-25: Simon Goldschmidt (idea by Mason) + * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h + which are a simple wrapper to the correct lwIP include files. + + 2012-01-16: Simon Goldschmidt + * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP + + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) + + 2011-09-27: Simon Goldschmidt + * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) + (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) + + 2011-09-21: Simon Goldschmidt + * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on + send (TCP only, bug #33820) + + 2011-09-21: Simon Goldschmidt + * init.c: Converted runtime-sanity-checks into compile-time checks that can + be disabled (since runtime checks can often not be seen on embedded targets) + + 2011-09-11: Simon Goldschmidt + * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file + to get a clear separation of which functions an application or port may use + (task #11281) + + 2011-09-11: Simon Goldschmidt + * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize + initial local TCP/UDP ports (so that different port ranges are used after + a reboot; bug #33818; this one added tcp_init/udp_init functions again) + + 2011-09-03: Simon Goldschmidt + * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) + + 2011-08-24: Simon Goldschmidt + * opt.h, netif.h/.c: added netif remove callback (bug #32397) + + 2011-07-26: Simon Goldschmidt + * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter + function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + + 2011-07-21: Simon Goldschmidt + * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes + ioctl/FIONREAD return the size of the next pending datagram. + + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) + * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that + pcb->state != LISTEN + + 2011-05-25: Simon Goldschmidt + * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, + combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 + and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP + code so that the code is more readable. + + 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) + * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to + Ivan! (this is work in progress: we're just post release anyway :-) + + 2011-05-14: Simon Goldschmidt (patch by Stphane Lesage) + * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static + memory message + + + ++ Bugfixes: + + 2013-01-15: Simon Goldschmidt + * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order + + 2013-01-15: Simon Goldschmidt + * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning + + 2013-01-14: Simon Goldschmidt + * dns.c: fixed bug #37705 Possible memory corruption in DNS query + + 2013-01-11: Simon Goldschmidt + * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it + + 2012-09-26: Simon Goldschmidt + * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7843 Fix corner case with dhcp timeouts + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-08-13: Simon Goldschmidt + * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start + dereferences NULL + + 2012-08-13: Simon Goldschmidt + * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps + configured but no interfaces available + + 2012-08-13: Simon Goldschmidt + * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time + + 2012-05-11: Simon Goldschmidt (patch by Marty) + * memp.c: fixed bug #36412: memp.c does not compile when + MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 + + 2012-05-08: Simon Goldschmidt + * tcp_out.c: fixed bug #36380: unsent_oversize mismatch in 1.4.1RC1 (this was + a debug-check issue only) + + 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) + * ppp.c: fixed bug #36283 (PPP struct used on header size computation and + not packed) + + 2012-05-03: Simon Goldschmidt (patch by David Empson) + * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with + zero length) + + 2012-03-27: Simon Goldschmidt + * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c + + 2012-03-27: Simon Goldschmidt (patch by Mason) + * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the + send MSS + + 2012-03-25: Simon Goldschmidt + * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed + for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 + + 2012-03-25: Simon Goldschmidt + * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space + pollution in api_msg.c and netifapi.c + + 2012-03-22: Simon Goldschmidt + * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward + + 2012-03-20: Simon Goldschmidt (patch by Mason) + * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list + + 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) + * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, + possible bug on little endian system + + 2012-02-23: Simon Goldschmidt + * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt + * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() + (bug #35541: PPP Memory Leak) + + 2012-02-16: Simon Goldschmidt + * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt (patch by Stphane Lesage) + * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed + + 2012-02-15: Simon Goldschmidt + * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with + MEMP_MEM_MALLOC==1 + + 2012-02-12: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on + MSS > pcb->snd_wnd (by not creating segments bigger than half the window) + + 2012-02-11: Simon Goldschmidt + * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait + queue while closing + + 2012-01-22: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) + + 2012-01-21: Simon Goldschmidt + * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb + + 2012-01-20: Simon Goldschmidt + * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths + + 2012-01-20: Simon Goldschmidt + * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy + + 2011-11-25: Simon Goldschmidt + * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt + tcp_active_pcbs in some cases + + 2011-11-23: Simon Goldschmidt + * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with + '#ifndef sys_msleep' + + 2011-11-22: Simon Goldschmidt + * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when + netif is brought down + + 2011-10-28: Simon Goldschmidt + * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks + + 2011-10-23: Simon Goldschmidt + * mem.c: fixed bug #34429: possible memory corruption with + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 + + 2011-10-18: Simon Goldschmidt + * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard + error value + + 2011-10-18: Simon Goldschmidt + * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small + windows (bug #34176 select after non-blocking send times out) + + 2011-10-18: Simon Goldschmidt + * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't + consider netif->mtu, causes slow network + + 2011-10-18: Simon Goldschmidt + * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code + + 2011-10-18: Simon Goldschmidt + * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS + + 2011-10-17: Simon Goldschmidt + * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api + + 2011-10-13: Simon Goldschmidt + * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no + zero window is received) by starting the persist timer when a zero window is + received, not when we have more data queued for sending than fits into the + window + + 2011-10-13: Simon Goldschmidt + * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex + + 2011-10-13: Simon Goldschmidt + * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is + used and not all protocols are enabled + + 2011-10-12: Simon Goldschmidt + * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 + + 2011-10-09: Simon Goldschmidt + * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect + byte value when pcb->unacked != NULL + + 2011-10-09: Simon Goldschmidt + * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong + + 2011-09-27: Simon Goldschmidt + * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... + + 2011-09-27: Simon Goldschmidt + * tcp_in.c: fixed bug #28288: Data after FIN in oos queue + + 2011-09-27: Simon Goldschmidt + * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf + + 2011-09-24: Simon Goldschmidt + * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 + + 2011-09-23: Simon Goldschmidt + * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for + the last packet including FIN can lose data + + 2011-09-22: Simon Goldschmidt + * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into + account + + 2011-09-21: Simon Goldschmidt + * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks + in init.c + + 2011-09-20: Simon Goldschmidt + * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) + + 2011-09-11: Simon Goldschmidt + * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs + (bug #34019) + + 2011-09-09: Simon Goldschmidt + * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if + udp port matches + + 2011-09-03: Simon Goldschmidt + * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet + is aggregated and sent to application + + 2011-09-01: Simon Goldschmidt + * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared + to other options + + 2011-09-01: Simon Goldschmidt + * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno + + 2011-08-24: Simon Goldschmidt + * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard + + 2011-08-24: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling + accept() on UDP connections + + 2011-08-24: Simon Goldschmidt + * sockets.h: fixed bug #34057 socklen_t should be a typedef + + 2011-08-24: Simon Goldschmidt + * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) + + 2011-08-24: Simon Goldschmidt + * dhcp.c: fixed bug #34122 dhcp: hostname can overflow + + 2011-08-24: Simon Goldschmidt + * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr + + 2011-08-22: Simon Goldschmidt + * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This + merely prevents nagle from not transmitting fast after closing.) + + 2011-07-22: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns + always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now + lwip_send() sends as much as possible for non-blocking sockets + + 2011-07-22: Simon Goldschmidt + * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented + for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level. + + 2011-07-21: Simon Goldschmidt + * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by + sending an ARP request when an ARP entry is used in the last minute before + it would time out. + + 2011-07-04: Simon Goldschmidt + * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. + + 2011-06-26: Simon Goldschmidt + * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by + updating its documentation only. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an + unaligned pointer. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" + + + +(STABLE-1.4.0) + + ++ New features: + + 2011-03-27: Simon Goldschmidt + * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and + calculate it in tcp_zero_window_probe (the only place where it was used). + + 2010-11-21: Simon Goldschmidt + * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif + (fixes bug #31525). + + 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) + * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for + IP_MULTICAST_LOOP at socket- and raw-API level. + + 2010-06-16: Simon Goldschmidt + * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow + link-layer-addressed UDP traffic to be received while a netif is down (just + like DHCP during configuration) + + 2010-05-22: Simon Goldschmidt + * many many files: bug #27352: removed packing from ip_addr_t, the packed + version is now only used in protocol headers. Added global storage for + current src/dest IP address while in input functions. + + 2010-05-16: Simon Goldschmidt + * def.h: task #10391: Add preprocessor-macros for compile-time htonl + calculation (and use them throughout the stack where applicable) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool + instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own + MEMP pool instead of the heap + + 2010-05-13: Simon Goldschmidt + * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added + new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast + packets to more than one pcb. + + 2010-05-02: Simon Goldschmidt + * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending + UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-04-30: Simon Goldschmidt + * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that + take a precalculated checksum, added pbuf_fill_chksum() to copy data + into a pbuf and at the same time calculating the checksum for that data + + 2010-04-29: Simon Goldschmidt + * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying + 2-byte-aligned IP addresses and MAC addresses + + 2010-04-28: Patch by Bill Auerbach + * ip.c: Inline generating IP checksum to save a function call + + 2010-04-14: Simon Goldschmidt + * tcpip.h/.c, timers.c: Added an overridable define to get informed when the + tcpip_thread processes messages or timeouts to implement a watchdog. + + 2010-03-28: Simon Goldschmidt + * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing + fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-03-27: Simon Goldschmidt + * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ + etharp_query to prevent unnecessary function calls (inspired by + patch #7135). + + 2010-03-20: Simon Goldschmidt + * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code + since the linker cannot do this automatically to save space. + + 2010-03-20: Simon Goldschmidt + * opt.h, etharp.c/.h: Added support for static ARP table entries + + 2010-03-14: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum + when creating TCP segments, not when (re-)transmitting them. + + 2010-03-07: Simon Goldschmidt + * sockets.c: bug #28775 (select/event_callback: only check select_cb_list + on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. + This should speed up receiving data on sockets as the select code in + event_callback is only executed when select is waiting. + + 2010-03-06: Simon Goldschmidt + * tcp_out.c: task #7013 (Create option to have all packets delivered to + netif->output in one piece): Always copy to try to create single pbufs + in tcp_write. + + 2010-03-06: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv + by not allocating a netbuf): added function netconn_recv_tcp_pbuf() + for tcp netconns to receive pbufs, not netbufs; use that function + for tcp sockets. + + 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt + * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: + Work on tcp_enqueue: Don't waste memory when chaining segments, + added option TCP_OVERSIZE to prevent creating many small pbufs when + calling tcp_write with many small blocks of data. Instead, pbufs are + allocated larger than needed and the space is used for later calls to + tcp_write. + + 2010-02-21: Simon Goldschmidt + * stats.c/.h: Added const char* name to mem- and memp-stats for easier + debugging. + + 2010-02-21: Simon Goldschmidt + * tcp.h (and usages), added tcp_impl.h: Splitted API and internal + implementation of tcp to make API usage cleare to application programmers + + 2010-02-14: Simon Goldschmidt/Stephane Lesage + * ip_addr.h: Improved some defines working on ip addresses, added faster + macro to copy addresses that cannot be NULL + + 2010-02-13: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- + blocking send operation) + + 2010-02-12: Simon Goldschmidt + * sockets.c/.h: Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + 2010-02-12: Simon Goldschmidt + * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated + memory): added autoip_set_struct() and dhcp_set_struct() to let autoip + and dhcp work with user-allocated structs instead of callin mem_malloc + + 2010-02-12: Simon Goldschmidt/Jeff Barber + * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has + SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT + + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + + 2010-02-09: Simon Goldschmidt (Simon Kallweit) + * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 + (Restart system timeout handling) + + 2010-02-09: Simon Goldschmidt + * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into + netif.c) - loopif does not have to be created by the port any more, + just define LWIP_HAVE_LOOPIF to 1. + + 2010-02-08: Simon Goldschmidt + * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa + inet_ntoa_r/ipaddr_ntoa_r + + 2010-02-08: Simon Goldschmidt + * netif.h: Added netif_s/get_igmp_mac_filter() macros + + 2010-02-05: Simon Goldschmidt + * netif.h: Added function-like macros to get/set the hostname on a netif + + 2010-02-04: Simon Goldschmidt + * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to + make changing the actual implementation behind the typedef easier. + + 2010-02-01: Simon Goldschmidt + * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool + for allocating memory when getaddrinfo() is called. + + 2010-01-31: Simon Goldschmidt + * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse + them once instead of parsing for every option. This also removes + the need for mem_malloc from dhcp_recv and makes it possible to + correctly retrieve the BOOTP file. + + 2010-01-30: simon Goldschmidt + * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect + the sockets array. + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, api_msg.c, sockets.c: Added except set support in select + (patch #6860) + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: + Add non-blocking support for connect (partly from patch #6860), + plus many cleanups in socket & netconn API. + + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + + 2010-01-26: Simon Goldschmidt + * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. + + 2010-01-14: Simon Goldschmidt + * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback + by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() + + 2010-01-13: Simon Goldschmidt + * mem.c: The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + (patch #6966 and bug #26133) + + 2010-01-10: Simon Goldschmidt (Bill Auerbach) + * opt.h, memp.c: patch #6822 (Add option to place memory pools in + separate arrays) + + 2010-01-10: Simon Goldschmidt + * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define + LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) + + 2009-12-31: Simon Goldschmidt + * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h + added timers.c/.h: Separated timer implementation from semaphore/mbox + implementation, moved timer implementation to timers.c/.h, timers are + now only called from tcpip_thread or by explicitly checking them. + (TASK#7235) + + 2009-12-27: Simon Goldschmidt + * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option + LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) + + + ++ Bugfixes: + + 2011-04-20: Simon Goldschmidt + * sys_arch.txt: sys_arch_timeouts() is not needed any more. + + 2011-04-13: Simon Goldschmidt + * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by + using ports in the IANA private/dynamic range (49152 through 65535). + + 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: + * etharp.h/.c: Fixed broken VLAN support. + + 2011-03-27: Simon Goldschmidt + * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp + pcbs) by checking if the pcb was bound (local_port != 0). + + 2011-03-27: Simon Goldschmidt + * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) + + 2011-03-27: Simon Goldschmidt + * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and + raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. + + 2011-03-27: Simon Goldschmidt + * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route + is present never times out) by starting retransmission timer before checking + route. + + 2011-03-22: Simon Goldschmidt + * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only + calling sio_read_abort() if the file descriptor is valid. + + 2011-03-14: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect + more than once can render a socket useless) since it mainly involves changing + "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. + + 2011-03-13: Simon Goldschmidt + * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing + err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: + use EALRADY instead of -1 + + 2011-03-13: Simon Goldschmidt + * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the + connection has been aborted by err_tcp (since this is not a normal closing + procedure). + + 2011-03-13: Simon Goldschmidt + * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind + with pcb->state != CLOSED + + 2011-02-17: Simon Goldschmidt + * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in + documentation + + 2011-02-17: Simon Goldschmidt + * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. + + 2011-01-24: Simon Goldschmidt + * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems + + 2010-12-02: Simon Goldschmidt + * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. + + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt + * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS + after a successful nonblocking connection. + + 2010-11-22: Simon Goldschmidt + * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr + must be sent link-local + + 2010-11-22: Simon Goldschmidt + * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for + LWIP_TIMERS==0 + + 2010-11-20: Simon Goldschmidt + * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number + + 2010-11-20: Simon Goldschmidt + * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to + resemble other stacks. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else + no-copy TCP writes will never succeed. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does + not match documentation: return ERR_ARG instead of ERR_VAL if not + initialized or wrong argument. + + 2010-10-20: Simon Goldschmidt + * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 + + 2010-10-05: Simon Goldschmidt + * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when + replugging the network cable after an AutoIP address was assigned. + + 2010-08-10: Simon Goldschmidt + * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs + + 2010-08-03: Simon Goldschmidt + * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) + + 2010-08-01: Simon Goldschmidt (patch by Greg Renda) + * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big + endian architectures) + + 2010-07-28: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP + disabled. + + 2010-07-27: Simon Goldschmidt + * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no + harm but never did anything + + 2010-07-21: Simon Goldschmidt + * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not + add IP options) + + 2010-07-16: Kieran Mansley + * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator + + 2010-07-10: Simon Goldschmidt + * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options + + 2010-06-30: Simon Goldschmidt + * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in + netconn_delete) + + 2010-06-28: Kieran Mansley + * timers.c remove unportable printing of C function pointers + + 2010-06-24: Simon Goldschmidt + * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag + NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading + + 2010-06-24: Simon Goldschmidt + * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly + implemented shutdown at socket level. + + 2010-06-21: Simon Goldschmidt + * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has + problems with zero-copy DMA MACs) by adding custom pbufs and implementing + custom pbufs that reference other (original) pbufs. Additionally set + IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. + + 2010-06-15: Simon Goldschmidt + * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses + + 2010-06-14: Simon Goldschmidt + * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses + + 2010-06-12: Simon Goldschmidt + * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop + state + + 2010-05-17: Simon Goldschmidt + * netdb.c: Correctly NULL-terminate h_addr_list + + 2010-05-16: Simon Goldschmidt + * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent + "symbol already defined" i.e. when linking to winsock + + 2010-05-05: Simon Goldschmidt + * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may + overflow) + + 2010-04-21: Simon Goldschmidt + * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening + connection) + + 2010-03-28: Luca Ceresoli + * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers + + 2010-03-27: Luca Ceresoli + * mib2.c: patch #7130: remove meaningless const qualifiers + + 2010-03-26: Simon Goldschmidt + * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too + + 2010-03-26: Simon Goldschmidt + * various files: Fixed compiling with different options disabled (TCP/UDP), + triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled + + 2010-03-25: Simon Goldschmidt + * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly + + 2010-03-25: Simon Goldschmidt + * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side + overrunning our rcv_wnd in ooseq case. + + 2010-03-22: Simon Goldschmidt + * tcp.c: tcp_listen() did not copy the pcb's prio. + + 2010-03-19: Simon Goldschmidt + * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set + + 2010-03-14: Simon Goldschmidt + * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports + where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h + and basing PBUF_LINK_HLEN on it. + + 2010-03-08: Simon Goldschmidt + * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections + when assiging routable address): when checking incoming packets and + aborting existing connection on address change, filter out link-local + addresses. + + 2010-03-06: Simon Goldschmidt + * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING + + 2010-03-06: Simon Goldschmidt + * ipv4/ip.c: Don't try to forward link-local addresses + + 2010-03-06: Simon Goldschmidt + * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- + addresses to gw + + 2010-03-05: Simon Goldschmidt + * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type + and state. + + 2010-03-05: Simon Goldschmidt + * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split + into multiple calls to tcp_write. + + 2010-02-21: Simon Goldschmidt + * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep + the implementation of DNS_USES_STATIC_BUF==1) + + 2010-02-20: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement + close() vs. shutdown(). Now the application does not get any more + recv callbacks after calling tcp_close(). Added tcp_shutdown(). + + 2010-02-19: Simon Goldschmidt + * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent + confusion with realloc() + + 2010-02-15: Simon Goldschmidt/Stephane Lesage + * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK + (fixes bug #28899) + + 2010-02-14: Simon Goldschmidt + * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with + LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and + admin-status of a netif are up + + 2010-02-14: Simon Goldschmidt + * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet + reception and is not really necessary + + 2010-02-14: Simon Goldschmidt + * etharp.c/.h: Fixed ARP input processing: only add a new entry if a + request was directed as us (RFC 826, Packet Reception), otherwise + only update existing entries; internalized some functions + + 2010-02-14: Simon Goldschmidt + * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be + disabled on netif used for PPPoE) by adding a new netif flag + (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet + device but prevents usage of ARP (so that ethernet_input can be used + for PPPoE). + + 2010-02-12: Simon Goldschmidt + * netif.c: netif_set_link_up/down: only do something if the link state + actually changes + + 2010-02-12: Simon Goldschmidt/Stephane Lesage + * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking + connect) + + 2010-02-12: Simon Goldschmidt + * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) + + 2010-02-09: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 + (recv() makes receive window update for data that wasn't received by + application) + + 2010-02-09: Simon Goldschmidt/Stephane Lesage + * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out + or any netconn_recv() error) + + 2010-02-09: Simon Goldschmidt + * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) + + 2010-02-09: Simon Goldschmidt + * netif.c: For loopback packets, adjust the stats- and snmp-counters + for the loopback netif. + + 2010-02-08: Simon Goldschmidt + * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity + since they are not used anywhere else. + + 2010-02-08: Simon Goldschmidt (Stphane Lesage) + * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats + (patch from bug #28798) + + 2010-02-08: Simon Goldschmidt (Stphane Lesage) + * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and + another bug when LWIP_RAND() returns zero. + + 2010-02-04: Simon Goldschmidt + * nearly every file: Use macros defined in ip_addr.h (some of them new) + to work with IP addresses (preparation for bug #27352 - Change ip_addr + from struct to typedef (u32_t) - and better code). + + 2010-01-31: Simon Goldschmidt + * netif.c: Don't call the link-callback from netif_set_up/down() since + this invalidly retriggers DHCP. + + 2010-01-29: Simon Goldschmidt + * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the + portability file inet.h and its contents from the stack: moved htonX- + functions to def.h (and the new def.c - they are not ipv4 dependent), + let inet.h depend on ip_addr.h and not the other way round. + This fixes bug #28732. + + 2010-01-28: Kieran Mansley + * tcp.c: Ensure ssthresh >= 2*MSS + + 2010-01-27: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv + callback can lead to accessing unallocated memory. As a consequence, + ERR_ABRT means the application has called tcp_abort()! + + 2010-01-25: Simon Goldschmidt + * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY + not implemented in SNMP): write-only or not-accessible are still + returned by getnext (though not by get) + + 2010-01-24: Simon Goldschmidt + * snmp: Renamed the private mib node from 'private' to 'mib_private' to + not use reserved C/C++ keywords + + 2010-01-23: Simon Goldschmidt + * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less + than 1 ms + + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + + 2010-01-19: Simon Goldschmidt + * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp + + 2010-01-18: Iordan Neshev/Simon Goldschmidt + * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some + bugfix backports from 2.4.x. + + 2010-01-18: Simon Goldschmidt + * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong + + 2010-01-17: Simon Goldschmidt + * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): + task #10102: "netconn: clean up conn->err threading issues" by adding + error return value to struct api_msg_msg + + 2010-01-17: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() + to return err_t (bugs #27709 and #28087) + + 2010-01-14: Simon Goldschmidt + * ...: Use typedef for function prototypes throughout the stack. + + 2010-01-13: Simon Goldschmidt + * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive + window = 0) by correctly draining recvmbox/acceptmbox + + 2010-01-11: Simon Goldschmidt + * pap.c: Fixed bug #13315 (PPP PAP authentication can result in + erroneous callbacks) by copying the code from recent pppd + + 2010-01-10: Simon Goldschmidt + * raw.c: Fixed bug #28506 (raw_bind should filter received packets) + + 2010-01-10: Simon Goldschmidt + * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) + + 2010-01-08: Simon Goldschmidt + * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) + + 2010-01-08: Simon Goldschmidt + * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string + passed to dns_local_addhost() might be volatile + + 2010-01-07: Simon Goldschmidt + * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too + + 2010-01-06: Simon Goldschmidt + * netdb.h: Fixed bug #28496: missing include guards in netdb.h + + 2009-12-31: Simon Goldschmidt + * many ppp files: Reorganised PPP source code from ucip structure to pppd + structure to easily compare our code against the pppd code (around v2.3.1) + + 2009-12-27: Simon Goldschmidt + * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted + unit test + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jrg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frdric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frdric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frdric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frdric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frdric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frdric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frdric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frdric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frdric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frdric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frdric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frdric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frdric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frdric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frdric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frdric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frdric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frdric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frdric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frdric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frdric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frdric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frdric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frdric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frdric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frdric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frdric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frdric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frdric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frdric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frdric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frdric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frdric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frdric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frdric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frdric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frdric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frdric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frdric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frdric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frdric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frdric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frdric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frdric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frdric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frdric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frdric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frdric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frdric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frdric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frdric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frdric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frdric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frdric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frdric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frdric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frdric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frdric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frdric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frdric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frdric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frdric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frdric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frdric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frdric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frdric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frdric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frdric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frdric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frdric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frdric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frdric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frdric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frdric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frdric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frdric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frdric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frdric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frdric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frdric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frdric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frdric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frdric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frdric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frdric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frdric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frdric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frdric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frdric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frdric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frdric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frdric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frdric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frdric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frdric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frdric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frdric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frdric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frdric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frdric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frdric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frdric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frdric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frdric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frdric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frdric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frdric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frdric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frdric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frdric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frdric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/Shared/lwip/CMakeLists.txt b/Shared/lwip/CMakeLists.txt new file mode 100644 index 0000000..121892d --- /dev/null +++ b/Shared/lwip/CMakeLists.txt @@ -0,0 +1,27 @@ +set(LWIP_SOURCES + src/core/timers.c + src/core/udp.c + src/core/memp.c + src/core/init.c + src/core/pbuf.c + src/core/tcp.c + src/core/tcp_out.c + src/core/sys.c + src/core/netif.c + src/core/def.c + src/core/mem.c + src/core/tcp_in.c + src/core/stats.c + src/core/inet_chksum.c + src/core/ipv4/icmp.c + src/core/ipv4/ip4.c + src/core/ipv4/ip4_addr.c + src/core/ipv4/ip_frag.c + src/core/ipv6/ip6.c + src/core/ipv6/nd6.c + src/core/ipv6/icmp6.c + src/core/ipv6/ip6_addr.c + src/core/ipv6/ip6_frag.c + custom/sys.c +) +badvpn_add_library(lwip "system" "" "${LWIP_SOURCES}") diff --git a/Shared/lwip/COPYING b/Shared/lwip/COPYING new file mode 100644 index 0000000..e23898b --- /dev/null +++ b/Shared/lwip/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/Shared/lwip/FILES b/Shared/lwip/FILES new file mode 100644 index 0000000..6625319 --- /dev/null +++ b/Shared/lwip/FILES @@ -0,0 +1,4 @@ +src/ - The source code for the lwIP TCP/IP stack. +doc/ - The documentation for lwIP. + +See also the FILES file in each subdirectory. diff --git a/Shared/lwip/README b/Shared/lwip/README new file mode 100644 index 0000000..a62cc4f --- /dev/null +++ b/Shared/lwip/README @@ -0,0 +1,89 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + +FEATURES + + * IP (Internet Protocol) including packet forwarding over multiple network + interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * Specialized raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + * SNMP (Simple Network Management Protocol) + * DHCP (Dynamic Host Configuration Protocol) + * AUTOIP (for IPv4, conform with RFC 3927) + * PPP (Point-to-Point Protocol) + * ARP (Address Resolution Protocol) for Ethernet + +LICENSE + +lwIP is freely available under a BSD license. + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, CVS and the +mailing list. A core team of developers will commit changes to the +CVS source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and +contributions (such as platform ports) are in the 'contrib' module. + +See doc/savannah.txt for details on CVS server access for users and +developers. + +Last night's CVS tar ball can be downloaded from: + http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING] + +The current CVS trees are web-browsable: + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/ + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/ + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + + +DOCUMENTATION + +The original out-dated homepage of lwIP and Adam Dunkels' papers on +lwIP are at the official lwIP home page: + http://www.sics.se/~adam/lwip/ + +Self documentation of the source code is regularly extracted from the +current CVS sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growin wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg + diff --git a/Shared/lwip/UPGRADING b/Shared/lwip/UPGRADING new file mode 100644 index 0000000..6501107 --- /dev/null +++ b/Shared/lwip/UPGRADING @@ -0,0 +1,144 @@ +This file lists major changes between release versions that require +ports or applications to be changed. Use it to update a port or an +application written for an older version of lwIP to correctly work +with newer versions. + + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ Application changes: + + * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for + compatibility to old applications, but will be removed in the future). + + * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() + + +++ Raw API: + * Changed the semantics of tcp_close() (since it was rather a + shutdown before): Now the application does *NOT* get any calls to the recv + callback (aside from NULL/closed) after calling tcp_close() + + * When calling tcp_abort() from a raw API TCP callback function, + make sure you return ERR_ABRT to prevent accessing unallocated memory. + (ERR_ABRT now means the applicaiton has called tcp_abort!) + + +++ Netconn API: + * Changed netconn_receive() and netconn_accept() to return + err_t, not a pointer to new data/netconn. + + +++ Socket API: + * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they + now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. + + * Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + +++ all APIs: + * correctly implemented SO(F)_REUSEADDR + + ++ Port changes + + +++ new files: + + * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: + + * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains + the actual application programmer's API + + * Separated timer implementation from sys.h/.c, moved to timers.h/.c; + Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you + still want to use your own timer implementation for NO_SYS==0 (as before). + + +++ sys layer: + + * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ + sys_sem_t; + + * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + + * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use + binary semaphores instead of mutexes - as before) + + +++ new options: + + * Don't waste memory when chaining segments, added option TCP_OVERSIZE to + prevent creating many small pbufs when calling tcp_write with many small + blocks of data. Instead, pbufs are allocated larger than needed and the + space is used for later calls to tcp_write. + + * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs + in tcp_write/udp_send. + + * Added an additional option LWIP_ETHERNET to support ethernet without ARP + (necessary for pure PPPoE) + + * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may + be used to place these pools into user-defined memory by using external + declaration. + + * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT + + +++ new pools: + + * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, + so MEMP_NUM_NETDB has to be set accordingly. + + * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so + MEMP_NUM_LOCALHOSTLIST has to be set accordingly. + + * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have + to be set accordingly. + + * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES + has to be set accordingly + + * Integrated loopif into netif.c - loopif does not have to be created by the + port any more, just define LWIP_HAVE_LOOPIF to 1. + + * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined + in cc.h, e.g. used by igmp) + + * Added printf-formatter X8_F to printf u8_t as hex + + * The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + + * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work + with user-allocated structs instead of calling mem_malloc + + * Added const char* name to mem- and memp-stats for easier debugging. + + * Calculate the TCP/UDP checksum while copying to only fetch data once: + Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum + + * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to + more than one pcb. + + * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned + off any more, if this is set to 0, only one packet (the most recent one) is + queued (like demanded by RFC 1122). + + + ++ Major bugfixes/improvements + + * Implemented tcp_shutdown() to only shut down one end of a connection + * Implemented shutdown() at socket- and netconn-level + * Added errorset support to select() + improved select speed overhead + * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) + * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 + * Use macros defined in ip_addr.h to work with IP addresses + * Implemented many nonblocking socket/netconn functions + * Fixed ARP input processing: only add a new entry if a request was directed as us + * mem_realloc() to mem_trim() to prevent confusion with realloc() + * Some improvements for AutoIP (don't route/forward link-local addresses, don't break + existing connections when assigning a routable address) + * Correctly handle remote side overrunning our rcv_wnd in ooseq case + * Removed packing from ip_addr_t, the packed version is now only used in protocol headers + * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 + * Added support for static ARP table entries + +(STABLE-1.3.2) + + * initial version of this file diff --git a/Shared/lwip/badvpn/misc/BRefTarget.h b/Shared/lwip/badvpn/misc/BRefTarget.h new file mode 100644 index 0000000..4324605 --- /dev/null +++ b/Shared/lwip/badvpn/misc/BRefTarget.h @@ -0,0 +1,114 @@ +/** + * @file BRefTarget.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_B_REF_TARGET_H +#define BADVPN_B_REF_TARGET_H + +#include + +#include +#include + +/** + * Represents a reference-counted object. + */ +typedef struct BRefTarget_s BRefTarget; + +/** + * Callback function called after the reference count of a {@link BRefTarget} + * reaches has reached zero. At this point the BRefTarget object has already + * been invalidated, i.e. {@link BRefTarget_Ref} must not be called on this + * object after this handler is called. + */ +typedef void (*BRefTarget_func_release) (BRefTarget *o); + +struct BRefTarget_s { + BRefTarget_func_release func_release; + int refcnt; + DebugObject d_obj; +}; + +/** + * Initializes a reference target object. The initial reference count of the object + * is 1. The \a func_release argument specifies the function to be called from + * {@link BRefTarget_Deref} when the reference count reaches zero. + */ +static void BRefTarget_Init (BRefTarget *o, BRefTarget_func_release func_release); + +/** + * Decrements the reference count of a reference target object. If the reference + * count has reached zero, the object's {@link BRefTarget_func_release} function + * is called, and the object is considered destroyed. + */ +static void BRefTarget_Deref (BRefTarget *o); + +/** + * Increments the reference count of a reference target object. + * Returns 1 on success and 0 on failure. + */ +static int BRefTarget_Ref (BRefTarget *o) WARN_UNUSED; + +static void BRefTarget_Init (BRefTarget *o, BRefTarget_func_release func_release) +{ + ASSERT(func_release) + + o->func_release = func_release; + o->refcnt = 1; + + DebugObject_Init(&o->d_obj); +} + +static void BRefTarget_Deref (BRefTarget *o) +{ + DebugObject_Access(&o->d_obj); + ASSERT(o->refcnt > 0) + + o->refcnt--; + + if (o->refcnt == 0) { + DebugObject_Free(&o->d_obj); + o->func_release(o); + } +} + +static int BRefTarget_Ref (BRefTarget *o) +{ + DebugObject_Access(&o->d_obj); + ASSERT(o->refcnt > 0) + + if (o->refcnt == INT_MAX) { + return 0; + } + + o->refcnt++; + + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/Utf16Decoder.h b/Shared/lwip/badvpn/misc/Utf16Decoder.h new file mode 100644 index 0000000..819ac94 --- /dev/null +++ b/Shared/lwip/badvpn/misc/Utf16Decoder.h @@ -0,0 +1,113 @@ +/** + * @file Utf16Decoder.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_UTF16DECODER_H +#define BADVPN_UTF16DECODER_H + +#include + +#include + +/** + * Decodes UTF-16 data into Unicode characters. + */ +typedef struct { + int cont; + uint32_t ch; +} Utf16Decoder; + +/** + * Initializes the UTF-16 decoder. + * + * @param o the object + */ +static void Utf16Decoder_Init (Utf16Decoder *o); + +/** + * Inputs a 16-bit value to the decoder. + * + * @param o the object + * @param b 16-bit value to input + * @param out_ch will receive a Unicode character if this function returns 1. + * If written, the character will be in the range 0 - 0x10FFFF, + * excluding the surrogate range 0xD800 - 0xDFFF. + * @return 1 if a Unicode character has been written to *out_ch, 0 if not + */ +static int Utf16Decoder_Input (Utf16Decoder *o, uint16_t b, uint32_t *out_ch); + +void Utf16Decoder_Init (Utf16Decoder *o) +{ + o->cont = 0; +} + +int Utf16Decoder_Input (Utf16Decoder *o, uint16_t b, uint32_t *out_ch) +{ + // high surrogate + if (b >= UINT16_C(0xD800) && b <= UINT16_C(0xDBFF)) { + // set continuation state + o->cont = 1; + + // add high bits + o->ch = (uint32_t)(b - UINT16_C(0xD800)) << 10; + + return 0; + } + + // low surrogate + if (b >= UINT16_C(0xDC00) && b <= UINT16_C(0xDFFF)) { + // check continuation + if (!o->cont) { + return 0; + } + + // add low bits + o->ch |= (b - UINT16_C(0xDC00)); + + // reset state + o->cont = 0; + + // don't report surrogates + if (o->ch >= UINT32_C(0xD800) && o->ch <= UINT32_C(0xDFFF)) { + return 0; + } + + // return character + *out_ch = o->ch; + return 1; + } + + // reset state + o->cont = 0; + + // return character + *out_ch = b; + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/Utf16Encoder.h b/Shared/lwip/badvpn/misc/Utf16Encoder.h new file mode 100644 index 0000000..4900b42 --- /dev/null +++ b/Shared/lwip/badvpn/misc/Utf16Encoder.h @@ -0,0 +1,67 @@ +/** + * @file Utf16Encoder.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_UTF16ENCODER_H +#define BADVPN_UTF16ENCODER_H + +#include + +/** + * Encodes a Unicode character into a sequence of 16-bit values according to UTF-16. + * + * @param ch Unicode character to encode + * @param out will receive the encoded 16-bit values. Must have space for 2 values. + * @return number of 16-bit values written, 0-2, with 0 meaning the character cannot + * be encoded + */ +static int Utf16Encoder_EncodeCharacter (uint32_t ch, uint16_t *out); + +int Utf16Encoder_EncodeCharacter (uint32_t ch, uint16_t *out) +{ + if (ch <= UINT32_C(0xFFFF)) { + // surrogates + if (ch >= UINT32_C(0xD800) && ch <= UINT32_C(0xDFFF)) { + return 0; + } + + out[0] = ch; + return 1; + } + + if (ch <= UINT32_C(0x10FFFF)) { + uint32_t x = ch - UINT32_C(0x10000); + out[0] = UINT32_C(0xD800) + (x >> 10); + out[1] = UINT32_C(0xDC00) + (x & UINT32_C(0x3FF)); + return 2; + } + + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/Utf8Decoder.h b/Shared/lwip/badvpn/misc/Utf8Decoder.h new file mode 100644 index 0000000..c6412b1 --- /dev/null +++ b/Shared/lwip/badvpn/misc/Utf8Decoder.h @@ -0,0 +1,143 @@ +/** + * @file Utf8Decoder.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_UTF8DECODER_H +#define BADVPN_UTF8DECODER_H + +#include + +#include + +/** + * Decodes UTF-8 data into Unicode characters. + */ +typedef struct { + int bytes; + int pos; + uint32_t ch; +} Utf8Decoder; + +/** + * Initializes the UTF-8 decoder. + * + * @param o the object + */ +static void Utf8Decoder_Init (Utf8Decoder *o); + +/** + * Inputs a byte to the decoder. + * + * @param o the object + * @param b byte to input + * @param out_ch will receive a Unicode character if this function returns 1. + * If written, the character will be in the range 0 - 0x10FFFF, + * excluding the surrogate range 0xD800 - 0xDFFF. + * @return 1 if a Unicode character has been written to *out_ch, 0 if not + */ +static int Utf8Decoder_Input (Utf8Decoder *o, uint8_t b, uint32_t *out_ch); + +void Utf8Decoder_Init (Utf8Decoder *o) +{ + o->bytes = 0; +} + +int Utf8Decoder_Input (Utf8Decoder *o, uint8_t b, uint32_t *out_ch) +{ + // one-byte character + if ((b & 128) == 0) { + o->bytes = 0; + *out_ch = b; + return 1; + } + + // start of two-byte character + if ((b & 224) == 192) { + o->bytes = 2; + o->pos = 1; + o->ch = (uint32_t)(b & 31) << 6; + return 0; + } + + // start of three-byte character + if ((b & 240) == 224) { + o->bytes = 3; + o->pos = 1; + o->ch = (uint32_t)(b & 15) << 12; + return 0; + } + + // start of four-byte character + if ((b & 248) == 240) { + o->bytes = 4; + o->pos = 1; + o->ch = (uint32_t)(b & 7) << 18; + return 0; + } + + // continuation of multi-byte character + if ((b & 192) == 128 && o->bytes > 0) { + ASSERT(o->bytes <= 4) + ASSERT(o->pos > 0) + ASSERT(o->pos < o->bytes) + + // add bits from this byte + o->ch |= (uint32_t)(b & 63) << (6 * (o->bytes - o->pos - 1)); + + // end of multi-byte character? + if (o->pos == o->bytes - 1) { + // reset state + o->bytes = 0; + + // don't report out-of-range characters + if (o->ch > UINT32_C(0x10FFFF)) { + return 0; + } + + // don't report surrogates + if (o->ch >= UINT32_C(0xD800) && o->ch <= UINT32_C(0xDFFF)) { + return 0; + } + + *out_ch = o->ch; + return 1; + } + + // increment byte index + o->pos++; + + return 0; + } + + // error, reset state + o->bytes = 0; + + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/Utf8Encoder.h b/Shared/lwip/badvpn/misc/Utf8Encoder.h new file mode 100644 index 0000000..00eb5e6 --- /dev/null +++ b/Shared/lwip/badvpn/misc/Utf8Encoder.h @@ -0,0 +1,81 @@ +/** + * @file Utf8Encoder.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_UTF8ENCODER_H +#define BADVPN_UTF8ENCODER_H + +#include + +/** + * Encodes a Unicode character into a sequence of bytes according to UTF-8. + * + * @param ch Unicode character to encode + * @param out will receive the encoded bytes. Must have space for 4 bytes. + * @return number of bytes written, 0-4, with 0 meaning the character cannot + * be encoded + */ +static int Utf8Encoder_EncodeCharacter (uint32_t ch, uint8_t *out); + +int Utf8Encoder_EncodeCharacter (uint32_t ch, uint8_t *out) +{ + if (ch <= UINT32_C(0x007F)) { + out[0] = ch; + return 1; + } + + if (ch <= UINT32_C(0x07FF)) { + out[0] = (0xC0 | (ch >> 6)); + out[1] = (0x80 | ((ch >> 0) & 0x3F)); + return 2; + } + + if (ch <= UINT32_C(0xFFFF)) { + // surrogates + if (ch >= UINT32_C(0xD800) && ch <= UINT32_C(0xDFFF)) { + return 0; + } + + out[0] = (0xE0 | (ch >> 12)); + out[1] = (0x80 | ((ch >> 6) & 0x3F)); + out[2] = (0x80 | ((ch >> 0) & 0x3F)); + return 3; + } + + if (ch < UINT32_C(0x10FFFF)) { + out[0] = (0xF0 | (ch >> 18)); + out[1] = (0x80 | ((ch >> 12) & 0x3F)); + out[2] = (0x80 | ((ch >> 6) & 0x3F)); + out[3] = (0x80 | ((ch >> 0) & 0x3F)); + return 4; + } + + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/arp_proto.h b/Shared/lwip/badvpn/misc/arp_proto.h new file mode 100644 index 0000000..71a6c98 --- /dev/null +++ b/Shared/lwip/badvpn/misc/arp_proto.h @@ -0,0 +1,60 @@ +/** + * @file arp_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the ARP protocol. + */ + +#ifndef BADVPN_ARP_PROTO_H +#define BADVPN_ARP_PROTO_H + +#include + +#include + +#define ARP_HARDWARE_TYPE_ETHERNET 1 + +#define ARP_OPCODE_REQUEST 1 +#define ARP_OPCODE_REPLY 2 + +B_START_PACKED +struct arp_packet { + uint16_t hardware_type; + uint16_t protocol_type; + uint8_t hardware_size; + uint8_t protocol_size; + uint16_t opcode; + uint8_t sender_mac[6]; + uint32_t sender_ip; + uint8_t target_mac[6]; + uint32_t target_ip; +} B_PACKED; +B_END_PACKED + +#endif diff --git a/Shared/lwip/badvpn/misc/array_length.h b/Shared/lwip/badvpn/misc/array_length.h new file mode 100644 index 0000000..15de964 --- /dev/null +++ b/Shared/lwip/badvpn/misc/array_length.h @@ -0,0 +1,35 @@ +/** + * @file array_length.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_ARRAY_LENGTH +#define BADVPN_ARRAY_LENGTH + +#define B_ARRAY_LENGTH(arr) (sizeof((arr)) / sizeof((arr)[0])) + +#endif diff --git a/Shared/lwip/badvpn/misc/ascii_utils.h b/Shared/lwip/badvpn/misc/ascii_utils.h new file mode 100644 index 0000000..2baa9fc --- /dev/null +++ b/Shared/lwip/badvpn/misc/ascii_utils.h @@ -0,0 +1,43 @@ +/** + * @file ascii_utils.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_ASCII_UTILS_H +#define BADVPN_ASCII_UTILS_H + +static char b_ascii_tolower (char c) +{ + return (c >= 'A' && c <= 'Z') ? (c + 32) : c; +} + +static char b_ascii_toupper (char c) +{ + return (c >= 'a' && c <= 'z') ? (c - 32) : c; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/balign.h b/Shared/lwip/badvpn/misc/balign.h new file mode 100644 index 0000000..57152af --- /dev/null +++ b/Shared/lwip/badvpn/misc/balign.h @@ -0,0 +1,76 @@ +/** + * @file balign.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Integer alignment macros. + */ + +#ifndef BADVPN_MISC_BALIGN_H +#define BADVPN_MISC_BALIGN_H + +#include +#include + +/** + * Checks if aligning x up to n would overflow. + */ +static int balign_up_overflows (size_t x, size_t n) +{ + size_t r = x % n; + + return (r && x > SIZE_MAX - (n - r)); +} + +/** + * Aligns x up to n. + */ +static size_t balign_up (size_t x, size_t n) +{ + size_t r = x % n; + return (r ? x + (n - r) : x); +} + +/** + * Aligns x down to n. + */ +static size_t balign_down (size_t x, size_t n) +{ + return (x - (x % n)); +} + +/** + * Calculates the quotient of a and b, rounded up. + */ +static size_t bdivide_up (size_t a, size_t b) +{ + size_t r = a % b; + return (r > 0 ? a / b + 1 : a / b); +} + +#endif diff --git a/Shared/lwip/badvpn/misc/balloc.h b/Shared/lwip/badvpn/misc/balloc.h new file mode 100644 index 0000000..7d2d54f --- /dev/null +++ b/Shared/lwip/badvpn/misc/balloc.h @@ -0,0 +1,248 @@ +/** + * @file balloc.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Memory allocation functions. + */ + +#ifndef BADVPN_MISC_BALLOC_H +#define BADVPN_MISC_BALLOC_H + +#include +#include +#include +#include + +#include +#include +#include + +/** + * Allocates memory. + * + * @param bytes number of bytes to allocate. + * @return a non-NULL pointer to the memory, or NULL on failure. + * The memory allocated can be freed using {@link BFree}. + */ +static void * BAlloc (size_t bytes); + +/** + * Frees memory. + * + * @param m memory to free. Must have been obtained with {@link BAlloc}, + * {@link BAllocArray}, or {@link BAllocArray2}. May be NULL; + * in this case, this function does nothing. + */ +static void BFree (void *m); + +/** + * Changes the size of a memory block. On success, the memory block + * may be moved to a different address. + * + * @param m pointer to a memory block obtained from {@link BAlloc} + * or other functions in this group. If this is NULL, the + * call is equivalent to {@link BAlloc}(bytes). + * @param bytes new size of the memory block + * @return new pointer to the memory block, or NULL on failure + */ +static void * BRealloc (void *m, size_t bytes); + +/** + * Allocates memory, with size given as a {@link bsize_t}. + * + * @param bytes number of bytes to allocate. If the size is overflow, + * this function will return NULL. + * @return a non-NULL pointer to the memory, or NULL on failure. + * The memory allocated can be freed using {@link BFree}. + */ +static void * BAllocSize (bsize_t bytes); + +/** + * Allocates memory for an array. + * A check is first done to make sure the multiplication doesn't overflow; + * otherwise, this is equivalent to {@link BAlloc}(count * bytes). + * This may be slightly faster if 'bytes' is constant, because a division + * with 'bytes' is performed. + * + * @param count number of elements. + * @param bytes size of one array element. + * @return a non-NULL pointer to the memory, or NULL on failure. + * The memory allocated can be freed using {@link BFree}. + */ +static void * BAllocArray (size_t count, size_t bytes); + +/** + * Reallocates memory that was allocated using one of the allocation + * functions in this file. On success, the memory may be moved to a + * different address, leaving the old address invalid. + * + * @param mem pointer to an existing memory block. May be NULL, in which + * case this is equivalent to {@link BAllocArray}. + * @param count number of elements for reallocation + * @param bytes size of one array element for reallocation + * @return a non-NULL pointer to the address of the reallocated memory + * block, or NULL on failure. On failure, the original memory + * block is left intact. + */ +static void * BReallocArray (void *mem, size_t count, size_t bytes); + +/** + * Allocates memory for a two-dimensional array. + * + * Checks are first done to make sure the multiplications don't overflow; + * otherwise, this is equivalent to {@link BAlloc}((count2 * (count1 * bytes)). + * + * @param count2 number of elements in one dimension. + * @param count1 number of elements in the other dimension. + * @param bytes size of one array element. + * @return a non-NULL pointer to the memory, or NULL on failure. + * The memory allocated can be freed using {@link BFree}. + */ +static void * BAllocArray2 (size_t count2, size_t count1, size_t bytes); + +/** + * Adds to a size_t with overflow detection. + * + * @param s pointer to a size_t to add to + * @param add number to add + * @return 1 on success, 0 on failure + */ +static int BSizeAdd (size_t *s, size_t add); + +/** + * Aligns a size_t upwards with overflow detection. + * + * @param s pointer to a size_t to align + * @param align alignment value. Must be >0. + * @return 1 on success, 0 on failure + */ +static int BSizeAlign (size_t *s, size_t align); + +void * BAlloc (size_t bytes) +{ + if (bytes == 0) { + return malloc(1); + } + + return malloc(bytes); +} + +void BFree (void *m) +{ + free(m); +} + +void * BRealloc (void *m, size_t bytes) +{ + if (bytes == 0) { + return realloc(m, 1); + } + + return realloc(m, bytes); +} + +void * BAllocSize (bsize_t bytes) +{ + if (bytes.is_overflow) { + return NULL; + } + + return BAlloc(bytes.value); +} + +void * BAllocArray (size_t count, size_t bytes) +{ + if (count == 0 || bytes == 0) { + return malloc(1); + } + + if (count > SIZE_MAX / bytes) { + return NULL; + } + + return BAlloc(count * bytes); +} + +void * BReallocArray (void *mem, size_t count, size_t bytes) +{ + if (count == 0 || bytes == 0) { + return realloc(mem, 1); + } + + if (count > SIZE_MAX / bytes) { + return NULL; + } + + return realloc(mem, count * bytes); +} + +void * BAllocArray2 (size_t count2, size_t count1, size_t bytes) +{ + if (count2 == 0 || count1 == 0 || bytes == 0) { + return malloc(1); + } + + if (count1 > SIZE_MAX / bytes) { + return NULL; + } + + if (count2 > SIZE_MAX / (count1 * bytes)) { + return NULL; + } + + return BAlloc(count2 * (count1 * bytes)); +} + +int BSizeAdd (size_t *s, size_t add) +{ + ASSERT(s) + + if (add > SIZE_MAX - *s) { + return 0; + } + *s += add; + return 1; +} + +int BSizeAlign (size_t *s, size_t align) +{ + ASSERT(s) + ASSERT(align > 0) + + size_t mod = *s % align; + if (mod > 0) { + if (align - mod > SIZE_MAX - *s) { + return 0; + } + *s += align - mod; + } + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/blimits.h b/Shared/lwip/badvpn/misc/blimits.h new file mode 100644 index 0000000..8bcdc2a --- /dev/null +++ b/Shared/lwip/badvpn/misc/blimits.h @@ -0,0 +1,60 @@ +/** + * @file blimits.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_BLIMITS_H +#define BADVPN_BLIMITS_H + +#include + +#define BTYPE_IS_SIGNED(type) ((type)-1 < 0) + +#define BSIGNED_TYPE_MIN(type) ( \ + sizeof(type) == 1 ? INT8_MIN : ( \ + sizeof(type) == 2 ? INT16_MIN : ( \ + sizeof(type) == 4 ? INT32_MIN : ( \ + sizeof(type) == 8 ? INT64_MIN : 0)))) + +#define BSIGNED_TYPE_MAX(type) ( \ + sizeof(type) == 1 ? INT8_MAX : ( \ + sizeof(type) == 2 ? INT16_MAX : ( \ + sizeof(type) == 4 ? INT32_MAX : ( \ + sizeof(type) == 8 ? INT64_MAX : 0)))) + +#define BUNSIGNED_TYPE_MIN(type) ((type)0) + +#define BUNSIGNED_TYPE_MAX(type) ( \ + sizeof(type) == 1 ? UINT8_MAX : ( \ + sizeof(type) == 2 ? UINT16_MAX : ( \ + sizeof(type) == 4 ? UINT32_MAX : ( \ + sizeof(type) == 8 ? UINT64_MAX : 0)))) + +#define BTYPE_MIN(type) (BTYPE_IS_SIGNED(type) ? BSIGNED_TYPE_MIN(type) : BUNSIGNED_TYPE_MIN(type)) +#define BTYPE_MAX(type) (BTYPE_IS_SIGNED(type) ? BSIGNED_TYPE_MAX(type) : BUNSIGNED_TYPE_MAX(type)) + +#endif diff --git a/Shared/lwip/badvpn/misc/bsize.h b/Shared/lwip/badvpn/misc/bsize.h new file mode 100644 index 0000000..2d724df --- /dev/null +++ b/Shared/lwip/badvpn/misc/bsize.h @@ -0,0 +1,117 @@ +/** + * @file bsize.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Arithmetic with overflow detection. + */ + +#ifndef BADVPN_MISC_BSIZE_H +#define BADVPN_MISC_BSIZE_H + +#include +#include +#include + +typedef struct { + int is_overflow; + size_t value; +} bsize_t; + +static bsize_t bsize_fromsize (size_t v); +static bsize_t bsize_fromint (int v); +static bsize_t bsize_overflow (void); +static int bsize_tosize (bsize_t s, size_t *out); +static int bsize_toint (bsize_t s, int *out); +static bsize_t bsize_add (bsize_t s1, bsize_t s2); +static bsize_t bsize_max (bsize_t s1, bsize_t s2); +static bsize_t bsize_mul (bsize_t s1, bsize_t s2); + +bsize_t bsize_fromsize (size_t v) +{ + bsize_t s = {0, v}; + return s; +} + +bsize_t bsize_fromint (int v) +{ + bsize_t s = {(v < 0 || v > SIZE_MAX), v}; + return s; +} + +static bsize_t bsize_overflow (void) +{ + bsize_t s = {1, 0}; + return s; +} + +int bsize_tosize (bsize_t s, size_t *out) +{ + if (s.is_overflow) { + return 0; + } + + if (out) { + *out = s.value; + } + + return 1; +} + +int bsize_toint (bsize_t s, int *out) +{ + if (s.is_overflow || s.value > INT_MAX) { + return 0; + } + + if (out) { + *out = s.value; + } + + return 1; +} + +bsize_t bsize_add (bsize_t s1, bsize_t s2) +{ + bsize_t s = {(s1.is_overflow || s2.is_overflow || s2.value > SIZE_MAX - s1.value), (s1.value + s2.value)}; + return s; +} + +bsize_t bsize_max (bsize_t s1, bsize_t s2) +{ + bsize_t s = {(s1.is_overflow || s2.is_overflow), ((s1.value > s2.value) * s1.value + (s1.value <= s2.value) * s2.value)}; + return s; +} + +bsize_t bsize_mul (bsize_t s1, bsize_t s2) +{ + bsize_t s = {(s1.is_overflow || s2.is_overflow || (s1.value != 0 && s2.value > SIZE_MAX / s1.value)), (s1.value * s2.value)}; + return s; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/bsort.h b/Shared/lwip/badvpn/misc/bsort.h new file mode 100644 index 0000000..24d7a66 --- /dev/null +++ b/Shared/lwip/badvpn/misc/bsort.h @@ -0,0 +1,69 @@ +/** + * @file bsort.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Sorting functions. + */ + +#ifndef BADVPN_MISC_BSORT_H +#define BADVPN_MISC_BSORT_H + +#include +#include +#include + +#include +#include + +typedef int (*BSort_comparator) (const void *e1, const void *e2); + +static void BInsertionSort (void *arr, size_t count, size_t esize, BSort_comparator compatator, void *temp); + +void BInsertionSort (void *arr, size_t count, size_t esize, BSort_comparator compatator, void *temp) +{ + ASSERT(esize > 0) + + for (size_t i = 0; i < count; i++) { + size_t j = i; + while (j > 0) { + uint8_t *x = (uint8_t *)arr + (j - 1) * esize; + uint8_t *y = (uint8_t *)arr + j * esize; + int c = compatator(x, y); + if (c <= 0) { + break; + } + memcpy(temp, x, esize); + memcpy(x, y, esize); + memcpy(y, temp, esize); + j--; + } + } +} + +#endif diff --git a/Shared/lwip/badvpn/misc/bstring.h b/Shared/lwip/badvpn/misc/bstring.h new file mode 100644 index 0000000..caef106 --- /dev/null +++ b/Shared/lwip/badvpn/misc/bstring.h @@ -0,0 +1,140 @@ +/** + * @file bstring.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_BSTRING_H +#define BADVPN_BSTRING_H + +#include + +#include +#include + +#define BSTRING_TYPE_STATIC 5 +#define BSTRING_TYPE_DYNAMIC 7 +#define BSTRING_TYPE_EXTERNAL 11 + +#define BSTRING_STATIC_SIZE 23 +#define BSTRING_STATIC_MAX (BSTRING_STATIC_SIZE - 1) + +typedef struct { + union { + struct { + char type; + char static_string[BSTRING_STATIC_SIZE]; + } us; + struct { + char type; + char *dynamic_string; + } ud; + struct { + char type; + const char *external_string; + } ue; + } u; +} BString; + +static void BString__assert (BString *o) +{ + switch (o->u.us.type) { + case BSTRING_TYPE_STATIC: + case BSTRING_TYPE_DYNAMIC: + case BSTRING_TYPE_EXTERNAL: + return; + } + + ASSERT(0); +} + +static int BString_Init (BString *o, const char *str) +{ + if (strlen(str) <= BSTRING_STATIC_MAX) { + strcpy(o->u.us.static_string, str); + o->u.us.type = BSTRING_TYPE_STATIC; + } else { + if (!(o->u.ud.dynamic_string = malloc(strlen(str) + 1))) { + return 0; + } + strcpy(o->u.ud.dynamic_string, str); + o->u.ud.type = BSTRING_TYPE_DYNAMIC; + } + + BString__assert(o); + return 1; +} + +static void BString_InitStatic (BString *o, const char *str) +{ + ASSERT(strlen(str) <= BSTRING_STATIC_MAX) + + strcpy(o->u.us.static_string, str); + o->u.us.type = BSTRING_TYPE_STATIC; + + BString__assert(o); +} + +static void BString_InitExternal (BString *o, const char *str) +{ + o->u.ue.external_string = str; + o->u.ue.type = BSTRING_TYPE_EXTERNAL; + + BString__assert(o); +} + +static void BString_InitAllocated (BString *o, char *str) +{ + o->u.ud.dynamic_string = str; + o->u.ud.type = BSTRING_TYPE_DYNAMIC; + + BString__assert(o); +} + +static void BString_Free (BString *o) +{ + BString__assert(o); + + if (o->u.ud.type == BSTRING_TYPE_DYNAMIC) { + free(o->u.ud.dynamic_string); + } +} + +static const char * BString_Get (BString *o) +{ + BString__assert(o); + + switch (o->u.us.type) { + case BSTRING_TYPE_STATIC: return o->u.us.static_string; + case BSTRING_TYPE_DYNAMIC: return o->u.ud.dynamic_string; + case BSTRING_TYPE_EXTERNAL: return o->u.ue.external_string; + } + + ASSERT(0); + return NULL; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/byteorder.h b/Shared/lwip/badvpn/misc/byteorder.h new file mode 100644 index 0000000..6d21d1b --- /dev/null +++ b/Shared/lwip/badvpn/misc/byteorder.h @@ -0,0 +1,197 @@ +/** + * @file byteorder.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Byte order conversion functions. + * + * hton* functions convert from host to big-endian (network) byte order. + * htol* functions convert from host to little-endian byte order. + * ntoh* functions convert from big-endian (network) to host byte order. + * ltoh* functions convert from little-endian to host byte order. + */ + +#ifndef BADVPN_MISC_BYTEORDER_H +#define BADVPN_MISC_BYTEORDER_H + +#define BADVPN_LITTLE_ENDIAN 1 +#if (defined(BADVPN_LITTLE_ENDIAN) + defined(BADVPN_BIG_ENDIAN)) != 1 +#error Unknown byte order or too many byte orders +#endif + +#include + +static uint16_t badvpn_reverse16 (uint16_t x) +{ + uint16_t y; + *((uint8_t *)&y+0) = *((uint8_t *)&x+1); + *((uint8_t *)&y+1) = *((uint8_t *)&x+0); + return y; +} + +static uint32_t badvpn_reverse32 (uint32_t x) +{ + uint32_t y; + *((uint8_t *)&y+0) = *((uint8_t *)&x+3); + *((uint8_t *)&y+1) = *((uint8_t *)&x+2); + *((uint8_t *)&y+2) = *((uint8_t *)&x+1); + *((uint8_t *)&y+3) = *((uint8_t *)&x+0); + return y; +} + +static uint64_t badvpn_reverse64 (uint64_t x) +{ + uint64_t y; + *((uint8_t *)&y+0) = *((uint8_t *)&x+7); + *((uint8_t *)&y+1) = *((uint8_t *)&x+6); + *((uint8_t *)&y+2) = *((uint8_t *)&x+5); + *((uint8_t *)&y+3) = *((uint8_t *)&x+4); + *((uint8_t *)&y+4) = *((uint8_t *)&x+3); + *((uint8_t *)&y+5) = *((uint8_t *)&x+2); + *((uint8_t *)&y+6) = *((uint8_t *)&x+1); + *((uint8_t *)&y+7) = *((uint8_t *)&x+0); + return y; +} + +static uint8_t hton8 (uint8_t x) +{ + return x; +} + +static uint8_t htol8 (uint8_t x) +{ + return x; +} + +#if defined(BADVPN_LITTLE_ENDIAN) + +static uint16_t hton16 (uint16_t x) +{ + return badvpn_reverse16(x); +} + +static uint32_t hton32 (uint32_t x) +{ + return badvpn_reverse32(x); +} + +static uint64_t hton64 (uint64_t x) +{ + return badvpn_reverse64(x); +} + +static uint16_t htol16 (uint16_t x) +{ + return x; +} + +static uint32_t htol32 (uint32_t x) +{ + return x; +} + +static uint64_t htol64 (uint64_t x) +{ + return x; +} + +#elif defined(BADVPN_BIG_ENDIAN) + +static uint16_t hton16 (uint16_t x) +{ + return x; +} + +static uint32_t hton32 (uint32_t x) +{ + return x; +} + +static uint64_t hton64 (uint64_t x) +{ + return x; +} + +static uint16_t htol16 (uint16_t x) +{ + return badvpn_reverse16(x); +} + +static uint32_t htol32 (uint32_t x) +{ + return badvpn_reverse32(x); +} + +static uint64_t htol64 (uint64_t x) +{ + return badvpn_reverse64(x); +} + +#endif + +//static uint8_t ntoh8 (uint8_t x) +//{ +// return hton8(x); +//} +// +//static uint16_t ntoh16 (uint16_t x) +//{ +// return hton16(x); +//} +// +//static uint32_t ntoh32 (uint32_t x) +//{ +// return hton32(x); +//} +// +//static uint64_t ntoh64 (uint64_t x) +//{ +// return hton64(x); +//} +// +//static uint8_t ltoh8 (uint8_t x) +//{ +// return htol8(x); +//} +// +//static uint16_t ltoh16 (uint16_t x) +//{ +// return htol16(x); +//} +// +//static uint32_t ltoh32 (uint32_t x) +//{ +// return htol32(x); +//} +// +//static uint64_t ltoh64 (uint64_t x) +//{ +// return htol64(x); +//} + +#endif diff --git a/Shared/lwip/badvpn/misc/cmdline.h b/Shared/lwip/badvpn/misc/cmdline.h new file mode 100644 index 0000000..396d794 --- /dev/null +++ b/Shared/lwip/badvpn/misc/cmdline.h @@ -0,0 +1,168 @@ +/** + * @file cmdline.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Command line construction functions. + */ + +#ifndef BADVPN_MISC_CMDLINE_H +#define BADVPN_MISC_CMDLINE_H + +#include +#include + +#include +#include +#include +#include + +typedef struct { + struct ExpArray arr; + size_t n; +} CmdLine; + +static int CmdLine_Init (CmdLine *c); +static void CmdLine_Free (CmdLine *c); +static int CmdLine_Append (CmdLine *c, const char *str); +static int CmdLine_AppendNoNull (CmdLine *c, const char *str, size_t str_len); +static int CmdLine_AppendNoNullMr (CmdLine *c, MemRef mr); +static int CmdLine_AppendMulti (CmdLine *c, int num, ...); +static int CmdLine_Finish (CmdLine *c); +static char ** CmdLine_Get (CmdLine *c); + +static int _CmdLine_finished (CmdLine *c) +{ + return (c->n > 0 && ((char **)c->arr.v)[c->n - 1] == NULL); +} + +int CmdLine_Init (CmdLine *c) +{ + if (!ExpArray_init(&c->arr, sizeof(char *), 16)) { + return 0; + } + + c->n = 0; + + return 1; +} + +void CmdLine_Free (CmdLine *c) +{ + for (size_t i = 0; i < c->n; i++) { + free(((char **)c->arr.v)[i]); + } + + free(c->arr.v); +} + +int CmdLine_Append (CmdLine *c, const char *str) +{ + ASSERT(str) + ASSERT(!_CmdLine_finished(c)) + + if (!ExpArray_resize(&c->arr, c->n + 1)) { + return 0; + } + + if (!(((char **)c->arr.v)[c->n] = strdup(str))) { + return 0; + } + + c->n++; + + return 1; +} + +int CmdLine_AppendNoNull (CmdLine *c, const char *str, size_t str_len) +{ + ASSERT(str) + ASSERT(!memchr(str, '\0', str_len)) + ASSERT(!_CmdLine_finished(c)) + + if (!ExpArray_resize(&c->arr, c->n + 1)) { + return 0; + } + + if (!(((char **)c->arr.v)[c->n] = b_strdup_bin(str, str_len))) { + return 0; + } + + c->n++; + + return 1; +} + +int CmdLine_AppendNoNullMr (CmdLine *c, MemRef mr) +{ + return CmdLine_AppendNoNull(c, mr.ptr, mr.len); +} + +int CmdLine_AppendMulti (CmdLine *c, int num, ...) +{ + int res = 1; + + va_list vl; + va_start(vl, num); + + for (int i = 0; i < num; i++) { + const char *str = va_arg(vl, const char *); + if (!CmdLine_Append(c, str)) { + res = 0; + break; + } + } + + va_end(vl); + + return res; +} + +int CmdLine_Finish (CmdLine *c) +{ + ASSERT(!_CmdLine_finished(c)) + + if (!ExpArray_resize(&c->arr, c->n + 1)) { + return 0; + } + + ((char **)c->arr.v)[c->n] = NULL; + + c->n++; + + return 1; +} + +char ** CmdLine_Get (CmdLine *c) +{ + ASSERT(_CmdLine_finished(c)) + + return (char **)c->arr.v; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/compare.h b/Shared/lwip/badvpn/misc/compare.h new file mode 100644 index 0000000..8d1a1b9 --- /dev/null +++ b/Shared/lwip/badvpn/misc/compare.h @@ -0,0 +1,37 @@ +/** + * @file compare.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_COMPARE_H +#define BADVPN_COMPARE_H + +#define B_COMPARE(a, b) (((a) > (b)) - ((a) < (b))) +#define B_COMPARE_COMBINE(cmp1, cmp2) ((cmp1) ? (cmp1) : (cmp2)) +#define B_COMPARE2(a, b, c, d) B_COMPARE_COMBINE(B_COMPARE((a), (b)), B_COMPARE((c), (d))) + +#endif diff --git a/Shared/lwip/badvpn/misc/concat_strings.h b/Shared/lwip/badvpn/misc/concat_strings.h new file mode 100644 index 0000000..30330bc --- /dev/null +++ b/Shared/lwip/badvpn/misc/concat_strings.h @@ -0,0 +1,85 @@ +/** + * @file concat_strings.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Function for concatenating strings. + */ + +#ifndef BADVPN_MISC_CONCAT_STRINGS_H +#define BADVPN_MISC_CONCAT_STRINGS_H + +#include +#include +#include + +#include + +static char * concat_strings (int num, ...) +{ + ASSERT(num >= 0) + + // calculate sum of lengths + size_t sum = 0; + va_list ap; + va_start(ap, num); + for (int i = 0; i < num; i++) { + const char *str = va_arg(ap, const char *); + size_t str_len = strlen(str); + if (str_len > SIZE_MAX - 1 - sum) { + va_end(ap); + return NULL; + } + sum += str_len; + } + va_end(ap); + + // allocate memory + char *res_str = (char *)malloc(sum + 1); + if (!res_str) { + return NULL; + } + + // copy strings + sum = 0; + va_start(ap, num); + for (int i = 0; i < num; i++) { + const char *str = va_arg(ap, const char *); + size_t str_len = strlen(str); + memcpy(res_str + sum, str, str_len); + sum += str_len; + } + va_end(ap); + + // terminate + res_str[sum] = '\0'; + + return res_str; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/dead.h b/Shared/lwip/badvpn/misc/dead.h new file mode 100644 index 0000000..7f57421 --- /dev/null +++ b/Shared/lwip/badvpn/misc/dead.h @@ -0,0 +1,134 @@ +/** + * @file dead.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Dead mechanism definitions. + * + * The dead mechanism is a way for a piece of code to detect whether some + * specific event has occured during some operation (usually during calling + * a user-provided handler function), without requiring access to memory + * that might no longer be available because of the event. + * + * It works somehow like that: + * + * First a dead variable ({@link dead_t}) is allocated somewhere, and + * initialized with {@link DEAD_INIT}, e.g.: + * DEAD_INIT(dead); + * + * When the event that needs to be caught occurs, {@link DEAD_KILL} is + * called, e.g.: + * DEAD_KILL(dead); + * The memory used by the dead variable is no longer needed after + * that. + * + * If a piece of code needs to know whether the event occured during some + * operation (but it must not have occured before!), it puts {@link DEAD_ENTER}} + * in front of the operation, and does {@link DEAD_LEAVE} at the end. If + * {@link DEAD_LEAVE} returned nonzero, the event occured, otherwise it did + * not. Example: + * DEAD_ENTER(dead) + * HandlerFunction(); + * if (DEAD_LEAVE(dead)) { + * (event occured) + * } + * + * If is is needed to check for the event more than once in a single block, + * {@link DEAD_DECLARE} should be put somewhere before, and {@link DEAD_ENTER2} + * should be used instead of {@link DEAD_ENTER}. + * + * If it is needed to check for multiple events (dead variables) at the same + * time, DEAD_*_N macros should be used instead, specifying different + * identiers as the first argument for different dead variables. + */ + +#ifndef BADVPN_MISC_DEAD_H +#define BADVPN_MISC_DEAD_H + +#include + +/** + * Dead variable. + */ +typedef int *dead_t; + +/** + * Initializes a dead variable. + */ +#define DEAD_INIT(ptr) { ptr = NULL; } + +/** + * Kills the dead variable, + */ +#define DEAD_KILL(ptr) { if (ptr) *(ptr) = 1; } + +/** + * Kills the dead variable with the given value, or does nothing + * if the value is 0. The value will seen by {@link DEAD_KILLED}. + */ +#define DEAD_KILL_WITH(ptr, val) { if (ptr) *(ptr) = (val); } + +/** + * Declares dead catching variables. + */ +#define DEAD_DECLARE int badvpn__dead; dead_t badvpn__prev_ptr; + +/** + * Enters a dead catching using already declared dead catching variables. + * The dead variable must have been initialized with {@link DEAD_INIT}, + * and {@link DEAD_KILL} must not have been called yet. + * {@link DEAD_LEAVE2} must be called before the current scope is left. + */ +#define DEAD_ENTER2(ptr) { badvpn__dead = 0; badvpn__prev_ptr = ptr; ptr = &badvpn__dead; } + +/** + * Declares dead catching variables and enters a dead catching. + * The dead variable must have been initialized with {@link DEAD_INIT}, + * and {@link DEAD_KILL} must not have been called yet. + * {@link DEAD_LEAVE2} must be called before the current scope is left. + */ +#define DEAD_ENTER(ptr) DEAD_DECLARE DEAD_ENTER2(ptr) + +/** + * Leaves a dead catching. + */ +#define DEAD_LEAVE2(ptr) { if (!badvpn__dead) ptr = badvpn__prev_ptr; if (badvpn__prev_ptr) *badvpn__prev_ptr = badvpn__dead; } + +/** + * Returns 1 if {@link DEAD_KILL} was called for the dead variable, 0 otherwise. + * Must be called after entering a dead catching. + */ +#define DEAD_KILLED (badvpn__dead) + +#define DEAD_DECLARE_N(n) int badvpn__dead##n; dead_t badvpn__prev_ptr##n; +#define DEAD_ENTER2_N(n, ptr) { badvpn__dead##n = 0; badvpn__prev_ptr##n = ptr; ptr = &badvpn__dead##n;} +#define DEAD_ENTER_N(n, ptr) DEAD_DECLARE_N(n) DEAD_ENTER2_N(n, ptr) +#define DEAD_LEAVE2_N(n, ptr) { if (!badvpn__dead##n) ptr = badvpn__prev_ptr##n; if (badvpn__prev_ptr##n) *badvpn__prev_ptr##n = badvpn__dead##n; } +#define DEAD_KILLED_N(n) (badvpn__dead##n) + +#endif diff --git a/Shared/lwip/badvpn/misc/debug.h b/Shared/lwip/badvpn/misc/debug.h new file mode 100644 index 0000000..20a9603 --- /dev/null +++ b/Shared/lwip/badvpn/misc/debug.h @@ -0,0 +1,141 @@ +/** + * @file debug.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Debugging macros. + */ + +/** + * @def DEBUG + * + * Macro for printing debugging text. Use the same way as printf, + * but without a newline. + * Prepends "function_name: " and appends a newline. + */ + +/** + * @def ASSERT_FORCE + * + * Macro for forced assertions. + * Evaluates the argument and terminates the program abnormally + * if the result is false. + */ + +/** + * @def ASSERT + * + * Macro for assertions. + * The argument may or may not be evaluated. + * If the argument is evaluated, it must not evaluate to false. + */ + +/** + * @def ASSERT_EXECUTE + * + * Macro for always-evaluated assertions. + * The argument is evaluated. + * The argument must not evaluate to false. + */ + +/** + * @def DEBUG_ZERO_MEMORY + * + * If debugging is enabled, zeroes the given memory region. + * First argument is pointer to the memory region, second is + * number of bytes. + */ + +/** + * @def WARN_UNUSED + * + * Tells the compiler that the result of a function should not be unused. + * Insert at the end of the declaration of a function before the semicolon. + */ + +/** + * @def B_USE + * + * This can be used to suppress warnings about unused variables. It can + * be applied to a variable or any expression. It does not evaluate the + * expression. + */ + +#ifndef BADVPN_MISC_DEBUG_H +#define BADVPN_MISC_DEBUG_H + +#include +#include +#include +#include +#include + +#define CDEBUG(...) \ + { \ + fprintf(stderr, "%s: ", __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } + +#define ASSERT_FORCE(e) \ + { \ + if (!(e)) { \ + fprintf(stderr, "%s:%d Assertion failed\n", __FILE__, __LINE__); \ + } \ + } + +#ifdef NDEBUG + #define DEBUG_ZERO_MEMORY(buf, len) {} + #define ASSERT(e) {} + #define ASSERT_EXECUTE(e) { (e); } +#else + #define DEBUG_ZERO_MEMORY(buf, len) { memset((buf), 0, (len)); } + #ifdef BADVPN_USE_C_ASSERT + #define ASSERT(e) { assert(e); } + #define ASSERT_EXECUTE(e) \ + { \ + int _assert_res = !!(e); \ + assert(_assert_res); \ + } + #else + #define ASSERT(e) ASSERT_FORCE(e) + #define ASSERT_EXECUTE(e) ASSERT_FORCE(e) + #endif +#endif + +#ifdef __GNUC__ + #define WARN_UNUSED __attribute__((warn_unused_result)) +#else + #define WARN_UNUSED +#endif + +#define B_USE(expr) (void)(sizeof((expr))); + +#define B_ASSERT_USE(expr) { ASSERT(expr) B_USE(expr) } + +#endif diff --git a/Shared/lwip/badvpn/misc/debugcounter.h b/Shared/lwip/badvpn/misc/debugcounter.h new file mode 100644 index 0000000..a8a54a1 --- /dev/null +++ b/Shared/lwip/badvpn/misc/debugcounter.h @@ -0,0 +1,118 @@ +/** + * @file debugcounter.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Counter for detecting leaks. + */ + +#ifndef BADVPN_MISC_DEBUGCOUNTER_H +#define BADVPN_MISC_DEBUGCOUNTER_H + +#include + +#include + +/** + * Counter for detecting leaks. + */ +typedef struct { +#ifndef NDEBUG + int32_t c; +#endif +} DebugCounter; + +#ifndef NDEBUG +#define DEBUGCOUNTER_STATIC { 0 } +#else +#define DEBUGCOUNTER_STATIC {} +#endif + +/** + * Initializes the object. + * The object is initialized with counter value zero. + * + * @param obj the object + */ +static void DebugCounter_Init (DebugCounter *obj) +{ +#ifndef NDEBUG + obj->c = 0; +#endif +} + +/** + * Frees the object. + * This does not have to be called when the counter is no longer needed. + * The counter value must be zero. + * + * @param obj the object + */ +static void DebugCounter_Free (DebugCounter *obj) +{ +#ifndef NDEBUG + ASSERT(obj->c == 0 || obj->c == INT32_MAX) +#endif +} + +/** + * Increments the counter. + * Increments the counter value by one. + * + * @param obj the object + */ +static void DebugCounter_Increment (DebugCounter *obj) +{ +#ifndef NDEBUG + ASSERT(obj->c >= 0) + + if (obj->c != INT32_MAX) { + obj->c++; + } +#endif +} + +/** + * Decrements the counter. + * The counter value must be >0. + * Decrements the counter value by one. + * + * @param obj the object + */ +static void DebugCounter_Decrement (DebugCounter *obj) +{ +#ifndef NDEBUG + ASSERT(obj->c > 0) + + if (obj->c != INT32_MAX) { + obj->c--; + } +#endif +} + +#endif diff --git a/Shared/lwip/badvpn/misc/debugerror.h b/Shared/lwip/badvpn/misc/debugerror.h new file mode 100644 index 0000000..182afd7 --- /dev/null +++ b/Shared/lwip/badvpn/misc/debugerror.h @@ -0,0 +1,90 @@ +/** + * @file debugerror.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Mechanism for ensuring an object is destroyed from inside an error handler + * or its jobs. + */ + +#ifndef BADVPN_MISC_DEBUGERROR_H +#define BADVPN_MISC_DEBUGERROR_H + +#include +#include + +#ifndef NDEBUG + #define DEBUGERROR(de, call) \ + { \ + ASSERT(!BPending_IsSet(&(de)->job)) \ + BPending_Set(&(de)->job); \ + (call); \ + } +#else + #define DEBUGERROR(de, call) { (call); } +#endif + +typedef struct { + #ifndef NDEBUG + BPending job; + #endif +} DebugError; + +static void DebugError_Init (DebugError *o, BPendingGroup *pg); +static void DebugError_Free (DebugError *o); +static void DebugError_AssertNoError (DebugError *o); + +#ifndef NDEBUG +static void _DebugError_job_handler (DebugError *o) +{ + ASSERT(0); +} +#endif + +void DebugError_Init (DebugError *o, BPendingGroup *pg) +{ + #ifndef NDEBUG + BPending_Init(&o->job, pg, (BPending_handler)_DebugError_job_handler, o); + #endif +} + +void DebugError_Free (DebugError *o) +{ + #ifndef NDEBUG + BPending_Free(&o->job); + #endif +} + +void DebugError_AssertNoError (DebugError *o) +{ + #ifndef NDEBUG + ASSERT(!BPending_IsSet(&o->job)) + #endif +} + +#endif diff --git a/Shared/lwip/badvpn/misc/dhcp_proto.h b/Shared/lwip/badvpn/misc/dhcp_proto.h new file mode 100644 index 0000000..ed83544 --- /dev/null +++ b/Shared/lwip/badvpn/misc/dhcp_proto.h @@ -0,0 +1,131 @@ +/** + * @file dhcp_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the DHCP protocol. + */ + +#ifndef BADVPN_MISC_DHCP_PROTO_H +#define BADVPN_MISC_DHCP_PROTO_H + +#include + +#include + +#define DHCP_OP_BOOTREQUEST 1 +#define DHCP_OP_BOOTREPLY 2 + +#define DHCP_HARDWARE_ADDRESS_TYPE_ETHERNET 1 + +#define DHCP_MAGIC 0x63825363 + +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_END 255 + +#define DHCP_OPTION_SUBNET_MASK 1 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DOMAIN_NAME_SERVER 6 +#define DHCP_OPTION_HOST_NAME 12 +#define DHCP_OPTION_REQUESTED_IP_ADDRESS 50 +#define DHCP_OPTION_IP_ADDRESS_LEASE_TIME 51 +#define DHCP_OPTION_DHCP_MESSAGE_TYPE 53 +#define DHCP_OPTION_DHCP_SERVER_IDENTIFIER 54 +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 +#define DHCP_OPTION_MAXIMUM_MESSAGE_SIZE 57 +#define DHCP_OPTION_RENEWAL_TIME_VALUE 58 +#define DHCP_OPTION_REBINDING_TIME_VALUE 59 +#define DHCP_OPTION_VENDOR_CLASS_IDENTIFIER 60 +#define DHCP_OPTION_CLIENT_IDENTIFIER 61 + +#define DHCP_MESSAGE_TYPE_DISCOVER 1 +#define DHCP_MESSAGE_TYPE_OFFER 2 +#define DHCP_MESSAGE_TYPE_REQUEST 3 +#define DHCP_MESSAGE_TYPE_DECLINE 4 +#define DHCP_MESSAGE_TYPE_ACK 5 +#define DHCP_MESSAGE_TYPE_NAK 6 +#define DHCP_MESSAGE_TYPE_RELEASE 7 + +B_START_PACKED +struct dhcp_header { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + uint32_t magic; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct dhcp_option_header { + uint8_t type; + uint8_t len; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct dhcp_option_dhcp_message_type { + uint8_t type; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct dhcp_option_maximum_message_size { + uint16_t size; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct dhcp_option_dhcp_server_identifier { + uint32_t id; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct dhcp_option_time { + uint32_t time; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct dhcp_option_addr { + uint32_t addr; +} B_PACKED; +B_END_PACKED + +#endif diff --git a/Shared/lwip/badvpn/misc/ethernet_proto.h b/Shared/lwip/badvpn/misc/ethernet_proto.h new file mode 100644 index 0000000..6e49e02 --- /dev/null +++ b/Shared/lwip/badvpn/misc/ethernet_proto.h @@ -0,0 +1,52 @@ +/** + * @file ethernet_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the Ethernet protocol. + */ + +#ifndef BADVPN_MISC_ETHERNET_PROTO_H +#define BADVPN_MISC_ETHERNET_PROTO_H + +#include + +#include + +#define ETHERTYPE_IPV4 0x0800 +#define ETHERTYPE_ARP 0x0806 + +B_START_PACKED +struct ethernet_header { + uint8_t dest[6]; + uint8_t source[6]; + uint16_t type; +} B_PACKED; +B_END_PACKED + +#endif diff --git a/Shared/lwip/badvpn/misc/exparray.h b/Shared/lwip/badvpn/misc/exparray.h new file mode 100644 index 0000000..b24149f --- /dev/null +++ b/Shared/lwip/badvpn/misc/exparray.h @@ -0,0 +1,101 @@ +/** + * @file exparray.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Dynamic array which grows exponentionally on demand. + */ + +#ifndef BADVPN_MISC_EXPARRAY_H +#define BADVPN_MISC_EXPARRAY_H + +#include +#include +#include + +#include + +struct ExpArray { + size_t esize; + size_t size; + void *v; +}; + +static int ExpArray_init (struct ExpArray *o, size_t esize, size_t size) +{ + ASSERT(esize > 0) + ASSERT(size > 0) + + o->esize = esize; + o->size = size; + + if (o->size > SIZE_MAX / o->esize) { + return 0; + } + + if (!(o->v = malloc(o->size * o->esize))) { + return 0; + } + + return 1; +} + +static int ExpArray_resize (struct ExpArray *o, size_t size) +{ + ASSERT(size > 0) + + if (size <= o->size) { + return 1; + } + + size_t newsize = o->size; + + while (newsize < size) { + if (2 > SIZE_MAX / newsize) { + return 0; + } + + newsize = 2 * newsize; + } + + if (newsize > SIZE_MAX / o->esize) { + return 0; + } + + void *newarr = realloc(o->v, newsize * o->esize); + if (!newarr) { + return 0; + } + + o->size = newsize; + o->v = newarr; + + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/expstring.h b/Shared/lwip/badvpn/misc/expstring.h new file mode 100644 index 0000000..8081e2f --- /dev/null +++ b/Shared/lwip/badvpn/misc/expstring.h @@ -0,0 +1,174 @@ +/** + * @file expstring.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_MISC_EXPSTRING_H +#define BADVPN_MISC_EXPSTRING_H + +#include + +#include +#include +#include +#include + +typedef struct { + struct ExpArray arr; + size_t n; +} ExpString; + +static int ExpString_Init (ExpString *c); +static void ExpString_Free (ExpString *c); +static int ExpString_Append (ExpString *c, const char *str); +static int ExpString_AppendChar (ExpString *c, char ch); +static int ExpString_AppendByte (ExpString *c, uint8_t x); +static int ExpString_AppendBinary (ExpString *c, const uint8_t *data, size_t len); +static int ExpString_AppendBinaryMr (ExpString *c, MemRef data); +static int ExpString_AppendZeros (ExpString *c, size_t len); +static char * ExpString_Get (ExpString *c); +static size_t ExpString_Length (ExpString *c); +static MemRef ExpString_GetMr (ExpString *c); + +int ExpString_Init (ExpString *c) +{ + if (!ExpArray_init(&c->arr, 1, 16)) { + return 0; + } + + c->n = 0; + ((char *)c->arr.v)[c->n] = '\0'; + + return 1; +} + +void ExpString_Free (ExpString *c) +{ + free(c->arr.v); +} + +int ExpString_Append (ExpString *c, const char *str) +{ + ASSERT(str) + + size_t l = strlen(str); + bsize_t newsize = bsize_add(bsize_fromsize(c->n), bsize_add(bsize_fromsize(l), bsize_fromint(1))); + + if (newsize.is_overflow || !ExpArray_resize(&c->arr, newsize.value)) { + return 0; + } + + memcpy((char *)c->arr.v + c->n, str, l); + c->n += l; + ((char *)c->arr.v)[c->n] = '\0'; + + return 1; +} + +int ExpString_AppendChar (ExpString *c, char ch) +{ + ASSERT(ch != '\0') + + bsize_t newsize = bsize_add(bsize_fromsize(c->n), bsize_fromint(2)); + + if (newsize.is_overflow || !ExpArray_resize(&c->arr, newsize.value)) { + return 0; + } + + ((char *)c->arr.v)[c->n] = ch; + c->n++; + ((char *)c->arr.v)[c->n] = '\0'; + + return 1; +} + +int ExpString_AppendByte (ExpString *c, uint8_t x) +{ + bsize_t newsize = bsize_add(bsize_fromsize(c->n), bsize_fromint(2)); + + if (newsize.is_overflow || !ExpArray_resize(&c->arr, newsize.value)) { + return 0; + } + + ((uint8_t *)c->arr.v)[c->n] = x; + c->n++; + ((char *)c->arr.v)[c->n] = '\0'; + + return 1; +} + +int ExpString_AppendBinary (ExpString *c, const uint8_t *data, size_t len) +{ + bsize_t newsize = bsize_add(bsize_fromsize(c->n), bsize_add(bsize_fromsize(len), bsize_fromint(1))); + + if (newsize.is_overflow || !ExpArray_resize(&c->arr, newsize.value)) { + return 0; + } + + memcpy((char *)c->arr.v + c->n, data, len); + c->n += len; + ((char *)c->arr.v)[c->n] = '\0'; + + return 1; +} + +int ExpString_AppendBinaryMr (ExpString *c, MemRef data) +{ + return ExpString_AppendBinary(c, (uint8_t const *)data.ptr, data.len); +} + +int ExpString_AppendZeros (ExpString *c, size_t len) +{ + bsize_t newsize = bsize_add(bsize_fromsize(c->n), bsize_add(bsize_fromsize(len), bsize_fromint(1))); + + if (newsize.is_overflow || !ExpArray_resize(&c->arr, newsize.value)) { + return 0; + } + + memset((char *)c->arr.v + c->n, 0, len); + c->n += len; + ((char *)c->arr.v)[c->n] = '\0'; + + return 1; +} + +char * ExpString_Get (ExpString *c) +{ + return (char *)c->arr.v; +} + +size_t ExpString_Length (ExpString *c) +{ + return c->n; +} + +MemRef ExpString_GetMr (ExpString *c) +{ + return MemRef_Make((char const *)c->arr.v, c->n); +} + +#endif diff --git a/Shared/lwip/badvpn/misc/find_char.h b/Shared/lwip/badvpn/misc/find_char.h new file mode 100644 index 0000000..9277ac6 --- /dev/null +++ b/Shared/lwip/badvpn/misc/find_char.h @@ -0,0 +1,58 @@ +/** + * @file find_char.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_FIND_CHAR_H +#define BADVPN_FIND_CHAR_H + +#include + +#include + +/** + * Finds the first character 'c' in the string represented by 'str' and 'len'. + * If found, returns 1 and writes the position to *out_pos (if out_pos!=NULL). + * If not found, returns 0 and does not modify *out_pos. + */ +static int b_find_char_bin (const char *str, size_t len, char c, size_t *out_pos) +{ + ASSERT(str) + + for (size_t i = 0; i < len; i++) { + if (str[i] == c) { + if (out_pos) { + *out_pos = i; + } + return 1; + } + } + + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/find_program.h b/Shared/lwip/badvpn/misc/find_program.h new file mode 100644 index 0000000..d381e18 --- /dev/null +++ b/Shared/lwip/badvpn/misc/find_program.h @@ -0,0 +1,103 @@ +/** + * @file find_program.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Function that finds the absolute path of a program by checking a predefined + * list of directories. + */ + +#ifndef BADVPN_FIND_PROGRAM_H +#define BADVPN_FIND_PROGRAM_H + +#include +#include +#include + +#include +#include +#include + +static char * badvpn_find_program (const char *name); + +static char * badvpn_find_program (const char *name) +{ + ASSERT(name) + + char *path = getenv("PATH"); + if (path) { + while (1) { + size_t i = 0; + while (path[i] != ':' && path[i] != '\0') { + i++; + } + char const *src = path; + size_t src_len = i; + if (src_len == 0) { + src = "."; + src_len = 1; + } + size_t name_len = strlen(name); + char *entry = BAllocSize(bsize_add(bsize_fromsize(src_len), bsize_add(bsize_fromsize(name_len), bsize_fromsize(2)))); + if (!entry) { + goto fail; + } + memcpy(entry, src, src_len); + entry[src_len] = '/'; + strcpy(entry + (src_len + 1), name); + if (access(entry, X_OK) == 0) { + return entry; + } + free(entry); + if (path[i] == '\0') { + break; + } + path += i + 1; + } + } + + const char *dirs[] = {"/usr/sbin", "/usr/bin", "/sbin", "/bin", NULL}; + + for (size_t i = 0; dirs[i]; i++) { + char *try_path = concat_strings(3, dirs[i], "/", name); + if (!try_path) { + goto fail; + } + + if (access(try_path, X_OK) == 0) { + return try_path; + } + + free(try_path); + } + +fail: + return NULL; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/get_iface_info.h b/Shared/lwip/badvpn/misc/get_iface_info.h new file mode 100644 index 0000000..190741b --- /dev/null +++ b/Shared/lwip/badvpn/misc/get_iface_info.h @@ -0,0 +1,110 @@ +/** + * @file get_iface_info.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_GETIFACEINFO_H +#define BADVPN_GETIFACEINFO_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + * Returns information about a network interface with the given name. + * + * @param ifname name of interface to get information for + * @param out_mac the MAC address will be returned here, unless NULL + * @param out_mtu the MTU will be returned here, unless NULL + * @param out_ifindex the interface index will be returned here, unless NULL + * @return 1 on success, 0 on failure + */ +static int badvpn_get_iface_info (const char *ifname, uint8_t *out_mac, int *out_mtu, int *out_ifindex) WARN_UNUSED; + + +static int badvpn_get_iface_info (const char *ifname, uint8_t *out_mac, int *out_mtu, int *out_ifindex) +{ + ASSERT(ifname) + + struct ifreq ifr; + + int s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + goto fail0; + } + + // get MAC + if (out_mac) { + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifname); + if (ioctl(s, SIOCGIFHWADDR, &ifr)) { + goto fail1; + } + if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { + goto fail1; + } + memcpy(out_mac, ifr.ifr_hwaddr.sa_data, 6); + } + + // get MTU + if (out_mtu) { + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifname); + if (ioctl(s, SIOCGIFMTU, &ifr)) { + goto fail1; + } + *out_mtu = ifr.ifr_mtu; + } + + // get interface index + if (out_ifindex) { + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifname); + if (ioctl(s, SIOCGIFINDEX, &ifr)) { + goto fail1; + } + *out_ifindex = ifr.ifr_ifindex; + } + + close(s); + + return 1; + +fail1: + close(s); +fail0: + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/grow_array.h b/Shared/lwip/badvpn/misc/grow_array.h new file mode 100644 index 0000000..9a42d04 --- /dev/null +++ b/Shared/lwip/badvpn/misc/grow_array.h @@ -0,0 +1,139 @@ +/** + * @file grow_array.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Preprocessor inputs: +// GROWARRAY_NAME - prefix of of functions to define +// GROWARRAY_OBJECT_TYPE - type of structure where array and capacity sizes are +// GROWARRAY_ARRAY_MEMBER - array member +// GROWARRAY_CAPACITY_MEMBER - capacity member +// GROWARRAY_MAX_CAPACITY - max value of capacity member + +#include +#include +#include + +#include +#include +#include + +#define GrowArrayObject GROWARRAY_OBJECT_TYPE +#define GrowArray_Init MERGE(GROWARRAY_NAME, _Init) +#define GrowArray_InitEmpty MERGE(GROWARRAY_NAME, _InitEmpty) +#define GrowArray_Free MERGE(GROWARRAY_NAME, _Free) +#define GrowArray_DoubleUp MERGE(GROWARRAY_NAME, _DoubleUp) +#define GrowArray_DoubleUpLimit MERGE(GROWARRAY_NAME, _DoubleUpLimit) + +static int GrowArray_Init (GrowArrayObject *o, size_t capacity) WARN_UNUSED; +static void GrowArray_InitEmpty (GrowArrayObject *o); +static void GrowArray_Free (GrowArrayObject *o); +static int GrowArray_DoubleUp (GrowArrayObject *o) WARN_UNUSED; +static int GrowArray_DoubleUpLimit (GrowArrayObject *o, size_t limit) WARN_UNUSED; + +static int GrowArray_Init (GrowArrayObject *o, size_t capacity) +{ + if (capacity > GROWARRAY_MAX_CAPACITY) { + return 0; + } + + if (capacity == 0) { + o->GROWARRAY_ARRAY_MEMBER = NULL; + } else { + if (!(o->GROWARRAY_ARRAY_MEMBER = BAllocArray(capacity, sizeof(o->GROWARRAY_ARRAY_MEMBER[0])))) { + return 0; + } + } + + o->GROWARRAY_CAPACITY_MEMBER = capacity; + + return 1; +} + +static void GrowArray_InitEmpty (GrowArrayObject *o) +{ + o->GROWARRAY_ARRAY_MEMBER = NULL; + o->GROWARRAY_CAPACITY_MEMBER = 0; +} + +static void GrowArray_Free (GrowArrayObject *o) +{ + if (o->GROWARRAY_ARRAY_MEMBER) { + BFree(o->GROWARRAY_ARRAY_MEMBER); + } +} + +static int GrowArray_DoubleUp (GrowArrayObject *o) +{ + return GrowArray_DoubleUpLimit(o, SIZE_MAX); +} + +static int GrowArray_DoubleUpLimit (GrowArrayObject *o, size_t limit) +{ + if (o->GROWARRAY_CAPACITY_MEMBER > SIZE_MAX / 2 || o->GROWARRAY_CAPACITY_MEMBER > GROWARRAY_MAX_CAPACITY / 2) { + return 0; + } + + size_t newcap = 2 * o->GROWARRAY_CAPACITY_MEMBER; + if (newcap == 0) { + newcap = 1; + } + + if (newcap > limit) { + newcap = limit; + if (newcap == o->GROWARRAY_CAPACITY_MEMBER) { + return 0; + } + } + + void *newarr = BAllocArray(newcap, sizeof(o->GROWARRAY_ARRAY_MEMBER[0])); + if (!newarr) { + return 0; + } + + memcpy(newarr, o->GROWARRAY_ARRAY_MEMBER, o->GROWARRAY_CAPACITY_MEMBER * sizeof(o->GROWARRAY_ARRAY_MEMBER[0])); + + BFree(o->GROWARRAY_ARRAY_MEMBER); + + o->GROWARRAY_ARRAY_MEMBER = newarr; + o->GROWARRAY_CAPACITY_MEMBER = newcap; + + return 1; +} + +#undef GROWARRAY_NAME +#undef GROWARRAY_OBJECT_TYPE +#undef GROWARRAY_ARRAY_MEMBER +#undef GROWARRAY_CAPACITY_MEMBER +#undef GROWARRAY_MAX_CAPACITY + +#undef GrowArrayObject +#undef GrowArray_Init +#undef GrowArray_InitEmpty +#undef GrowArray_Free +#undef GrowArray_DoubleUp +#undef GrowArray_DoubleUpLimit diff --git a/Shared/lwip/badvpn/misc/hashfun.h b/Shared/lwip/badvpn/misc/hashfun.h new file mode 100644 index 0000000..5e8956a --- /dev/null +++ b/Shared/lwip/badvpn/misc/hashfun.h @@ -0,0 +1,60 @@ +/** + * @file hashfun.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_HASHFUN_H +#define BADVPN_HASHFUN_H + +#include +#include + +static size_t badvpn_djb2_hash (const uint8_t *str) +{ + size_t hash = 5381; + int c; + + while (c = *str++) { + hash = ((hash << 5) + hash) + c; + } + + return hash; +} + +static size_t badvpn_djb2_hash_bin (const uint8_t *str, size_t str_len) +{ + size_t hash = 5381; + + while (str_len-- > 0) { + int c = *str++; + hash = ((hash << 5) + hash) + c; + } + + return hash; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/igmp_proto.h b/Shared/lwip/badvpn/misc/igmp_proto.h new file mode 100644 index 0000000..9188ea0 --- /dev/null +++ b/Shared/lwip/badvpn/misc/igmp_proto.h @@ -0,0 +1,97 @@ +/** + * @file igmp_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the IGMP protocol. + */ + +#ifndef BADVPN_MISC_IGMP_PROTO_H +#define BADVPN_MISC_IGMP_PROTO_H + +#include + +#include + +#define IGMP_TYPE_MEMBERSHIP_QUERY 0x11 +#define IGMP_TYPE_V1_MEMBERSHIP_REPORT 0x12 +#define IGMP_TYPE_V2_MEMBERSHIP_REPORT 0x16 +#define IGMP_TYPE_V3_MEMBERSHIP_REPORT 0x22 +#define IGMP_TYPE_V2_LEAVE_GROUP 0x17 + +#define IGMP_RECORD_TYPE_MODE_IS_INCLUDE 1 +#define IGMP_RECORD_TYPE_MODE_IS_EXCLUDE 2 +#define IGMP_RECORD_TYPE_CHANGE_TO_INCLUDE_MODE 3 +#define IGMP_RECORD_TYPE_CHANGE_TO_EXCLUDE_MODE 4 + +B_START_PACKED +struct igmp_source { + uint32_t addr; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct igmp_base { + uint8_t type; + uint8_t max_resp_code; + uint16_t checksum; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct igmp_v3_query_extra { + uint32_t group; + uint8_t reserved4_suppress1_qrv3; + uint8_t qqic; + uint16_t number_of_sources; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct igmp_v3_report_extra { + uint16_t reserved; + uint16_t number_of_group_records; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct igmp_v3_report_record { + uint8_t type; + uint8_t aux_data_len; + uint16_t number_of_sources; + uint32_t group; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct igmp_v2_extra { + uint32_t group; +} B_PACKED; +B_END_PACKED + +#endif diff --git a/Shared/lwip/badvpn/misc/ipaddr.h b/Shared/lwip/badvpn/misc/ipaddr.h new file mode 100644 index 0000000..6de5852 --- /dev/null +++ b/Shared/lwip/badvpn/misc/ipaddr.h @@ -0,0 +1,201 @@ +/** + * @file ipaddr.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * IP address parsing functions. + */ + +#ifndef BADVPN_MISC_IPADDR_H +#define BADVPN_MISC_IPADDR_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +struct ipv4_ifaddr { + uint32_t addr; + int prefix; +}; + +static int ipaddr_parse_ipv4_addr (MemRef name, uint32_t *out_addr); +static int ipaddr_parse_ipv4_prefix (MemRef str, int *num); +static int ipaddr_parse_ipv4_ifaddr (MemRef str, struct ipv4_ifaddr *out); +static int ipaddr_ipv4_ifaddr_from_addr_mask (uint32_t addr, uint32_t mask, struct ipv4_ifaddr *out); +static uint32_t ipaddr_ipv4_mask_from_prefix (int prefix); +static int ipaddr_ipv4_prefix_from_mask (uint32_t mask, int *out_prefix); +static int ipaddr_ipv4_addrs_in_network (uint32_t addr1, uint32_t addr2, int netprefix); + +#define IPADDR_PRINT_MAX 19 + +static void ipaddr_print_addr (uint32_t addr, char *out); +static void ipaddr_print_ifaddr (struct ipv4_ifaddr ifaddr, char *out); + +int ipaddr_parse_ipv4_addr (MemRef name, uint32_t *out_addr) +{ + for (size_t i = 0; ; i++) { + size_t j; + for (j = 0; j < name.len && name.ptr[j] != '.'; j++); + + if ((j == name.len && i < 3) || (j < name.len && i == 3)) { + return 0; + } + + if (j < 1 || j > 3) { + return 0; + } + + uintmax_t d; + if (!parse_unsigned_integer(MemRef_SubTo(name, j), &d)) { + return 0; + } + + if (d > 255) { + return 0; + } + + ((uint8_t *)out_addr)[i] = d; + + if (i == 3) { + return 1; + } + + name.ptr += j + 1; + name.len -= j + 1; + } +} + +int ipaddr_parse_ipv4_prefix (MemRef str, int *num) +{ + uintmax_t d; + if (!parse_unsigned_integer(str, &d)) { + return 0; + } + if (d > 32) { + return 0; + } + + *num = d; + return 1; +} + +int ipaddr_parse_ipv4_ifaddr (MemRef str, struct ipv4_ifaddr *out) +{ + size_t slash_pos; + if (!MemRef_FindChar(str, '/', &slash_pos)) { + return 0; + } + + return (ipaddr_parse_ipv4_addr(MemRef_SubTo(str, slash_pos), &out->addr) && + ipaddr_parse_ipv4_prefix(MemRef_SubFrom(str, slash_pos + 1), &out->prefix)); +} + +int ipaddr_ipv4_ifaddr_from_addr_mask (uint32_t addr, uint32_t mask, struct ipv4_ifaddr *out) +{ + int prefix; + if (!ipaddr_ipv4_prefix_from_mask(mask, &prefix)) { + return 0; + } + + out->addr = addr; + out->prefix = prefix; + return 1; +} + +uint32_t ipaddr_ipv4_mask_from_prefix (int prefix) +{ + ASSERT(prefix >= 0) + ASSERT(prefix <= 32) + + uint32_t t = 0; + for (int i = 0; i < prefix; i++) { + t |= 1 << (32 - i - 1); + } + + return hton32(t); +} + +int ipaddr_ipv4_prefix_from_mask (uint32_t mask, int *out_prefix) +{ + uint32_t t = 0; + int i; + for (i = 0; i <= 32; i++) { + if (ntoh32(mask) == t) { + break; + } + if (i < 32) { + t |= (1 << (32 - i - 1)); + } + } + if (!(i <= 32)) { + return 0; + } + + *out_prefix = i; + return 1; +} + +int ipaddr_ipv4_addrs_in_network (uint32_t addr1, uint32_t addr2, int netprefix) +{ + ASSERT(netprefix >= 0) + ASSERT(netprefix <= 32) + + uint32_t mask = ipaddr_ipv4_mask_from_prefix(netprefix); + + return !!((addr1 & mask) == (addr2 & mask)); +} + +void ipaddr_print_addr (uint32_t addr, char *out) +{ + ASSERT(out) + + uint8_t *b = (uint8_t *)&addr; + + sprintf(out, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8, + b[0], b[1], b[2], b[3]); +} + +void ipaddr_print_ifaddr (struct ipv4_ifaddr ifaddr, char *out) +{ + ASSERT(ifaddr.prefix >= 0) + ASSERT(ifaddr.prefix <= 32) + ASSERT(out) + + uint8_t *b = (uint8_t *)&ifaddr.addr; + + sprintf(out, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"/%d", + b[0], b[1], b[2], b[3], ifaddr.prefix); +} + +#endif diff --git a/Shared/lwip/badvpn/misc/ipaddr6.h b/Shared/lwip/badvpn/misc/ipaddr6.h new file mode 100644 index 0000000..2b25013 --- /dev/null +++ b/Shared/lwip/badvpn/misc/ipaddr6.h @@ -0,0 +1,383 @@ +/** + * @file ipaddr6.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * IPv6 address parsing functions. + */ + +#ifndef BADVPN_MISC_IPADDR6_H +#define BADVPN_MISC_IPADDR6_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct ipv6_addr { + uint8_t bytes[16]; +}; + +struct ipv6_ifaddr { + struct ipv6_addr addr; + int prefix; +}; + +static int ipaddr6_parse_ipv6_addr (MemRef name, struct ipv6_addr *out_addr); +static int ipaddr6_parse_ipv6_prefix (MemRef str, int *out_num); +static int ipaddr6_parse_ipv6_ifaddr (MemRef str, struct ipv6_ifaddr *out); +static int ipaddr6_ipv6_ifaddr_from_addr_mask (struct ipv6_addr addr, struct ipv6_addr mask, struct ipv6_ifaddr *out); +static void ipaddr6_ipv6_mask_from_prefix (int prefix, struct ipv6_addr *out_mask); +static int ipaddr6_ipv6_prefix_from_mask (struct ipv6_addr mask, int *out_prefix); +static int ipaddr6_ipv6_addrs_in_network (struct ipv6_addr addr1, struct ipv6_addr addr2, int netprefix); + +#define IPADDR6_PRINT_MAX 44 + +static void ipaddr6_print_addr (struct ipv6_addr addr, char *out_buf); +static void ipaddr6_print_ifaddr (struct ipv6_ifaddr addr, char *out_buf); + +int ipaddr6_parse_ipv6_addr (MemRef name, struct ipv6_addr *out_addr) +{ + int num_blocks = 0; + int compress_pos = -1; + uint16_t block = 0; + int empty = 1; + + size_t i = 0; + + while (i < name.len) { + if (name.ptr[i] == '.') { + goto ipv4_ending; + } else if (name.ptr[i] == ':') { + int is_double = (i + 1 < name.len && name.ptr[i + 1] == ':'); + + if (i > 0) { + if (empty || num_blocks == 7) { + return 0; + } + out_addr->bytes[2 * num_blocks + 0] = block >> 8; + out_addr->bytes[2 * num_blocks + 1] = block & 0xFF; + num_blocks++; + block = 0; + empty = 1; + } + else if (!is_double) { + return 0; + } + + if (is_double) { + if (compress_pos != -1) { + return 0; + } + compress_pos = num_blocks; + } + + i += 1 + is_double; + } else { + int digit = decode_hex_digit(name.ptr[i]); + if (digit < 0) { + return 0; + } + if (block > UINT16_MAX / 16) { + return 0; + } + block *= 16; + if (digit > UINT16_MAX - block) { + return 0; + } + block += digit; + empty = 0; + i += 1; + } + } + + if (!empty) { + out_addr->bytes[2 * num_blocks + 0] = block >> 8; + out_addr->bytes[2 * num_blocks + 1] = block & 0xFF; + num_blocks++; + } + else if (num_blocks != compress_pos) { + return 0; + } + +ipv4_done: + if (compress_pos == -1) { + if (num_blocks != 8) { + return 0; + } + compress_pos = 0; + } + + int num_rear = num_blocks - compress_pos; + memmove(out_addr->bytes + 2 * (8 - num_rear), out_addr->bytes + 2 * compress_pos, 2 * num_rear); + memset(out_addr->bytes + 2 * compress_pos, 0, 2 * (8 - num_rear - compress_pos)); + + return 1; + +ipv4_ending: + if (empty || (num_blocks == 0 && compress_pos == -1)) { + return 0; + } + + while (name.ptr[i - 1] != ':') { + i--; + } + + uint8_t bytes[4]; + int cur_byte = 0; + uint8_t byte = 0; + empty = 1; + + while (i < name.len) { + if (name.ptr[i] == '.') { + if (empty || cur_byte == 3) { + return 0; + } + bytes[cur_byte] = byte; + cur_byte++; + byte = 0; + empty = 1; + } else { + if (!empty && byte == 0) { + return 0; + } + int digit = decode_decimal_digit(name.ptr[i]); + if (digit < 0) { + return 0; + } + if (byte > UINT8_MAX / 10) { + return 0; + } + byte *= 10; + if (digit > UINT8_MAX - byte) { + return 0; + } + byte += digit; + empty = 0; + } + i++; + } + + if (cur_byte != 3 || empty) { + return 0; + } + bytes[cur_byte] = byte; + + if (8 - num_blocks < 2) { + return 0; + } + memcpy(out_addr->bytes + 2 * num_blocks, bytes, 4); + num_blocks += 2; + + goto ipv4_done; +} + +int ipaddr6_parse_ipv6_prefix (MemRef str, int *out_num) +{ + uintmax_t d; + if (!parse_unsigned_integer(str, &d)) { + return 0; + } + if (d > 128) { + return 0; + } + + *out_num = d; + return 1; +} + +int ipaddr6_parse_ipv6_ifaddr (MemRef str, struct ipv6_ifaddr *out) +{ + size_t slash_pos; + if (!MemRef_FindChar(str, '/', &slash_pos)) { + return 0; + } + + return (ipaddr6_parse_ipv6_addr(MemRef_SubTo(str, slash_pos), &out->addr) && + ipaddr6_parse_ipv6_prefix(MemRef_SubFrom(str, slash_pos + 1), &out->prefix)); +} + +int ipaddr6_ipv6_ifaddr_from_addr_mask (struct ipv6_addr addr, struct ipv6_addr mask, struct ipv6_ifaddr *out) +{ + int prefix; + if (!ipaddr6_ipv6_prefix_from_mask(mask, &prefix)) { + return 0; + } + + out->addr = addr; + out->prefix = prefix; + return 1; +} + +void ipaddr6_ipv6_mask_from_prefix (int prefix, struct ipv6_addr *out_mask) +{ + ASSERT(prefix >= 0) + ASSERT(prefix <= 128) + + int quot = prefix / 8; + int rem = prefix % 8; + + if (quot > 0) { + memset(out_mask->bytes, UINT8_MAX, quot); + } + if (16 - quot > 0) { + memset(out_mask->bytes + quot, 0, 16 - quot); + } + + for (int i = 0; i < rem; i++) { + out_mask->bytes[quot] |= (uint8_t)1 << (8 - i - 1); + } +} + +int ipaddr6_ipv6_prefix_from_mask (struct ipv6_addr mask, int *out_prefix) +{ + int prefix = 0; + int i = 0; + + while (i < 16 && mask.bytes[i] == UINT8_MAX) { + prefix += 8; + i++; + } + + if (i < 16) { + uint8_t t = 0; + int j; + for (j = 0; j <= 8; j++) { + if (mask.bytes[i] == t) { + break; + } + if (j < 8) { + t |= ((uint8_t)1 << (8 - j - 1)); + } + } + if (!(j <= 8)) { + return 0; + } + + prefix += j; + i++; + + while (i < 16) { + if (mask.bytes[i] != 0) { + return 0; + } + i++; + } + } + + *out_prefix = prefix; + return 1; +} + +int ipaddr6_ipv6_addrs_in_network (struct ipv6_addr addr1, struct ipv6_addr addr2, int netprefix) +{ + ASSERT(netprefix >= 0) + ASSERT(netprefix <= 128) + + int quot = netprefix / 8; + int rem = netprefix % 8; + + if (memcmp(addr1.bytes, addr2.bytes, quot)) { + return 0; + } + + if (rem == 0) { + return 1; + } + + uint8_t t = 0; + for (int i = 0; i < rem; i++) { + t |= (uint8_t)1 << (8 - i - 1); + } + + return ((addr1.bytes[quot] & t) == (addr2.bytes[quot] & t)); +} + +void ipaddr6_print_addr (struct ipv6_addr addr, char *out_buf) +{ + int largest_start = 0; + int largest_len = 0; + int current_start = 0; + int current_len = 0; + + for (int i = 0; i < 8; i++) { + if (addr.bytes[2 * i] == 0 && addr.bytes[2 * i + 1] == 0) { + current_len++; + if (current_len > largest_len) { + largest_start = current_start; + largest_len = current_len; + } + } else { + current_start = i + 1; + current_len = 0; + } + } + + if (largest_len > 1) { + for (int i = 0; i < largest_start; i++) { + uint16_t block = ((uint16_t)addr.bytes[2 * i] << 8) | addr.bytes[2 * i + 1]; + out_buf += sprintf(out_buf, "%"PRIx16":", block); + } + if (largest_start == 0) { + out_buf += sprintf(out_buf, ":"); + } + + for (int i = largest_start + largest_len; i < 8; i++) { + uint16_t block = ((uint16_t)addr.bytes[2 * i] << 8) | addr.bytes[2 * i + 1]; + out_buf += sprintf(out_buf, ":%"PRIx16, block); + } + if (largest_start + largest_len == 8) { + out_buf += sprintf(out_buf, ":"); + } + } else { + const char *prefix = ""; + for (int i = 0; i < 8; i++) { + uint16_t block = ((uint16_t)addr.bytes[2 * i] << 8) | addr.bytes[2 * i + 1]; + out_buf += sprintf(out_buf, "%s%"PRIx16, prefix, block); + prefix = ":"; + } + } +} + +void ipaddr6_print_ifaddr (struct ipv6_ifaddr addr, char *out_buf) +{ + ASSERT(addr.prefix >= 0) + ASSERT(addr.prefix <= 128) + + ipaddr6_print_addr(addr.addr, out_buf); + sprintf(out_buf + strlen(out_buf), "/%d", addr.prefix); +} + +#endif diff --git a/Shared/lwip/badvpn/misc/ipv4_proto.h b/Shared/lwip/badvpn/misc/ipv4_proto.h new file mode 100644 index 0000000..fea7260 --- /dev/null +++ b/Shared/lwip/badvpn/misc/ipv4_proto.h @@ -0,0 +1,145 @@ +/** + * @file ipv4_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the IPv4 protocol. + */ + +#ifndef BADVPN_MISC_IPV4_PROTO_H +#define BADVPN_MISC_IPV4_PROTO_H + +#include +#include + +#include +#include +#include +#include + +#define IPV4_PROTOCOL_IGMP 2 +#define IPV4_PROTOCOL_UDP 17 + +B_START_PACKED +struct ipv4_header { + uint8_t version4_ihl4; + uint8_t ds; + uint16_t total_length; + // + uint16_t identification; + uint16_t flags3_fragmentoffset13; + // + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + // + uint32_t source_address; + // + uint32_t destination_address; +} B_PACKED; +B_END_PACKED + +#define IPV4_GET_VERSION(_header) (((_header).version4_ihl4&0xF0)>>4) +#define IPV4_GET_IHL(_header) (((_header).version4_ihl4&0x0F)>>0) + +#define IPV4_MAKE_VERSION_IHL(size) (((size)/4) + (4 << 4)) + +static uint16_t ipv4_checksum (const struct ipv4_header *header, const char *extra, uint16_t extra_len) +{ + ASSERT(extra_len % 2 == 0) + ASSERT(extra_len == 0 || extra) + + uint32_t t = 0; + + for (uint16_t i = 0; i < sizeof(*header) / 2; i++) { + t += badvpn_read_be16((const char *)header + 2 * i); + } + + for (uint16_t i = 0; i < extra_len / 2; i++) { + t += badvpn_read_be16((const char *)extra + 2 * i); + } + + while (t >> 16) { + t = (t & 0xFFFF) + (t >> 16); + } + + return hton16(~t); +} + +static int ipv4_check (uint8_t *data, int data_len, struct ipv4_header *out_header, uint8_t **out_payload, int *out_payload_len) +{ + ASSERT(data_len >= 0) + ASSERT(out_header) + ASSERT(out_payload) + ASSERT(out_payload_len) + + // check base header + if (data_len < sizeof(struct ipv4_header)) { + return 0; + } + memcpy(out_header, data, sizeof(*out_header)); + + // check version + if (IPV4_GET_VERSION(*out_header) != 4) { + return 0; + } + + // check options + uint16_t header_len = IPV4_GET_IHL(*out_header) * 4; + if (header_len < sizeof(struct ipv4_header)) { + return 0; + } + if (header_len > data_len) { + return 0; + } + + // check total length + uint16_t total_length = ntoh16(out_header->total_length); + if (total_length < header_len) { + return 0; + } + if (total_length > data_len) { + return 0; + } + + // check checksum + uint16_t checksum_in_packet = out_header->checksum; + out_header->checksum = hton16(0); + uint16_t checksum_computed = ipv4_checksum(out_header, (char *)data + sizeof(*out_header), header_len - sizeof(*out_header)); + out_header->checksum = checksum_in_packet; + if (checksum_in_packet != checksum_computed) { + return 0; + } + + *out_payload = data + header_len; + *out_payload_len = total_length - header_len; + + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/ipv6_proto.h b/Shared/lwip/badvpn/misc/ipv6_proto.h new file mode 100644 index 0000000..b255541 --- /dev/null +++ b/Shared/lwip/badvpn/misc/ipv6_proto.h @@ -0,0 +1,86 @@ +/** + * @file ipv6_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_IPV6_PROTO_H +#define BADVPN_IPV6_PROTO_H + +#include +#include + +#include +#include +#include + +#define IPV6_NEXT_IGMP 2 +#define IPV6_NEXT_UDP 17 + +B_START_PACKED +struct ipv6_header { + uint8_t version4_tc4; + uint8_t tc4_fl4; + uint16_t fl; + uint16_t payload_length; + uint8_t next_header; + uint8_t hop_limit; + uint8_t source_address[16]; + uint8_t destination_address[16]; +} B_PACKED; +B_END_PACKED + +static int ipv6_check (uint8_t *data, int data_len, struct ipv6_header *out_header, uint8_t **out_payload, int *out_payload_len) +{ + ASSERT(data_len >= 0) + ASSERT(out_header) + ASSERT(out_payload) + ASSERT(out_payload_len) + + // check base header + if (data_len < sizeof(struct ipv6_header)) { + return 0; + } + memcpy(out_header, data, sizeof(*out_header)); + + // check version + if ((ntoh8(out_header->version4_tc4) >> 4) != 6) { + return 0; + } + + // check payload length + uint16_t payload_length = ntoh16(out_header->payload_length); + if (payload_length > data_len - sizeof(struct ipv6_header)) { + return 0; + } + + *out_payload = data + sizeof(struct ipv6_header); + *out_payload_len = payload_length; + + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/loggers_string.h b/Shared/lwip/badvpn/misc/loggers_string.h new file mode 100644 index 0000000..66986b8 --- /dev/null +++ b/Shared/lwip/badvpn/misc/loggers_string.h @@ -0,0 +1,43 @@ +/** + * @file loggers_string.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * List of available loggers. + */ + +#ifndef BADVPN_MISC_LOGGERSSTRING_H +#define BADVPN_MISC_LOGGERSSTRING_H + +#ifdef BADVPN_USE_WINAPI +#define LOGGERS_STRING "stdout" +#else +#define LOGGERS_STRING "stdout/syslog" +#endif + +#endif diff --git a/Shared/lwip/badvpn/misc/loglevel.h b/Shared/lwip/badvpn/misc/loglevel.h new file mode 100644 index 0000000..6e9f911 --- /dev/null +++ b/Shared/lwip/badvpn/misc/loglevel.h @@ -0,0 +1,80 @@ +/** + * @file loglevel.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Log level specification parsing function. + */ + +#ifndef BADVPN_MISC_LOGLEVEL_H +#define BADVPN_MISC_LOGLEVEL_H + +#include + +#include + +/** + * Parses the log level string. + * + * @param str log level string. Recognizes none, error, warning, notice, + * info, debug. + * @return 0 for none, one of BLOG_* for some log level, -1 for unrecognized + */ +static int parse_loglevel (char *str); + +int parse_loglevel (char *str) +{ + if (!strcmp(str, "none")) { + return 0; + } + if (!strcmp(str, "error")) { + return BLOG_ERROR; + } + if (!strcmp(str, "warning")) { + return BLOG_WARNING; + } + if (!strcmp(str, "notice")) { + return BLOG_NOTICE; + } + if (!strcmp(str, "info")) { + return BLOG_INFO; + } + if (!strcmp(str, "debug")) { + return BLOG_DEBUG; + } + + char *endptr; + long int res = strtol(str, &endptr, 10); + if (*str && !*endptr && res >= 0 && res <= BLOG_DEBUG) { + return res; + } + + return -1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/maxalign.h b/Shared/lwip/badvpn/misc/maxalign.h new file mode 100644 index 0000000..cb1f460 --- /dev/null +++ b/Shared/lwip/badvpn/misc/maxalign.h @@ -0,0 +1,53 @@ +/** + * @file maxalign.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_MAXALIGN_H +#define BADVPN_MAXALIGN_H + +#include +#include + +typedef union { + short a; + long b; + long long c; + double d; + long double e; + void *f; + uint8_t g; + uint16_t h; + uint32_t i; + uint64_t j; + size_t k; + void (*l) (void); +} bmax_align_t; + +#define BMAX_ALIGN (__alignof(bmax_align_t)) + +#endif diff --git a/Shared/lwip/badvpn/misc/memref.h b/Shared/lwip/badvpn/misc/memref.h new file mode 100644 index 0000000..03bfd16 --- /dev/null +++ b/Shared/lwip/badvpn/misc/memref.h @@ -0,0 +1,175 @@ +/** + * @file memref.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_MEMREF_H +#define BADVPN_MEMREF_H + +#include +#include +#include + +#include +#include +#include + +typedef struct { + char const *ptr; + size_t len; +} MemRef; + +static MemRef MemRef_Make (char const *ptr, size_t len); +static MemRef MemRef_MakeCstr (char const *ptr); +static char MemRef_At (MemRef o, size_t pos); +static void MemRef_AssertRange (MemRef o, size_t offset, size_t length); +static MemRef MemRef_SubFrom (MemRef o, size_t offset); +static MemRef MemRef_SubTo (MemRef o, size_t length); +static MemRef MemRef_Sub (MemRef o, size_t offset, size_t length); +static char * MemRef_StrDup (MemRef o); +static void MemRef_CopyOut (MemRef o, char *out); +static int MemRef_Equal (MemRef o, MemRef other); +static int MemRef_FindChar (MemRef o, char ch, size_t *out_index); + +#define MEMREF_LOOP_CHARS__BODY(char_rel_pos_var, char_var, body) \ +{ \ + for (size_t char_rel_pos_var = 0; char_rel_pos_var < MemRef__Loop_length; char_rel_pos_var++) { \ + char char_var = MemRef__Loop_o.ptr[MemRef__Loop_offset + char_rel_pos_var]; \ + { body } \ + } \ +} + +#define MEMREF_LOOP_CHARS_RANGE(o, offset, length, char_rel_pos_var, char_var, body) \ +{ \ + MemRef MemRef__Loop_o = (o); \ + size_t MemRef__Loop_offset = (offset); \ + size_t MemRef__Loop_length = (length); \ + MEMREF_LOOP_CHARS__BODY(char_rel_pos_var, char_var, body) \ +} + +#define MEMREF_LOOP_CHARS(o, char_rel_pos_var, char_var, body) \ +{ \ + MemRef MemRef__Loop_o = (o); \ + size_t MemRef__Loop_offset = 0; \ + size_t MemRef__Loop_length = MemRef__Loop_o.len; \ + MEMREF_LOOP_CHARS__BODY(char_rel_pos_var, char_var, body) \ +} + +// + +static MemRef MemRef_Make (char const *ptr, size_t len) +{ + MemRef res; + res.ptr = ptr; + res.len = len; + return res; +} + +static MemRef MemRef_MakeCstr (char const *ptr) +{ + ASSERT(ptr) + + return MemRef_Make(ptr, strlen(ptr)); +} + +static char MemRef_At (MemRef o, size_t pos) +{ + ASSERT(o.ptr) + ASSERT(pos < o.len) + + return o.ptr[pos]; +} + +static void MemRef_AssertRange (MemRef o, size_t offset, size_t length) +{ + ASSERT(offset <= o.len) + ASSERT(length <= o.len - offset) +} + +static MemRef MemRef_SubFrom (MemRef o, size_t offset) +{ + ASSERT(o.ptr) + ASSERT(offset <= o.len) + + return MemRef_Make(o.ptr + offset, o.len - offset); +} + +static MemRef MemRef_SubTo (MemRef o, size_t length) +{ + ASSERT(o.ptr) + ASSERT(length <= o.len) + + return MemRef_Make(o.ptr, length); +} + +static MemRef MemRef_Sub (MemRef o, size_t offset, size_t length) +{ + ASSERT(o.ptr) + MemRef_AssertRange(o, offset, length); + + return MemRef_Make(o.ptr + offset, length); +} + +static char * MemRef_StrDup (MemRef o) +{ + ASSERT(o.ptr) + + return b_strdup_bin(o.ptr, o.len); +} + +static void MemRef_CopyOut (MemRef o, char *out) +{ + ASSERT(o.ptr) + ASSERT(out) + + memcpy(out, o.ptr, o.len); +} + +static int MemRef_Equal (MemRef o, MemRef other) +{ + ASSERT(o.ptr) + ASSERT(other.ptr) + + return (o.len == other.len) && !memcmp(o.ptr, other.ptr, o.len); +} + +static int MemRef_FindChar (MemRef o, char ch, size_t *out_index) +{ + ASSERT(o.ptr) + + for (size_t i = 0; i < o.len; i++) { + if (o.ptr[i] == ch) { + if (out_index) { + *out_index = i; + } + return 1; + } + } + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/merge.h b/Shared/lwip/badvpn/misc/merge.h new file mode 100644 index 0000000..5322771 --- /dev/null +++ b/Shared/lwip/badvpn/misc/merge.h @@ -0,0 +1,36 @@ +/** + * @file merge.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_MERGE_H +#define BADVPN_MERGE_H + +#define MERGE_HELPER(x, y) x ## y +#define MERGE(x, y) MERGE_HELPER(x, y) + +#endif diff --git a/Shared/lwip/badvpn/misc/minmax.h b/Shared/lwip/badvpn/misc/minmax.h new file mode 100644 index 0000000..ca82055 --- /dev/null +++ b/Shared/lwip/badvpn/misc/minmax.h @@ -0,0 +1,56 @@ +/** + * @file minmax.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Minimum and maximum macros. + */ + +#ifndef BADVPN_MISC_MINMAX_H +#define BADVPN_MISC_MINMAX_H + +#include +#include + +#define DEFINE_BMINMAX(name, type) \ +static type bmin ## name (type a, type b) { return (a < b ? a : b); } \ +static type bmax ## name (type a, type b) { return (a > b ? a : b); } + +DEFINE_BMINMAX(_size, size_t) +DEFINE_BMINMAX(_int, int) +DEFINE_BMINMAX(_int8, int8_t) +DEFINE_BMINMAX(_int16, int16_t) +DEFINE_BMINMAX(_int32, int32_t) +DEFINE_BMINMAX(_int64, int64_t) +DEFINE_BMINMAX(_uint, unsigned int) +DEFINE_BMINMAX(_uint8, uint8_t) +DEFINE_BMINMAX(_uint16, uint16_t) +DEFINE_BMINMAX(_uint32, uint32_t) +DEFINE_BMINMAX(_uint64, uint64_t) + +#endif diff --git a/Shared/lwip/badvpn/misc/modadd.h b/Shared/lwip/badvpn/misc/modadd.h new file mode 100644 index 0000000..4e4f04a --- /dev/null +++ b/Shared/lwip/badvpn/misc/modadd.h @@ -0,0 +1,59 @@ +/** + * @file modadd.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Modular addition macro. + * + * Calculates (x + y) mod m, assuming + * 0 <= x < m and 0 <= y < m. + */ + +#ifndef BADVPN_MISC_MODADD_H +#define BADVPN_MISC_MODADD_H + +#include + +#define DECLARE_BMODADD(type, name) \ +static type bmodadd_##name (type x, type y, type m) \ +{ \ + ASSERT(x >= 0) \ + ASSERT(x < m) \ + ASSERT(y >= 0) \ + ASSERT(y < m) \ + \ + if (y >= m - x) { \ + return (y - (m - x)); \ + } else { \ + return (x + y); \ + } \ +} \ + +DECLARE_BMODADD(int, int) + +#endif diff --git a/Shared/lwip/badvpn/misc/mswsock.h b/Shared/lwip/badvpn/misc/mswsock.h new file mode 100644 index 0000000..4f4c38d --- /dev/null +++ b/Shared/lwip/badvpn/misc/mswsock.h @@ -0,0 +1,229 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +#ifndef _MSWSOCK_ +#define _MSWSOCK_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SO_CONNDATA 0x7000 +#define SO_CONNOPT 0x7001 +#define SO_DISCDATA 0x7002 +#define SO_DISCOPT 0x7003 +#define SO_CONNDATALEN 0x7004 +#define SO_CONNOPTLEN 0x7005 +#define SO_DISCDATALEN 0x7006 +#define SO_DISCOPTLEN 0x7007 + +#define SO_OPENTYPE 0x7008 + +#define SO_SYNCHRONOUS_ALERT 0x10 +#define SO_SYNCHRONOUS_NONALERT 0x20 + +#define SO_MAXDG 0x7009 +#define SO_MAXPATHDG 0x700A +#define SO_UPDATE_ACCEPT_CONTEXT 0x700B +#define SO_CONNECT_TIME 0x700C +#define SO_UPDATE_CONNECT_CONTEXT 0x7010 + +#define TCP_BSDURGENT 0x7000 + +#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) +#if (_WIN32_WINNT < 0x0600) && (_WIN32_WINNT >= 0x0501) +#define SIO_SOCKET_CLOSE_NOTIFY _WSAIOW(IOC_VENDOR,13) +#endif /* >= XP && < VISTA */ +#if (_WIN32_WINNT >= 0x0600) +#define SIO_BSP_HANDLE _WSAIOR(IOC_WS2,27) +#define SIO_BSP_HANDLE_SELECT _WSAIOR(IOC_WS2,28) +#define SIO_BSP_HANDLE_POLL _WSAIOR(IOC_WS2,29) + +#define SIO_EXT_SELECT _WSAIORW(IOC_WS2,30) +#define SIO_EXT_POLL _WSAIORW(IOC_WS2,31) +#define SIO_EXT_SENDMSG _WSAIORW(IOC_WS2,32) + +#define SIO_BASE_HANDLE _WSAIOR(IOC_WS2,34) +#endif /* _WIN32_WINNT >= 0x0600 */ + +#ifndef __MSWSOCK_WS1_SHARED + int WINAPI WSARecvEx(SOCKET s,char *buf,int len,int *flags); +#endif /* __MSWSOCK_WS1_SHARED */ + +#define TF_DISCONNECT 0x01 +#define TF_REUSE_SOCKET 0x02 +#define TF_WRITE_BEHIND 0x04 +#define TF_USE_DEFAULT_WORKER 0x00 +#define TF_USE_SYSTEM_THREAD 0x10 +#define TF_USE_KERNEL_APC 0x20 + +#include +#ifndef __MSWSOCK_WS1_SHARED + WINBOOL WINAPI TransmitFile(SOCKET hSocket,HANDLE hFile,DWORD nNumberOfBytesToWrite,DWORD nNumberOfBytesPerSend,LPOVERLAPPED lpOverlapped,LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,DWORD dwReserved); + WINBOOL WINAPI AcceptEx(SOCKET sListenSocket,SOCKET sAcceptSocket,PVOID lpOutputBuffer,DWORD dwReceiveDataLength,DWORD dwLocalAddressLength,DWORD dwRemoteAddressLength,LPDWORD lpdwBytesReceived,LPOVERLAPPED lpOverlapped); + VOID WINAPI GetAcceptExSockaddrs(PVOID lpOutputBuffer,DWORD dwReceiveDataLength,DWORD dwLocalAddressLength,DWORD dwRemoteAddressLength,struct sockaddr **LocalSockaddr,LPINT LocalSockaddrLength,struct sockaddr **RemoteSockaddr,LPINT RemoteSockaddrLength); +#endif /* __MSWSOCK_WS1_SHARED */ + + typedef WINBOOL (WINAPI *LPFN_TRANSMITFILE)(SOCKET hSocket,HANDLE hFile,DWORD nNumberOfBytesToWrite,DWORD nNumberOfBytesPerSend,LPOVERLAPPED lpOverlapped,LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,DWORD dwReserved); + +#define WSAID_TRANSMITFILE {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} + + typedef WINBOOL (WINAPI *LPFN_ACCEPTEX)(SOCKET sListenSocket,SOCKET sAcceptSocket,PVOID lpOutputBuffer,DWORD dwReceiveDataLength,DWORD dwLocalAddressLength,DWORD dwRemoteAddressLength,LPDWORD lpdwBytesReceived,LPOVERLAPPED lpOverlapped); + +#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} + + typedef VOID (WINAPI *LPFN_GETACCEPTEXSOCKADDRS)(PVOID lpOutputBuffer,DWORD dwReceiveDataLength,DWORD dwLocalAddressLength,DWORD dwRemoteAddressLength,struct sockaddr **LocalSockaddr,LPINT LocalSockaddrLength,struct sockaddr **RemoteSockaddr,LPINT RemoteSockaddrLength); + +#define WSAID_GETACCEPTEXSOCKADDRS {0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} + + typedef struct _TRANSMIT_PACKETS_ELEMENT { + ULONG dwElFlags; +#define TP_ELEMENT_MEMORY 1 +#define TP_ELEMENT_FILE 2 +#define TP_ELEMENT_EOP 4 + ULONG cLength; + __MINGW_EXTENSION union { + __MINGW_EXTENSION struct { + LARGE_INTEGER nFileOffset; + HANDLE hFile; + }; + PVOID pBuffer; + }; + } TRANSMIT_PACKETS_ELEMENT,*PTRANSMIT_PACKETS_ELEMENT,*LPTRANSMIT_PACKETS_ELEMENT; + +#define TP_DISCONNECT TF_DISCONNECT +#define TP_REUSE_SOCKET TF_REUSE_SOCKET +#define TP_USE_DEFAULT_WORKER TF_USE_DEFAULT_WORKER +#define TP_USE_SYSTEM_THREAD TF_USE_SYSTEM_THREAD +#define TP_USE_KERNEL_APC TF_USE_KERNEL_APC + + typedef WINBOOL (WINAPI *LPFN_TRANSMITPACKETS) (SOCKET hSocket,LPTRANSMIT_PACKETS_ELEMENT lpPacketArray,DWORD nElementCount,DWORD nSendSize,LPOVERLAPPED lpOverlapped,DWORD dwFlags); + +#define WSAID_TRANSMITPACKETS {0xd9689da0,0x1f90,0x11d3,{0x99,0x71,0x00,0xc0,0x4f,0x68,0xc8,0x76}} + + typedef WINBOOL (WINAPI *LPFN_CONNECTEX)(SOCKET s,const struct sockaddr *name,int namelen,PVOID lpSendBuffer,DWORD dwSendDataLength,LPDWORD lpdwBytesSent,LPOVERLAPPED lpOverlapped); + +#define WSAID_CONNECTEX {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}} + + typedef WINBOOL (WINAPI *LPFN_DISCONNECTEX)(SOCKET s,LPOVERLAPPED lpOverlapped,DWORD dwFlags,DWORD dwReserved); + +#define WSAID_DISCONNECTEX {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} + +#define DE_REUSE_SOCKET TF_REUSE_SOCKET + +#define NLA_NAMESPACE_GUID {0x6642243a,0x3ba8,0x4aa6,{0xba,0xa5,0x2e,0xb,0xd7,0x1f,0xdd,0x83}} + +#define NLA_SERVICE_CLASS_GUID {0x37e515,0xb5c9,0x4a43,{0xba,0xda,0x8b,0x48,0xa8,0x7a,0xd2,0x39}} + +#define NLA_ALLUSERS_NETWORK 0x00000001 +#define NLA_FRIENDLY_NAME 0x00000002 + + typedef enum _NLA_BLOB_DATA_TYPE { + NLA_RAW_DATA = 0,NLA_INTERFACE = 1,NLA_802_1X_LOCATION = 2,NLA_CONNECTIVITY = 3,NLA_ICS = 4 + } NLA_BLOB_DATA_TYPE,*PNLA_BLOB_DATA_TYPE; + + typedef enum _NLA_CONNECTIVITY_TYPE { + NLA_NETWORK_AD_HOC = 0,NLA_NETWORK_MANAGED = 1,NLA_NETWORK_UNMANAGED = 2,NLA_NETWORK_UNKNOWN = 3 + } NLA_CONNECTIVITY_TYPE,*PNLA_CONNECTIVITY_TYPE; + + typedef enum _NLA_INTERNET { + NLA_INTERNET_UNKNOWN = 0,NLA_INTERNET_NO = 1,NLA_INTERNET_YES = 2 + } NLA_INTERNET,*PNLA_INTERNET; + + typedef struct _NLA_BLOB { + struct { + NLA_BLOB_DATA_TYPE type; + DWORD dwSize; + DWORD nextOffset; + } header; + union { + CHAR rawData[1]; + struct { + DWORD dwType; + DWORD dwSpeed; + CHAR adapterName[1]; + } interfaceData; + struct { + CHAR information[1]; + } locationData; + struct { + NLA_CONNECTIVITY_TYPE type; + NLA_INTERNET internet; + } connectivity; + struct { + struct { + DWORD speed; + DWORD type; + DWORD state; + WCHAR machineName[256]; + WCHAR sharedAdapterName[256]; + } remote; + } ICS; + } data; + } NLA_BLOB,*PNLA_BLOB,*LPNLA_BLOB; + +#ifdef BADVPN_SHIPPED_MSWSOCK_DECLARE_WSAMSG + typedef struct _WSAMSG { + LPSOCKADDR name; + INT namelen; + LPWSABUF lpBuffers; + DWORD dwBufferCount; + WSABUF Control; + DWORD dwFlags; + } WSAMSG,*PWSAMSG,*LPWSAMSG; +#endif + + typedef struct _WSACMSGHDR { + SIZE_T cmsg_len; + INT cmsg_level; + INT cmsg_type; + } WSACMSGHDR,*PWSACMSGHDR,*LPWSACMSGHDR; + +#define WSA_CMSGHDR_ALIGN(length) (((length) + TYPE_ALIGNMENT(WSACMSGHDR)-1) & (~(TYPE_ALIGNMENT(WSACMSGHDR)-1))) +#define WSA_CMSGDATA_ALIGN(length) (((length) + MAX_NATURAL_ALIGNMENT-1) & (~(MAX_NATURAL_ALIGNMENT-1))) +#define WSA_CMSG_FIRSTHDR(msg) (((msg)->Control.len >= sizeof(WSACMSGHDR)) ? (LPWSACMSGHDR)(msg)->Control.buf : (LPWSACMSGHDR)NULL) +#define WSA_CMSG_NXTHDR(msg,cmsg) ((!(cmsg)) ? WSA_CMSG_FIRSTHDR(msg) : ((((u_char *)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len) + sizeof(WSACMSGHDR)) > (u_char *)((msg)->Control.buf) + (msg)->Control.len) ? (LPWSACMSGHDR)NULL : (LPWSACMSGHDR)((u_char *)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len)))) +#define WSA_CMSG_DATA(cmsg) ((u_char *)(cmsg) + WSA_CMSGDATA_ALIGN(sizeof(WSACMSGHDR))) +#define WSA_CMSG_SPACE(length) (WSA_CMSGDATA_ALIGN(sizeof(WSACMSGHDR) + WSA_CMSGHDR_ALIGN(length))) +#define WSA_CMSG_LEN(length) (WSA_CMSGDATA_ALIGN(sizeof(WSACMSGHDR)) + length) + +#define MSG_TRUNC 0x0100 +#define MSG_CTRUNC 0x0200 +#define MSG_BCAST 0x0400 +#define MSG_MCAST 0x0800 + + typedef INT (WINAPI *LPFN_WSARECVMSG)(SOCKET s, LPWSAMSG lpMsg, + LPDWORD lpdwNumberOfBytesRecvd, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +#define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}} + +#if(_WIN32_WINNT >= 0x0600) + typedef struct { + LPWSAMSG lpMsg; + DWORD dwFlags; + LPDWORD lpNumberOfBytesSent; + LPWSAOVERLAPPED lpOverlapped; + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; + } WSASENDMSG, *LPWSASENDMSG; + + typedef INT (WSAAPI *LPFN_WSASENDMSG)(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags, + LPDWORD lpNumberOfBytesSent, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +#define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}} + +#endif /* (_WIN32_WINNT >= 0x0600) */ + +#ifdef __cplusplus +} +#endif + +#endif /* _MSWSOCK_ */ diff --git a/Shared/lwip/badvpn/misc/nonblocking.h b/Shared/lwip/badvpn/misc/nonblocking.h new file mode 100644 index 0000000..fe82584 --- /dev/null +++ b/Shared/lwip/badvpn/misc/nonblocking.h @@ -0,0 +1,51 @@ +/** + * @file nonblocking.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Function for enabling non-blocking mode for a file descriptor. + */ + +#ifndef BADVPN_MISC_NONBLOCKING_H +#define BADVPN_MISC_NONBLOCKING_H + +#include +#include + +static int badvpn_set_nonblocking (int fd); + +int badvpn_set_nonblocking (int fd) +{ + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + return 0; + } + + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/nsskey.h b/Shared/lwip/badvpn/misc/nsskey.h new file mode 100644 index 0000000..8268235 --- /dev/null +++ b/Shared/lwip/badvpn/misc/nsskey.h @@ -0,0 +1,118 @@ +/** + * @file nsskey.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Function for opening a NSS certificate and its private key. + */ + +#ifndef BADVPN_MISC_NSSKEY_H +#define BADVPN_MISC_NSSKEY_H + +#include + +#include +#include +#include +#include + +#include + +#include + +/** + * Opens a NSS certificate and its private key. + * + * @param name name of the certificate + * @param out_cert on success, the certificate will be returned here. Should be + * released with CERT_DestroyCertificate. + * @param out_key on success, the private key will be returned here. Should be + * released with SECKEY_DestroyPrivateKey. + * @return 1 on success, 0 on failure + */ +static int open_nss_cert_and_key (char *name, CERTCertificate **out_cert, SECKEYPrivateKey **out_key) WARN_UNUSED; + +static SECKEYPrivateKey * find_nss_private_key (char *name) +{ + SECKEYPrivateKey *key = NULL; + + PK11SlotList *slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL); + if (!slot_list) { + return NULL; + } + + PK11SlotListElement *slot_entry; + for (slot_entry = slot_list->head; !key && slot_entry; slot_entry = slot_entry->next) { + SECKEYPrivateKeyList *key_list = PK11_ListPrivKeysInSlot(slot_entry->slot, name, NULL); + if (!key_list) { + BLog(BLOG_ERROR, "PK11_ListPrivKeysInSlot failed"); + continue; + } + + SECKEYPrivateKeyListNode *key_node; + for (key_node = PRIVKEY_LIST_HEAD(key_list); !key && !PRIVKEY_LIST_END(key_node, key_list); key_node = PRIVKEY_LIST_NEXT(key_node)) { + char *key_name = PK11_GetPrivateKeyNickname(key_node->key); + if (!key_name || strcmp(key_name, name)) { + PORT_Free((void *)key_name); + continue; + } + PORT_Free((void *)key_name); + + key = SECKEY_CopyPrivateKey(key_node->key); + } + + SECKEY_DestroyPrivateKeyList(key_list); + } + + PK11_FreeSlotList(slot_list); + + return key; +} + +int open_nss_cert_and_key (char *name, CERTCertificate **out_cert, SECKEYPrivateKey **out_key) +{ + CERTCertificate *cert; + cert = CERT_FindCertByNicknameOrEmailAddr(CERT_GetDefaultCertDB(), name); + if (!cert) { + BLog(BLOG_ERROR, "CERT_FindCertByName failed (%d)", (int)PR_GetError()); + return 0; + } + + SECKEYPrivateKey *key = find_nss_private_key(name); + if (!key) { + BLog(BLOG_ERROR, "Failed to find private key"); + CERT_DestroyCertificate(cert); + return 0; + } + + *out_cert = cert; + *out_key = key; + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/offset.h b/Shared/lwip/badvpn/misc/offset.h new file mode 100644 index 0000000..23b7683 --- /dev/null +++ b/Shared/lwip/badvpn/misc/offset.h @@ -0,0 +1,51 @@ +/** + * @file offset.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Macros for determining offsets of members in structs. + */ + +#ifndef BADVPN_MISC_OFFSET_H +#define BADVPN_MISC_OFFSET_H + +#include +#include + +/** + * Returns a pointer to a struct, given a pointer to its member. + */ +#define UPPER_OBJECT(_ptr, _object_type, _field_name) ((_object_type *)((char *)(_ptr) - offsetof(_object_type, _field_name))) + +/** + * Returns the offset of one struct member from another. + * Expands to an int. + */ +#define OFFSET_DIFF(_object_type, _field1, _field2) ((int)offsetof(_object_type, _field1) - (int)offsetof(_object_type, _field2)) + +#endif diff --git a/Shared/lwip/badvpn/misc/open_standard_streams.h b/Shared/lwip/badvpn/misc/open_standard_streams.h new file mode 100644 index 0000000..7fd6d41 --- /dev/null +++ b/Shared/lwip/badvpn/misc/open_standard_streams.h @@ -0,0 +1,54 @@ +/** + * @file open_standard_streams.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_OPEN_STANDARD_STREAMS_H +#define BADVPN_OPEN_STANDARD_STREAMS_H + +#ifndef BADVPN_USE_WINAPI +#include +#include +#include +#include +#endif + +static void open_standard_streams (void) +{ +#ifndef BADVPN_USE_WINAPI + int fd; + + do { + fd = open("/dev/null", O_RDWR); + if (fd > 2) { + close(fd); + } + } while (fd >= 0 && fd <= 2); +#endif +} + +#endif diff --git a/Shared/lwip/badvpn/misc/overflow.h b/Shared/lwip/badvpn/misc/overflow.h new file mode 100644 index 0000000..9fde52a --- /dev/null +++ b/Shared/lwip/badvpn/misc/overflow.h @@ -0,0 +1,66 @@ +/** + * @file overflow.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Functions for checking for overflow of integer addition. + */ + +#ifndef BADVPN_MISC_OVERFLOW_H +#define BADVPN_MISC_OVERFLOW_H + +#include +#include + +#define DEFINE_UNSIGNED_OVERFLOW(_name, _type, _max) \ +static int add_ ## _name ## _overflows (_type a, _type b) \ +{\ + return (b > _max - a); \ +} + +#define DEFINE_SIGNED_OVERFLOW(_name, _type, _min, _max) \ +static int add_ ## _name ## _overflows (_type a, _type b) \ +{\ + if ((a < 0) ^ (b < 0)) return 0; \ + if (a < 0) return -(a < _min - b); \ + return (a > _max - b); \ +} + +DEFINE_UNSIGNED_OVERFLOW(uint, unsigned int, UINT_MAX) +DEFINE_UNSIGNED_OVERFLOW(uint8, uint8_t, UINT8_MAX) +DEFINE_UNSIGNED_OVERFLOW(uint16, uint16_t, UINT16_MAX) +DEFINE_UNSIGNED_OVERFLOW(uint32, uint32_t, UINT32_MAX) +DEFINE_UNSIGNED_OVERFLOW(uint64, uint64_t, UINT64_MAX) + +DEFINE_SIGNED_OVERFLOW(int, int, INT_MIN, INT_MAX) +DEFINE_SIGNED_OVERFLOW(int8, int8_t, INT8_MIN, INT8_MAX) +DEFINE_SIGNED_OVERFLOW(int16, int16_t, INT16_MIN, INT16_MAX) +DEFINE_SIGNED_OVERFLOW(int32, int32_t, INT32_MIN, INT32_MAX) +DEFINE_SIGNED_OVERFLOW(int64, int64_t, INT64_MIN, INT64_MAX) + +#endif diff --git a/Shared/lwip/badvpn/misc/packed.h b/Shared/lwip/badvpn/misc/packed.h new file mode 100644 index 0000000..2175536 --- /dev/null +++ b/Shared/lwip/badvpn/misc/packed.h @@ -0,0 +1,51 @@ +/** + * @file packed.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Structure packing macros. + */ + +#ifndef BADVPN_PACKED_H +#define BADVPN_PACKED_H + +#ifdef _MSC_VER + +#define B_START_PACKED __pragma(pack(push, 1)) +#define B_END_PACKED __pragma(pack(pop)) +#define B_PACKED + +#else + +#define B_START_PACKED +#define B_END_PACKED +#define B_PACKED __attribute__((packed)) + +#endif + +#endif diff --git a/Shared/lwip/badvpn/misc/parse_number.h b/Shared/lwip/badvpn/misc/parse_number.h new file mode 100644 index 0000000..e5ef333 --- /dev/null +++ b/Shared/lwip/badvpn/misc/parse_number.h @@ -0,0 +1,234 @@ +/** + * @file parse_number.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Numeric string parsing. + */ + +#ifndef BADVPN_MISC_PARSE_NUMBER_H +#define BADVPN_MISC_PARSE_NUMBER_H + +#include +#include +#include +#include + +#include +#include + +// public parsing functions +static int decode_decimal_digit (char c); +static int decode_hex_digit (char c); +static int parse_unsigned_integer (MemRef str, uintmax_t *out) WARN_UNUSED; +static int parse_unsigned_hex_integer (MemRef str, uintmax_t *out) WARN_UNUSED; +static int parse_signmag_integer (MemRef str, int *out_sign, uintmax_t *out_mag) WARN_UNUSED; + +// public generation functions +static int compute_decimal_repr_size (uintmax_t x); +static void generate_decimal_repr (uintmax_t x, char *out, int repr_size); +static int generate_decimal_repr_string (uintmax_t x, char *out); + +// implementation follows + +// decimal representation of UINTMAX_MAX +static const char parse_number__uintmax_max_str[] = "18446744073709551615"; + +// make sure UINTMAX_MAX is what we think it is +static const char parse_number__uintmax_max_str_assert[(UINTMAX_MAX == UINTMAX_C(18446744073709551615)) ? 1 : -1]; + +static int decode_decimal_digit (char c) +{ + switch (c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + } + + return -1; +} + +static int decode_hex_digit (char c) +{ + switch (c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'A': case 'a': return 10; + case 'B': case 'b': return 11; + case 'C': case 'c': return 12; + case 'D': case 'd': return 13; + case 'E': case 'e': return 14; + case 'F': case 'f': return 15; + } + + return -1; +} + +static int parse__no_overflow (const char *str, size_t str_len, uintmax_t *out) +{ + uintmax_t n = 0; + + while (str_len > 0) { + if (*str < '0' || *str > '9') { + return 0; + } + + n = 10 * n + (*str - '0'); + + str++; + str_len--; + } + + *out = n; + return 1; +} + +int parse_unsigned_integer (MemRef str, uintmax_t *out) +{ + // we do not allow empty strings + if (str.len == 0) { + return 0; + } + + // remove leading zeros + while (str.len > 0 && *str.ptr == '0') { + str.ptr++; + str.len--; + } + + // detect overflow + if (str.len > sizeof(parse_number__uintmax_max_str) - 1 || + (str.len == sizeof(parse_number__uintmax_max_str) - 1 && memcmp(str.ptr, parse_number__uintmax_max_str, sizeof(parse_number__uintmax_max_str) - 1) > 0)) { + return 0; + } + + // will not overflow (but can still have invalid characters) + return parse__no_overflow(str.ptr, str.len, out); +} + +int parse_unsigned_hex_integer (MemRef str, uintmax_t *out) +{ + uintmax_t n = 0; + + if (str.len == 0) { + return 0; + } + + while (str.len > 0) { + int digit = decode_hex_digit(*str.ptr); + if (digit < 0) { + return 0; + } + + if (n > UINTMAX_MAX / 16) { + return 0; + } + n *= 16; + + if (digit > UINTMAX_MAX - n) { + return 0; + } + n += digit; + + str.ptr++; + str.len--; + } + + *out = n; + return 1; +} + +int parse_signmag_integer (MemRef str, int *out_sign, uintmax_t *out_mag) +{ + int sign = 1; + if (str.len > 0 && (str.ptr[0] == '+' || str.ptr[0] == '-')) { + sign = 1 - 2 * (str.ptr[0] == '-'); + str.ptr++; + str.len--; + } + + if (!parse_unsigned_integer(str, out_mag)) { + return 0; + } + + *out_sign = sign; + return 1; +} + +int compute_decimal_repr_size (uintmax_t x) +{ + int size = 0; + + do { + size++; + x /= 10; + } while (x > 0); + + return size; +} + +void generate_decimal_repr (uintmax_t x, char *out, int repr_size) +{ + ASSERT(out) + ASSERT(repr_size == compute_decimal_repr_size(x)) + + out += repr_size; + + do { + *(--out) = '0' + (x % 10); + x /= 10; + } while (x > 0); +} + +int generate_decimal_repr_string (uintmax_t x, char *out) +{ + ASSERT(out) + + int repr_size = compute_decimal_repr_size(x); + generate_decimal_repr(x, out, repr_size); + out[repr_size] = '\0'; + + return repr_size; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/print_macros.h b/Shared/lwip/badvpn/misc/print_macros.h new file mode 100644 index 0000000..a07fdbe --- /dev/null +++ b/Shared/lwip/badvpn/misc/print_macros.h @@ -0,0 +1,98 @@ +/** + * @file print_macros.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Format macros for printf() for non-standard compilers. + */ + +#ifndef BADVPN_PRINT_MACROS +#define BADVPN_PRINT_MACROS + +#ifdef _MSC_VER + +// size_t +#define PRIsz "Iu" + +// signed exact width (intN_t) +#define PRId8 "d" +#define PRIi8 "i" +#define PRId16 "d" +#define PRIi16 "i" +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRId64 "I64d" +#define PRIi64 "I64i" + +// unsigned exact width (uintN_t) +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIo16 "o" +#define PRIu16 "u" +#define PRIx16 "x" +#define PRIX16 "X" +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" + +// signed maximum width (intmax_t) +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +// unsigned maximum width (uintmax_t) +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +// signed pointer (intptr_t) +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// unsigned pointer (uintptr_t) +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +#else + +#include + +#define PRIsz "zu" + +#endif + +#endif diff --git a/Shared/lwip/badvpn/misc/read_file.h b/Shared/lwip/badvpn/misc/read_file.h new file mode 100644 index 0000000..e1862e5 --- /dev/null +++ b/Shared/lwip/badvpn/misc/read_file.h @@ -0,0 +1,98 @@ +/** + * @file read_file.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Function for reading a file into memory using stdio. + */ + +#ifndef BADVPN_MISC_READ_FILE_H +#define BADVPN_MISC_READ_FILE_H + +#include +#include +#include +#include + +static int read_file (const char *file, uint8_t **out_data, size_t *out_len) +{ + FILE *f = fopen(file, "r"); + if (!f) { + goto fail0; + } + + size_t buf_len = 0; + size_t buf_size = 128; + + uint8_t *buf = (uint8_t *)malloc(buf_size); + if (!buf) { + goto fail1; + } + + while (1) { + if (buf_len == buf_size) { + if (2 > SIZE_MAX / buf_size) { + goto fail; + } + size_t newsize = 2 * buf_size; + + uint8_t *newbuf = (uint8_t *)realloc(buf, newsize); + if (!newbuf) { + goto fail; + } + + buf = newbuf; + buf_size = newsize; + } + + size_t bytes = fread(buf + buf_len, 1, buf_size - buf_len, f); + if (bytes == 0) { + if (feof(f)) { + break; + } + goto fail; + } + + buf_len += bytes; + } + + fclose(f); + + *out_data = buf; + *out_len = buf_len; + return 1; + +fail: + free(buf); +fail1: + fclose(f); +fail0: + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/read_write_int.h b/Shared/lwip/badvpn/misc/read_write_int.h new file mode 100644 index 0000000..bc4ed2c --- /dev/null +++ b/Shared/lwip/badvpn/misc/read_write_int.h @@ -0,0 +1,181 @@ +/** + * @file read_write_int.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_READ_WRITE_INT_H +#define BADVPN_READ_WRITE_INT_H + +#include + +static uint8_t badvpn_read_le8 (const char *c_ptr); +static uint16_t badvpn_read_le16 (const char *c_ptr); +static uint32_t badvpn_read_le32 (const char *c_ptr); +static uint64_t badvpn_read_le64 (const char *c_ptr); + +static uint8_t badvpn_read_be8 (const char *c_ptr); +static uint16_t badvpn_read_be16 (const char *c_ptr); +static uint32_t badvpn_read_be32 (const char *c_ptr); +static uint64_t badvpn_read_be64 (const char *c_ptr); + +static void badvpn_write_le8 (uint8_t x, char *c_ptr); +static void badvpn_write_le16 (uint16_t x, char *c_ptr); +static void badvpn_write_le32 (uint32_t x, char *c_ptr); +static void badvpn_write_le64 (uint64_t x, char *c_ptr); + +static void badvpn_write_be8 (uint8_t x, char *c_ptr); +static void badvpn_write_be16 (uint16_t x, char *c_ptr); +static void badvpn_write_be32 (uint32_t x, char *c_ptr); +static void badvpn_write_be64 (uint64_t x, char *c_ptr); + +static uint8_t badvpn_read_le8 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint8_t)ptr[0] << 0); +} + +static uint16_t badvpn_read_le16 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint16_t)ptr[1] << 8) | ((uint16_t)ptr[0] << 0); +} + +static uint32_t badvpn_read_le32 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint32_t)ptr[3] << 24) | ((uint32_t)ptr[2] << 16) | + ((uint32_t)ptr[1] << 8) | ((uint32_t)ptr[0] << 0); +} + +static uint64_t badvpn_read_le64 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint64_t)ptr[7] << 56) | ((uint64_t)ptr[6] << 48) | + ((uint64_t)ptr[5] << 40) | ((uint64_t)ptr[4] << 32) | + ((uint64_t)ptr[3] << 24) | ((uint64_t)ptr[2] << 16) | + ((uint64_t)ptr[1] << 8) | ((uint64_t)ptr[0] << 0); +} + +static uint8_t badvpn_read_be8 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint8_t)ptr[0] << 0); +} + +static uint16_t badvpn_read_be16 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint16_t)ptr[0] << 8) | ((uint16_t)ptr[1] << 0); +} + +static uint32_t badvpn_read_be32 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint32_t)ptr[0] << 24) | ((uint32_t)ptr[1] << 16) | + ((uint32_t)ptr[2] << 8) | ((uint32_t)ptr[3] << 0); +} + +static uint64_t badvpn_read_be64 (const char *c_ptr) +{ + const uint8_t *ptr = (const uint8_t *)c_ptr; + return ((uint64_t)ptr[0] << 56) | ((uint64_t)ptr[1] << 48) | + ((uint64_t)ptr[2] << 40) | ((uint64_t)ptr[3] << 32) | + ((uint64_t)ptr[4] << 24) | ((uint64_t)ptr[5] << 16) | + ((uint64_t)ptr[6] << 8) | ((uint64_t)ptr[7] << 0); +} + +static void badvpn_write_le8 (uint8_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[0] = x >> 0; +} + +static void badvpn_write_le16 (uint16_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[1] = x >> 8; + ptr[0] = x >> 0; +} + +static void badvpn_write_le32 (uint32_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[3] = x >> 24; + ptr[2] = x >> 16; + ptr[1] = x >> 8; + ptr[0] = x >> 0; +} + +static void badvpn_write_le64 (uint64_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[7] = x >> 56; + ptr[6] = x >> 48; + ptr[5] = x >> 40; + ptr[4] = x >> 32; + ptr[3] = x >> 24; + ptr[2] = x >> 16; + ptr[1] = x >> 8; + ptr[0] = x >> 0; +} + +static void badvpn_write_be8 (uint8_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[0] = x >> 0; +} + +static void badvpn_write_be16 (uint16_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[0] = x >> 8; + ptr[1] = x >> 0; +} + +static void badvpn_write_be32 (uint32_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[0] = x >> 24; + ptr[1] = x >> 16; + ptr[2] = x >> 8; + ptr[3] = x >> 0; +} + +static void badvpn_write_be64 (uint64_t x, char *c_ptr) +{ + uint8_t *ptr = (uint8_t *)c_ptr; + ptr[0] = x >> 56; + ptr[1] = x >> 48; + ptr[2] = x >> 40; + ptr[3] = x >> 32; + ptr[4] = x >> 24; + ptr[5] = x >> 16; + ptr[6] = x >> 8; + ptr[7] = x >> 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/socks_proto.h b/Shared/lwip/badvpn/misc/socks_proto.h new file mode 100644 index 0000000..41f5a1f --- /dev/null +++ b/Shared/lwip/badvpn/misc/socks_proto.h @@ -0,0 +1,118 @@ +/** + * @file socks_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the SOCKS protocol. + */ + +#ifndef BADVPN_MISC_SOCKS_PROTO_H +#define BADVPN_MISC_SOCKS_PROTO_H + +#include + +#include + +#define SOCKS_VERSION 0x05 + +#define SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED 0x00 +#define SOCKS_METHOD_GSSAPI 0x01 +#define SOCKS_METHOD_USERNAME_PASSWORD 0x02 +#define SOCKS_METHOD_NO_ACCEPTABLE_METHODS 0xFF + +#define SOCKS_CMD_CONNECT 0x01 +#define SOCKS_CMD_BIND 0x02 +#define SOCKS_CMD_UDP_ASSOCIATE 0x03 + +#define SOCKS_ATYP_IPV4 0x01 +#define SOCKS_ATYP_DOMAINNAME 0x03 +#define SOCKS_ATYP_IPV6 0x04 + +#define SOCKS_REP_SUCCEEDED 0x00 +#define SOCKS_REP_GENERAL_FAILURE 0x01 +#define SOCKS_REP_CONNECTION_NOT_ALLOWED 0x02 +#define SOCKS_REP_NETWORK_UNREACHABLE 0x03 +#define SOCKS_REP_HOST_UNREACHABLE 0x04 +#define SOCKS_REP_CONNECTION_REFUSED 0x05 +#define SOCKS_REP_TTL_EXPIRED 0x06 +#define SOCKS_REP_COMMAND_NOT_SUPPORTED 0x07 +#define SOCKS_REP_ADDRESS_TYPE_NOT_SUPPORTED 0x08 + +B_START_PACKED +struct socks_client_hello_header { + uint8_t ver; + uint8_t nmethods; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct socks_client_hello_method { + uint8_t method; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct socks_server_hello { + uint8_t ver; + uint8_t method; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct socks_request_header { + uint8_t ver; + uint8_t cmd; + uint8_t rsv; + uint8_t atyp; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct socks_reply_header { + uint8_t ver; + uint8_t rep; + uint8_t rsv; + uint8_t atyp; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct socks_addr_ipv4 { + uint32_t addr; + uint16_t port; +} B_PACKED; +B_END_PACKED + +B_START_PACKED +struct socks_addr_ipv6 { + uint8_t addr[16]; + uint16_t port; +} B_PACKED; +B_END_PACKED + +#endif diff --git a/Shared/lwip/badvpn/misc/sslsocket.h b/Shared/lwip/badvpn/misc/sslsocket.h new file mode 100644 index 0000000..71e43c2 --- /dev/null +++ b/Shared/lwip/badvpn/misc/sslsocket.h @@ -0,0 +1,48 @@ +/** + * @file sslsocket.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Structure for moving around sockets, possibly together with SSL compoments. + */ + +#ifndef BADVPN_MISC_SSLSOCKET_H +#define BADVPN_MISC_SSLSOCKET_H + +#include + +#include +#include + +typedef struct { + BConnection con; + PRFileDesc bottom_prfd; + PRFileDesc *ssl_prfd; +} sslsocket; + +#endif diff --git a/Shared/lwip/badvpn/misc/stdbuf_cmdline.h b/Shared/lwip/badvpn/misc/stdbuf_cmdline.h new file mode 100644 index 0000000..8459c64 --- /dev/null +++ b/Shared/lwip/badvpn/misc/stdbuf_cmdline.h @@ -0,0 +1,92 @@ +/** + * @file stdbuf_cmdline.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Builds command line for running a program via stdbuf. + */ + +#ifndef BADVPN_STDBUF_CMDLINE_H +#define BADVPN_STDBUF_CMDLINE_H + +#include + +#include +#include +#include + +/** + * Builds the initial part of command line for calling a program via stdbuf + * with standard output buffering set to line-buffered. + * + * @param out {@link CmdLine} to append the result to. Note than on failure, only + * some part of the cmdline may have been appended. + * @param stdbuf_exec full path to stdbuf executable + * @param exec path to the executable. Must not contain nulls. + * @param exec_len number of characters in exec + * @return 1 on success, 0 on failure + */ +static int build_stdbuf_cmdline (CmdLine *out, const char *stdbuf_exec, const char *exec, size_t exec_len) WARN_UNUSED; + +int build_stdbuf_cmdline (CmdLine *out, const char *stdbuf_exec, const char *exec, size_t exec_len) +{ + ASSERT(!memchr(exec, '\0', exec_len)) + + if (!CmdLine_AppendMulti(out, 3, stdbuf_exec, "-o", "L")) { + goto fail1; + } + + if (exec[0] == '/') { + if (!CmdLine_AppendNoNull(out, exec, exec_len)) { + goto fail1; + } + } else { + bsize_t size = bsize_add(bsize_fromsize(exec_len), bsize_fromsize(3)); + char *real_exec = BAllocSize(size); + if (!real_exec) { + goto fail1; + } + + memcpy(real_exec, "./", 2); + memcpy(real_exec + 2, exec, exec_len); + real_exec[2 + exec_len] = '\0'; + + int res = CmdLine_Append(out, real_exec); + free(real_exec); + if (!res) { + goto fail1; + } + } + + return 1; + +fail1: + return 0; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/strdup.h b/Shared/lwip/badvpn/misc/strdup.h new file mode 100644 index 0000000..2e475bb --- /dev/null +++ b/Shared/lwip/badvpn/misc/strdup.h @@ -0,0 +1,86 @@ +/** + * @file strdup.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Allocate memory for a string and copy it there. + */ + +#ifndef BADVPN_STRDUP_H +#define BADVPN_STRDUP_H + +#include +#include +#include + +#include + +/** + * Allocate and copy a null-terminated string. + */ +static char * b_strdup (const char *str) +{ + ASSERT(str) + + size_t len = strlen(str); + + char *s = (char *)malloc(len + 1); + if (!s) { + return NULL; + } + + memcpy(s, str, len + 1); + + return s; +} + +/** + * Allocate memory for a null-terminated string and use the + * given data as its contents. A null terminator is appended + * after the specified data. + */ +static char * b_strdup_bin (const char *str, size_t len) +{ + ASSERT(str) + + if (len == SIZE_MAX) { + return NULL; + } + + char *s = (char *)malloc(len + 1); + if (!s) { + return NULL; + } + + memcpy(s, str, len); + s[len] = '\0'; + + return s; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/string_begins_with.h b/Shared/lwip/badvpn/misc/string_begins_with.h new file mode 100644 index 0000000..3c9c5e9 --- /dev/null +++ b/Shared/lwip/badvpn/misc/string_begins_with.h @@ -0,0 +1,96 @@ +/** + * @file string_begins_with.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Function for checking if a string begins with a given string. + */ + +#ifndef BADVPN_MISC_STRING_BEGINS_WITH +#define BADVPN_MISC_STRING_BEGINS_WITH + +#include +#include + +#include + +static size_t data_begins_with (const char *str, size_t str_len, const char *needle) +{ + ASSERT(strlen(needle) > 0) + + size_t len = 0; + + while (str_len > 0 && *needle) { + if (*str != *needle) { + return 0; + } + str++; + str_len--; + needle++; + len++; + } + + if (*needle) { + return 0; + } + + return len; +} + +static size_t string_begins_with (const char *str, const char *needle) +{ + ASSERT(strlen(needle) > 0) + + return data_begins_with(str, strlen(str), needle); +} + +static size_t data_begins_with_bin (const char *str, size_t str_len, const char *needle, size_t needle_len) +{ + ASSERT(needle_len > 0) + + size_t len = 0; + + while (str_len > 0 && needle_len > 0) { + if (*str != *needle) { + return 0; + } + str++; + str_len--; + needle++; + needle_len--; + len++; + } + + if (needle_len > 0) { + return 0; + } + + return len; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/substring.h b/Shared/lwip/badvpn/misc/substring.h new file mode 100644 index 0000000..958d5ff --- /dev/null +++ b/Shared/lwip/badvpn/misc/substring.h @@ -0,0 +1,82 @@ +#include + +#include +#include + +static void build_substring_backtrack_table (MemRef str, size_t *out_table) +{ + ASSERT(str.len > 0) + + size_t x = 0; + + for (size_t i = 1; i < str.len; i++) { + out_table[i] = x; + while (x > 0 && str.ptr[i] != str.ptr[x]) { + x = out_table[x]; + } + if (str.ptr[i] == str.ptr[x]) { + x++; + } + } +} + +static int find_substring (MemRef text, MemRef word, const size_t *table, size_t *out_position) +{ + ASSERT(word.len > 0) + + size_t x = 0; + + for (size_t i = 0; i < text.len; i++) { + while (x > 0 && text.ptr[i] != word.ptr[x]) { + x = table[x]; + } + if (text.ptr[i] == word.ptr[x]) { + if (x + 1 == word.len) { + *out_position = i - x; + return 1; + } + x++; + } + } + + return 0; +} + +static void build_substring_backtrack_table_reverse (MemRef str, size_t *out_table) +{ + ASSERT(str.len > 0) + + size_t x = 0; + + for (size_t i = 1; i < str.len; i++) { + out_table[i] = x; + while (x > 0 && str.ptr[str.len - 1 - i] != str.ptr[str.len - 1 - x]) { + x = out_table[x]; + } + if (str.ptr[str.len - 1 - i] == str.ptr[str.len - 1 - x]) { + x++; + } + } +} + +static int find_substring_reverse (MemRef text, MemRef word, const size_t *table, size_t *out_position) +{ + ASSERT(word.len > 0) + + size_t x = 0; + + for (size_t i = 0; i < text.len; i++) { + while (x > 0 && text.ptr[text.len - 1 - i] != word.ptr[word.len - 1 - x]) { + x = table[x]; + } + if (text.ptr[text.len - 1 - i] == word.ptr[word.len - 1 - x]) { + if (x + 1 == word.len) { + *out_position = (text.len - 1 - i); + return 1; + } + x++; + } + } + + return 0; +} diff --git a/Shared/lwip/badvpn/misc/udp_proto.h b/Shared/lwip/badvpn/misc/udp_proto.h new file mode 100644 index 0000000..23ec69a --- /dev/null +++ b/Shared/lwip/badvpn/misc/udp_proto.h @@ -0,0 +1,170 @@ +/** + * @file udp_proto.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Definitions for the UDP protocol. + */ + +#ifndef BADVPN_MISC_UDP_PROTO_H +#define BADVPN_MISC_UDP_PROTO_H + +#include + +#include +#include +#include +#include +#include + +B_START_PACKED +struct udp_header { + uint16_t source_port; + uint16_t dest_port; + uint16_t length; + uint16_t checksum; +} B_PACKED; +B_END_PACKED + +static uint32_t udp_checksum_summer (const char *data, uint16_t len) +{ + ASSERT(len % 2 == 0) + + uint32_t t = 0; + + for (uint16_t i = 0; i < len / 2; i++) { + t += badvpn_read_be16(data + 2 * i); + } + + return t; +} + +static uint16_t udp_checksum (const struct udp_header *header, const uint8_t *payload, uint16_t payload_len, uint32_t source_addr, uint32_t dest_addr) +{ + uint32_t t = 0; + + t += udp_checksum_summer((char *)&source_addr, sizeof(source_addr)); + t += udp_checksum_summer((char *)&dest_addr, sizeof(dest_addr)); + + uint16_t x; + x = hton16(IPV4_PROTOCOL_UDP); + t += udp_checksum_summer((char *)&x, sizeof(x)); + x = hton16(sizeof(*header) + payload_len); + t += udp_checksum_summer((char *)&x, sizeof(x)); + + t += udp_checksum_summer((const char *)header, sizeof(*header)); + + if (payload_len % 2 == 0) { + t += udp_checksum_summer((const char *)payload, payload_len); + } else { + t += udp_checksum_summer((const char *)payload, payload_len - 1); + + x = hton16(((uint16_t)payload[payload_len - 1]) << 8); + t += udp_checksum_summer((char *)&x, sizeof(x)); + } + + while (t >> 16) { + t = (t & 0xFFFF) + (t >> 16); + } + + if (t == 0) { + t = UINT16_MAX; + } + + return hton16(~t); +} + +static uint16_t udp_ip6_checksum (const struct udp_header *header, const uint8_t *payload, uint16_t payload_len, const uint8_t *source_addr, const uint8_t *dest_addr) +{ + uint32_t t = 0; + + t += udp_checksum_summer((const char *)source_addr, 16); + t += udp_checksum_summer((const char *)dest_addr, 16); + + uint32_t x; + x = hton32(sizeof(*header) + payload_len); + t += udp_checksum_summer((char *)&x, sizeof(x)); + x = hton32(IPV6_NEXT_UDP); + t += udp_checksum_summer((char *)&x, sizeof(x)); + + t += udp_checksum_summer((const char *)header, sizeof(*header)); + + if (payload_len % 2 == 0) { + t += udp_checksum_summer((const char *)payload, payload_len); + } else { + t += udp_checksum_summer((const char *)payload, payload_len - 1); + + uint16_t y; + y = hton16(((uint16_t)payload[payload_len - 1]) << 8); + t += udp_checksum_summer((char *)&y, sizeof(y)); + } + + while (t >> 16) { + t = (t & 0xFFFF) + (t >> 16); + } + + if (t == 0) { + t = UINT16_MAX; + } + + return hton16(~t); +} + +static int udp_check (const uint8_t *data, int data_len, struct udp_header *out_header, uint8_t **out_payload, int *out_payload_len) +{ + ASSERT(data_len >= 0) + ASSERT(out_header) + ASSERT(out_payload) + ASSERT(out_payload_len) + + // parse UDP header + if (data_len < sizeof(struct udp_header)) { + return 0; + } + memcpy(out_header, data, sizeof(*out_header)); + data += sizeof(*out_header); + data_len -= sizeof(*out_header); + + // verify UDP payload + int udp_length = ntoh16(out_header->length); + if (udp_length < sizeof(*out_header)) { + return 0; + } + if (udp_length > sizeof(*out_header) + data_len) { + return 0; + } + + // ignore stray data + data_len = udp_length - sizeof(*out_header); + + *out_payload = (uint8_t *)data; + *out_payload_len = data_len; + return 1; +} + +#endif diff --git a/Shared/lwip/badvpn/misc/unicode_funcs.h b/Shared/lwip/badvpn/misc/unicode_funcs.h new file mode 100644 index 0000000..2442e7f --- /dev/null +++ b/Shared/lwip/badvpn/misc/unicode_funcs.h @@ -0,0 +1,232 @@ +/** + * @file unicode_funcs.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_UNICODE_FUNCS_H +#define BADVPN_UNICODE_FUNCS_H + +#include +#include +#include +#include +#include +#include + +/** + * Decodes UTF-16 data as bytes into an allocated null-terminated UTF-8 string. + * + * @param data UTF-16 data, in big endian + * @param data_len size of data in bytes + * @param out_is_error if not NULL and the function returns a string, + * *out_is_error will be set to 0 or 1, indicating + * whether there have been errors decoding the input. + * A null decoded character is treated as an error. + * @return An UTF-8 null-terminated string which can be freed with free(), + * or NULL if out of memory. + */ +static char * unicode_decode_utf16_to_utf8 (const uint8_t *data, size_t data_len, int *out_is_error); + +/** + * Decodes UTF-8 data into UTF-16 data as bytes. + * + * @param data UTF-8 data + * @param data_len size of data in bytes + * @param out output buffer + * @param out_avail number of bytes available in output buffer + * @param out_len if not NULL, *out_len will contain the number of bytes + * required to store the resulting data (or overflow) + * @param out_is_error if not NULL, *out_is_error will contain 0 or 1, + * indicating whether there have been errors decoding + * the input + */ +static void unicode_decode_utf8_to_utf16 (const uint8_t *data, size_t data_len, uint8_t *out, size_t out_avail, bsize_t *out_len, int *out_is_error); + +static char * unicode_decode_utf16_to_utf8 (const uint8_t *data, size_t data_len, int *out_is_error) +{ + // will build the resulting UTF-8 string by appending to ExpString + ExpString str; + if (!ExpString_Init(&str)) { + goto fail0; + } + + // init UTF-16 decoder + Utf16Decoder decoder; + Utf16Decoder_Init(&decoder); + + // set initial input and input matching positions + size_t i_in = 0; + size_t i_ch = 0; + + int error = 0; + + while (i_in < data_len) { + // read two input bytes from the input position + uint8_t x = data[i_in++]; + if (i_in == data_len) { + break; + } + uint8_t y = data[i_in++]; + + // combine them into a 16-bit value + uint16_t xy = (((uint16_t)x << 8) | (uint16_t)y); + + // give the 16-bit value to the UTF-16 decoder and maybe + // receive a Unicode character back + uint32_t ch; + if (!Utf16Decoder_Input(&decoder, xy, &ch)) { + continue; + } + + if (!error) { + // encode the Unicode character back into UTF-16 + uint16_t chenc[2]; + int chenc_n = Utf16Encoder_EncodeCharacter(ch, chenc); + ASSERT(chenc_n > 0) + + // match the result with input + for (int chenc_i = 0; chenc_i < chenc_n; chenc_i++) { + uint8_t cx = (chenc[chenc_i] >> 8); + uint8_t cy = (chenc[chenc_i] & 0xFF); + + if (i_ch >= data_len || data[i_ch] != cx) { + error = 1; + break; + } + i_ch++; + + if (i_ch >= data_len || data[i_ch] != cy) { + error = 1; + break; + } + i_ch++; + } + } + + // we don't like null Unicode characters because we're building a + // null-terminated UTF-8 string + if (ch == 0) { + error = 1; + continue; + } + + // encode the Unicode character into UTF-8 + uint8_t enc[5]; + int enc_n = Utf8Encoder_EncodeCharacter(ch, enc); + ASSERT(enc_n > 0) + + // append the resulting UTF-8 bytes to the result string + enc[enc_n] = 0; + if (!ExpString_Append(&str, enc)) { + goto fail1; + } + } + + // check if we matched the whole input string when encoding back + if (i_ch < data_len) { + error = 1; + } + + if (out_is_error) { + *out_is_error = error; + } + return ExpString_Get(&str); + +fail1: + ExpString_Free(&str); +fail0: + return NULL; +} + +static void unicode_decode_utf8_to_utf16 (const uint8_t *data, size_t data_len, uint8_t *out, size_t out_avail, bsize_t *out_len, int *out_is_error) +{ + Utf8Decoder decoder; + Utf8Decoder_Init(&decoder); + + size_t i_in = 0; + size_t i_ch = 0; + + bsize_t len = bsize_fromsize(0); + + int error = 0; + + while (i_in < data_len) { + uint8_t x = data[i_in++]; + + uint32_t ch; + if (!Utf8Decoder_Input(&decoder, x, &ch)) { + continue; + } + + if (!error) { + uint8_t chenc[4]; + int chenc_n = Utf8Encoder_EncodeCharacter(ch, chenc); + ASSERT(chenc_n > 0) + + for (int chenc_i = 0; chenc_i < chenc_n; chenc_i++) { + if (i_ch >= data_len || data[i_ch] != chenc[chenc_i]) { + error = 1; + break; + } + i_ch++; + } + } + + uint16_t enc[2]; + int enc_n = Utf16Encoder_EncodeCharacter(ch, enc); + ASSERT(enc_n > 0) + + len = bsize_add(len, bsize_fromsize(2 * enc_n)); + + for (int enc_i = 0; enc_i < enc_n; enc_i++) { + if (out_avail == 0) { + break; + } + *(out++) = (enc[enc_i] >> 8); + out_avail--; + + if (out_avail == 0) { + break; + } + *(out++) = (enc[enc_i] & 0xFF); + out_avail--; + } + } + + if (i_ch < data_len) { + error = 1; + } + + if (out_len) { + *out_len = len; + } + if (out_is_error) { + *out_is_error = error; + } +} + +#endif diff --git a/Shared/lwip/badvpn/misc/version.h b/Shared/lwip/badvpn/misc/version.h new file mode 100644 index 0000000..1079ab0 --- /dev/null +++ b/Shared/lwip/badvpn/misc/version.h @@ -0,0 +1,41 @@ +/** + * @file version.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @section DESCRIPTION + * + * Product information definitions. + */ + +#ifndef BADVPN_MISC_VERSION_H +#define BADVPN_MISC_VERSION_H + +#define GLOBAL_PRODUCT_NAME "BadVPN" +#define GLOBAL_VERSION "1.999.130" +#define GLOBAL_COPYRIGHT_NOTICE "Copyright (C) 2010 Ambroz Bizjak " + +#endif diff --git a/Shared/lwip/badvpn/misc/write_file.h b/Shared/lwip/badvpn/misc/write_file.h new file mode 100644 index 0000000..50b323a --- /dev/null +++ b/Shared/lwip/badvpn/misc/write_file.h @@ -0,0 +1,70 @@ +/** + * @file write_file.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BADVPN_WRITE_FILE_H +#define BADVPN_WRITE_FILE_H + +#include +#include +#include + +#include +#include + +static int write_file (const char *file, MemRef data) +{ + FILE *f = fopen(file, "w"); + if (!f) { + goto fail0; + } + + while (data.len > 0) { + size_t res = fwrite(data.ptr, 1, data.len, f); + if (res == 0) { + goto fail1; + } + + ASSERT(res <= data.len) + + data = MemRef_SubFrom(data, res); + } + + if (fclose(f) != 0) { + return 0; + } + + return 1; + +fail1: + fclose(f); +fail0: + return 0; +} + +#endif diff --git a/Shared/lwip/custom/arch/cc.h b/Shared/lwip/custom/arch/cc.h new file mode 100644 index 0000000..a77edcc --- /dev/null +++ b/Shared/lwip/custom/arch/cc.h @@ -0,0 +1,98 @@ +/** + * @file cc.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_CUSTOM_CC_H +#define LWIP_CUSTOM_CC_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +//#include + +#define u8_t uint8_t +#define s8_t int8_t +#define u16_t uint16_t +#define s16_t int16_t +#define u32_t uint32_t +#define s32_t int32_t +#define mem_ptr_t uintptr_t + +#define PACK_STRUCT_BEGIN B_START_PACKED +#define PACK_STRUCT_END B_END_PACKED +#define PACK_STRUCT_STRUCT B_PACKED +extern void lwiplog(const char *fmt, ...); +extern void lwipassertlog(const char *fmt, ...); +//extern void testLog(NSString *f, int line,char *format,...); +//extern void surfLog(char *string,NSString *file,NSInteger line); +#define LWIP_PLATFORM_DIAG(x) {lwiplog x;} while(0) +//#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +//#define LWIP_PLATFORM_DIAG(x) { if (BLog_WouldLog(BLOG_CHANNEL_lwip, BLOG_INFO)) { BLog_Begin(); BLog_Append x; BLog_Finish(BLOG_CHANNEL_lwip, BLOG_INFO); } } +//#define LWIP_PLATFORM_ASSERT(x) { fprintf(stderr, "%s: lwip assertion failure: %s\n", __FUNCTION__, (x)); abort(); } +#define LWIP_PLATFORM_ASSERT(x) { lwipassertlog("%s Line %d] %s: lwip assertion failure: %s\n", __FILE__, __LINE__, __FUNCTION__,(x)); abort(); } +#define U8_F "c" +#define S8_F "c" +#define X8_F "x" +#define U16_F PRIu16 +#define S16_F PRId16 +#define X16_F PRIx16 +#define U32_F PRIu32 +#define S32_F PRId32 +#define X32_F PRIx32 +#define SZT_F "zu" + +#define LWIP_PLATFORM_BYTESWAP 1 +#define LWIP_PLATFORM_HTONS(x) hton16(x) +#define LWIP_PLATFORM_HTONL(x) hton32(x) + +#define LWIP_RAND() ( \ + (((uint32_t)(rand() & 0xFF)) << 24) | \ + (((uint32_t)(rand() & 0xFF)) << 16) | \ + (((uint32_t)(rand() & 0xFF)) << 8) | \ + (((uint32_t)(rand() & 0xFF)) << 0) \ +) + +// for BYTE_ORDER +#if defined(BADVPN_USE_WINAPI) && !defined(_MSC_VER) + #include +#elif defined(BADVPN_LINUX) + #include +#elif defined(BADVPN_FREEBSD) + #include +#else + #include +#endif + +#endif diff --git a/Shared/lwip/custom/arch/perf.h b/Shared/lwip/custom/arch/perf.h new file mode 100644 index 0000000..09c9d47 --- /dev/null +++ b/Shared/lwip/custom/arch/perf.h @@ -0,0 +1,36 @@ +/** + * @file perf.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_CUSTOM_PERF_H +#define LWIP_CUSTOM_PERF_H + +#define PERF_START +#define PERF_STOP(x) + +#endif diff --git a/Shared/lwip/custom/lwipopts.h b/Shared/lwip/custom/lwipopts.h new file mode 100644 index 0000000..d255b46 --- /dev/null +++ b/Shared/lwip/custom/lwipopts.h @@ -0,0 +1,120 @@ +/** + * @file lwipopts.h + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_CUSTOM_LWIPOPTS_H +#define LWIP_CUSTOM_LWIPOPTS_H + +#define NO_SYS 1 +#define MEM_ALIGNMENT 4 + + +#define LWIP_ARP 0 +#define ARP_QUEUEING 0 +#define IP_FORWARD 0 +#define LWIP_ICMP 1 +#define LWIP_RAW 0 +#define LWIP_DHCP 0 +#define LWIP_AUTOIP 0 +#define LWIP_SNMP 0 +#define LWIP_IGMP 0 +#define LWIP_DNS 0 +#define LWIP_UDP 1 +#define LWIP_UDPLITE 0 +#define LWIP_TCP 1 +#define LWIP_CALLBACK_API 1 +#define LWIP_NETIF_API 0 +#define LWIP_NETIF_LOOPBACK 0 +#define LWIP_HAVE_LOOPIF 0 +#define LWIP_HAVE_SLIPIF 0 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define PPP_SUPPORT 0 +#define LWIP_IPV6 1 +#define LWIP_IPV6_MLD 0 +#define LWIP_IPV6_AUTOCONFIG 0 +#define LWIP_STATS 0 +#define MEMP_NUM_TCP_PCB_LISTEN 1 +#define MEMP_NUM_TCP_PCB 8 +#ifdef TCP_MSS +#undef TCP_MSS +#define TCP_MSS 1460 +#endif +#define LWIP_CHECKSUM_ON_COPY 1 + + +// MEM +#define MEM_SIZE (1024 * 1024 * 1) /* 1MiB */ +#define MEMP_NUM_PBUF 16 +#define MEMP_NUM_RAW_PCB 64 +//#define MEMP_NUM_TCP_PCB 64 +//#define MEMP_NUM_TCP_PCB_LISTEN 8 +//#define MEMP_NUM_TCP_PCB_LISTEN 6 +//#define MEMP_NUM_TCP_PCB 10 +#define MEMP_NUM_TCP_SEG 64 +#define MEMP_NUM_REASSDATA 5 +#define MEMP_NUM_FRAG_PBUF 15 +#define PBUF_POOL_SIZE 512 + + //#define TCP_MSL 2500UL //60000UL +#define TCP_SND_BUF TCP_WND //16384//2920// 16384// (2*TCP_MSS) +#define TCP_SND_QUEUELEN (2 * (TCP_SND_BUF)/(TCP_MSS)) +//#define LWIP_TCPIP_TIMEOUT 0 +#define MEM_LIBC_MALLOC 1 +#define MEMP_MEM_MALLOC 1 +//#define MEM_SIZE 800 +//#define TCP_WND 0x2400//0xFFFF +#define TCP_WND 0x1FA0// (3 * TCP_MSS) +//#define LWIP_STATS_DISPLAY 1 + +#ifdef DEBUG +//#define LWIP_DEBUG +//#endif +//#ifdef LWIP_DEBUG +#define MEM_DEBUG LWIP_DBG_ON +#define MEMP_DEBUG LWIP_DBG_ON +#define TIMERS_DEBUG LWIP_DBG_ON +#define PBUF_DEBUG LWIP_DBG_ON +#define IP_DEBUG LWIP_DBG_ON +#define TCP_DEBUG LWIP_DBG_ON +#define TIMERS_DEBUG LWIP_DBG_ON +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#define TCP_INPUT_DEBUG LWIP_DBG_ON +#define TCP_FR_DEBUG LWIP_DBG_ON +#define TCP_RTO_DEBUG LWIP_DBG_ON +#define TCP_CWND_DEBUG LWIP_DBG_ON +#define TCP_WND_DEBUG LWIP_DBG_ON +#define TCP_FR_DEBUG LWIP_DBG_ON +//#define TCP_RST_DEBUG LWIP_DBG_ON +//#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#define TCP_RST_DEBUG LWIP_DBG_ON +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#define TCPIP_DEBUG LWIP_DBG_ON +#endif + +#endif diff --git a/Shared/lwip/custom/sys.c b/Shared/lwip/custom/sys.c new file mode 100644 index 0000000..9aeea5b --- /dev/null +++ b/Shared/lwip/custom/sys.c @@ -0,0 +1,42 @@ +/** + * @file sys.c + * @author Ambroz Bizjak + * + * @section LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//#include + +#include "lwip/sys.h" +#include +u32_t sys_now (void) +{ + struct timeval tv; + ASSERT(gettimeofday(&tv, NULL) == 0) + long long r = ((int64_t)tv.tv_sec * 1000 + (int64_t)tv.tv_usec/1000); + return (uint32_t)r; + + //return btime_gettime(); +} diff --git a/Shared/lwip/doc/FILES b/Shared/lwip/doc/FILES new file mode 100644 index 0000000..05d356f --- /dev/null +++ b/Shared/lwip/doc/FILES @@ -0,0 +1,6 @@ +savannah.txt - How to obtain the current development source code. +contrib.txt - How to contribute to lwIP as a developer. +rawapi.txt - The documentation for the core API of lwIP. + Also provides an overview about the other APIs and multithreading. +snmp_agent.txt - The documentation for the lwIP SNMP agent. +sys_arch.txt - The documentation for a system abstraction layer of lwIP. diff --git a/Shared/lwip/doc/contrib.txt b/Shared/lwip/doc/contrib.txt new file mode 100644 index 0000000..39596fc --- /dev/null +++ b/Shared/lwip/doc/contrib.txt @@ -0,0 +1,63 @@ +1 Introduction + +This document describes some guidelines for people participating +in lwIP development. + +2 How to contribute to lwIP + +Here is a short list of suggestions to anybody working with lwIP and +trying to contribute bug reports, fixes, enhancements, platform ports etc. +First of all as you may already know lwIP is a volunteer project so feedback +to fixes or questions might often come late. Hopefully the bug and patch tracking +features of Savannah help us not lose users' input. + +2.1 Source code style: + +1. do not use tabs. +2. indentation is two spaces per level (i.e. per tab). +3. end debug messages with a trailing newline (\n). +4. one space between keyword and opening bracket. +5. no space between function and opening bracket. +6. one space and no newline before opening curly braces of a block. +7. closing curly brace on a single line. +8. spaces surrounding assignment and comparisons. +9. don't initialize static and/or global variables to zero, the compiler takes care of that. +10. use current source code style as further reference. + +2.2 Source code documentation style: + +1. JavaDoc compliant and Doxygen compatible. +2. Function documentation above functions in .c files, not .h files. + (This forces you to synchronize documentation and implementation.) +3. Use current documentation style as further reference. + +2.3 Bug reports and patches: + +1. Make sure you are reporting bugs or send patches against the latest + sources. (From the latest release and/or the current CVS sources.) +2. If you think you found a bug make sure it's not already filed in the + bugtracker at Savannah. +3. If you have a fix put the patch on Savannah. If it is a patch that affects + both core and arch specific stuff please separate them so that the core can + be applied separately while leaving the other patch 'open'. The prefered way + is to NOT touch archs you can't test and let maintainers take care of them. + This is a good way to see if they are used at all - the same goes for unix + netifs except tapif. +4. Do not file a bug and post a fix to it to the patch area. Either a bug report + or a patch will be enough. + If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. +5. Trivial patches (compiler warning, indentation and spelling fixes or anything obvious which takes a line or two) + can go to the lwip-users list. This is still the fastest way of interaction and the list is not so crowded + as to allow for loss of fixes. Putting bugs on Savannah and subsequently closing them is too much an overhead + for reporting a compiler warning fix. +6. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other + trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you + change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than + if it's not to the point and long :) so the chances for it to be applied are greater. + +2.4 Platform porters: + +1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and + you think it could benefit others[1] you might want discuss this on the mailing list. You + can also ask for CVS access to submit and maintain your port in the contrib CVS module. + \ No newline at end of file diff --git a/Shared/lwip/doc/rawapi.txt b/Shared/lwip/doc/rawapi.txt new file mode 100644 index 0000000..8c19030 --- /dev/null +++ b/Shared/lwip/doc/rawapi.txt @@ -0,0 +1,511 @@ +Raw TCP/IP interface for lwIP + +Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons + +lwIP provides three Application Program's Interfaces (APIs) for programs +to use for communication with the TCP/IP code: +* low-level "core" / "callback" or "raw" API. +* higher-level "sequential" API. +* BSD-style socket API. + +The sequential API provides a way for ordinary, sequential, programs +to use the lwIP stack. It is quite similar to the BSD socket API. The +model of execution is based on the blocking open-read-write-close +paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP +code and the application program must reside in different execution +contexts (threads). + +The socket API is a compatibility API for existing applications, +currently it is built on top of the sequential API. It is meant to +provide all functions needed to run socket API applications running +on other platforms (e.g. unix / windows etc.). However, due to limitations +in the specification of this API, there might be incompatibilities +that require small modifications of existing programs. + +** Threading + +lwIP started targeting single-threaded environments. When adding multi- +threading support, instead of making the core thread-safe, another +approach was chosen: there is one main thread running the lwIP core +(also known as the "tcpip_thread"). The raw API may only be used from +this thread! Application threads using the sequential- or socket API +communicate with this main thread through message passing. + + As such, the list of functions that may be called from + other threads or an ISR is very limited! Only functions + from these API header files are thread-safe: + - api.h + - netbuf.h + - netdb.h + - netifapi.h + - sockets.h + - sys.h + + Additionaly, memory (de-)allocation functions may be + called from multiple threads (not ISR!) with NO_SYS=0 + since they are protected by SYS_LIGHTWEIGHT_PROT and/or + semaphores. + + Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1 + and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, + pbuf_free() may also be called from another thread or + an ISR (since only then, mem_free - for PBUF_RAM - may + be called from an ISR: otherwise, the HEAP is only + protected by semaphores). + + +** The remainder of this document discusses the "raw" API. ** + +The raw TCP/IP interface allows the application program to integrate +better with the TCP/IP code. Program execution is event based by +having callback functions being called from within the TCP/IP +code. The TCP/IP code and the application program both run in the same +thread. The sequential API has a much higher overhead and is not very +well suited for small systems since it forces a multithreaded paradigm +on the application. + +The raw TCP/IP interface is not only faster in terms of code execution +time but is also less memory intensive. The drawback is that program +development is somewhat harder and application programs written for +the raw TCP/IP interface are more difficult to understand. Still, this +is the preferred way of writing applications that should be small in +code size and memory usage. + +Both APIs can be used simultaneously by different application +programs. In fact, the sequential API is implemented as an application +program using the raw TCP/IP interface. + +--- Callbacks + +Program execution is driven by callbacks. Each callback is an ordinary +C function that is called from within the TCP/IP code. Every callback +function is passed the current TCP or UDP connection state as an +argument. Also, in order to be able to keep program specific state, +the callback functions are called with a program specified argument +that is independent of the TCP/IP state. + +The function for setting the application connection state is: + +- void tcp_arg(struct tcp_pcb *pcb, void *arg) + + Specifies the program specific state that should be passed to all + other callback functions. The "pcb" argument is the current TCP + connection control block, and the "arg" argument is the argument + that will be passed to the callbacks. + + +--- TCP connection setup + +The functions used for setting up connections is similar to that of +the sequential API and of the BSD socket API. A new TCP connection +identifier (i.e., a protocol control block - PCB) is created with the +tcp_new() function. This PCB can then be either set to listen for new +incoming connections or be explicitly connected to another host. + +- struct tcp_pcb *tcp_new(void) + + Creates a new connection identifier (PCB). If memory is not + available for creating the new pcb, NULL is returned. + +- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local IP address and port number. The IP address + can be specified as IP_ADDR_ANY in order to bind the connection to + all local IP addresses. + + If another connection is bound to the same port, the function will + return ERR_USE, otherwise ERR_OK is returned. + +- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) + + Commands a pcb to start listening for incoming connections. When an + incoming connection is accepted, the function specified with the + tcp_accept() function will be called. The pcb will have to be bound + to a local port with the tcp_bind() function. + + The tcp_listen() function returns a new connection identifier, and + the one passed as an argument to the function will be + deallocated. The reason for this behavior is that less memory is + needed for a connection that is listening, so tcp_listen() will + reclaim the memory needed for the original connection and allocate a + new smaller memory block for the listening connection. + + tcp_listen() may return NULL if no memory was available for the + listening connection. If so, the memory associated with the pcb + passed as an argument to tcp_listen() will not be deallocated. + +- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) + + Same as tcp_listen, but limits the number of outstanding connections + in the listen queue to the value specified by the backlog argument. + To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. + +- void tcp_accepted(struct tcp_pcb *pcb) + + Inform lwIP that an incoming connection has been accepted. This would + usually be called from the accept callback. This allows lwIP to perform + housekeeping tasks, such as allowing further incoming connections to be + queued in the listen backlog. + ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed + into the accept callback! + +- void tcp_accept(struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, + err_t err)) + + Specified the callback function that should be called when a new + connection arrives on a listening connection. + +- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, err_t (* connected)(void *arg, + struct tcp_pcb *tpcb, + err_t err)); + + Sets up the pcb to connect to the remote host and sends the + initial SYN segment which opens the connection. + + The tcp_connect() function returns immediately; it does not wait for + the connection to be properly setup. Instead, it will call the + function specified as the fourth argument (the "connected" argument) + when the connection is established. If the connection could not be + properly established, either because the other host refused the + connection or because the other host didn't answer, the "err" + callback function of this pcb (registered with tcp_err, see below) + will be called. + + The tcp_connect() function can return ERR_MEM if no memory is + available for enqueueing the SYN segment. If the SYN indeed was + enqueued successfully, the tcp_connect() function returns ERR_OK. + + +--- Sending TCP data + +TCP data is sent by enqueueing the data with a call to +tcp_write(). When the data is successfully transmitted to the remote +host, the application will be notified with a call to a specified +callback function. + +- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags) + + Enqueues the data pointed to by the argument dataptr. The length of + the data is passed as the len parameter. The apiflags can be one or more of: + - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated + for the data to be copied into. If this flag is not given, no new memory + should be allocated and the data should only be referenced by pointer. This + also means that the memory behind dataptr must not change until the data is + ACKed by the remote host + - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is given, + the PSH flag is set in the last segment created by this call to tcp_write. + If this flag is given, the PSH flag is not set. + + The tcp_write() function will fail and return ERR_MEM if the length + of the data exceeds the current send buffer size or if the length of + the queue of outgoing segment is larger than the upper limit defined + in lwipopts.h. The number of bytes available in the output queue can + be retrieved with the tcp_sndbuf() function. + + The proper way to use this function is to call the function with at + most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, + the application should wait until some of the currently enqueued + data has been successfully received by the other host and try again. + +- void tcp_sent(struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, + u16_t len)) + + Specifies the callback function that should be called when data has + successfully been received (i.e., acknowledged) by the remote + host. The len argument passed to the callback function gives the + amount bytes that was acknowledged by the last acknowledgment. + + +--- Receiving TCP data + +TCP data reception is callback based - an application specified +callback function is called when new data arrives. When the +application has taken the data, it has to call the tcp_recved() +function to indicate that TCP can advertise increase the receive +window. + +- void tcp_recv(struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err)) + + Sets the callback function that will be called when new data + arrives. The callback function will be passed a NULL pbuf to + indicate that the remote host has closed the connection. If + there are no errors and the callback function is to return + ERR_OK, then it must free the pbuf. Otherwise, it must not + free the pbuf so that lwIP core code can store it. + +- void tcp_recved(struct tcp_pcb *pcb, u16_t len) + + Must be called when the application has received the data. The len + argument indicates the length of the received data. + + +--- Application polling + +When a connection is idle (i.e., no data is either transmitted or +received), lwIP will repeatedly poll the application by calling a +specified callback function. This can be used either as a watchdog +timer for killing connections that have stayed idle for too long, or +as a method of waiting for memory to become available. For instance, +if a call to tcp_write() has failed because memory wasn't available, +the application may use the polling functionality to call tcp_write() +again when the connection has been idle for a while. + +- void tcp_poll(struct tcp_pcb *pcb, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb), + u8_t interval) + + Specifies the polling interval and the callback function that should + be called to poll the application. The interval is specified in + number of TCP coarse grained timer shots, which typically occurs + twice a second. An interval of 10 means that the application would + be polled every 5 seconds. + + +--- Closing and aborting connections + +- err_t tcp_close(struct tcp_pcb *pcb) + + Closes the connection. The function may return ERR_MEM if no memory + was available for closing the connection. If so, the application + should wait and try again either by using the acknowledgment + callback or the polling functionality. If the close succeeds, the + function returns ERR_OK. + + The pcb is deallocated by the TCP code after a call to tcp_close(). + +- void tcp_abort(struct tcp_pcb *pcb) + + Aborts the connection by sending a RST (reset) segment to the remote + host. The pcb is deallocated. This function never fails. + + ATTENTION: When calling this from one of the TCP callbacks, make + sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + or you will risk accessing deallocated memory or memory leaks! + + +If a connection is aborted because of an error, the application is +alerted of this event by the err callback. Errors that might abort a +connection are when there is a shortage of memory. The callback +function to be called is set using the tcp_err() function. + +- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, + err_t err)) + + The error callback function does not get the pcb passed to it as a + parameter since the pcb may already have been deallocated. + + +--- Lower layer TCP interface + +TCP provides a simple interface to the lower layers of the +system. During system initialization, the function tcp_init() has +to be called before any other TCP function is called. When the system +is running, the two timer functions tcp_fasttmr() and tcp_slowtmr() +must be called with regular intervals. The tcp_fasttmr() should be +called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and +tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds. + + +--- UDP interface + +The UDP interface is similar to that of TCP, but due to the lower +level of complexity of UDP, the interface is significantly simpler. + +- struct udp_pcb *udp_new(void) + + Creates a new UDP pcb which can be used for UDP communication. The + pcb is not active until it has either been bound to a local address + or connected to a remote address. + +- void udp_remove(struct udp_pcb *pcb) + + Removes and deallocates the pcb. + +- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local address. The IP-address argument "ipaddr" + can be IP_ADDR_ANY to indicate that it should listen to any local IP + address. The function currently always return ERR_OK. + +- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Sets the remote end of the pcb. This function does not generate any + network traffic, but only set the remote address of the pcb. + +- err_t udp_disconnect(struct udp_pcb *pcb) + + Remove the remote end of the pcb. This function does not generate + any network traffic, but only removes the remote address of the pcb. + +- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) + + Sends the pbuf p. The pbuf is not deallocated. + +- void udp_recv(struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, + struct pbuf *p, + ip_addr_t *addr, + u16_t port), + void *recv_arg) + + Specifies a callback function that should be called when a UDP + datagram is received. + + +--- System initalization + +A truly complete and generic sequence for initializing the lwip stack +cannot be given because it depends on the build configuration (lwipopts.h) +and additional initializations for your runtime environment (e.g. timers). + +We can give you some idea on how to proceed when using the raw API. +We assume a configuration using a single Ethernet netif and the +UDP and TCP transport layers, IPv4 and the DHCP client. + +Call these functions in the order of appearance: + +- stats_init() + + Clears the structure where runtime statistics are gathered. + +- sys_init() + + Not of much use since we set the NO_SYS 1 option in lwipopts.h, + to be called for easy configuration changes. + +- mem_init() + + Initializes the dynamic memory heap defined by MEM_SIZE. + +- memp_init() + + Initializes the memory pools defined by MEMP_NUM_x. + +- pbuf_init() + + Initializes the pbuf memory pool defined by PBUF_POOL_SIZE. + +- etharp_init() + + Initializes the ARP table and queue. + Note: you must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval + after this initialization. + +- ip_init() + + Doesn't do much, it should be called to handle future changes. + +- udp_init() + + Clears the UDP PCB list. + +- tcp_init() + + Clears the TCP PCB list and clears some internal TCP timers. + Note: you must call tcp_fasttmr() and tcp_slowtmr() at the + predefined regular intervals after this initialization. + +- netif_add(struct netif *netif, ip_addr_t *ipaddr, + ip_addr_t *netmask, ip_addr_t *gw, + void *state, err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) + + Adds your network interface to the netif_list. Allocate a struct + netif and pass a pointer to this structure as the first argument. + Give pointers to cleared ip_addr structures when using DHCP, + or fill them with sane numbers otherwise. The state pointer may be NULL. + + The init function pointer must point to a initialization function for + your ethernet netif interface. The following code illustrates it's use. + + err_t netif_if_init(struct netif *netif) + { + u8_t i; + + for(i = 0; i < ETHARP_HWADDR_LEN; i++) netif->hwaddr[i] = some_eth_addr[i]; + init_my_eth_device(); + return ERR_OK; + } + + For ethernet drivers, the input function pointer must point to the lwip + function ethernet_input() declared in "netif/etharp.h". Other drivers + must use ip_input() declared in "lwip/ip.h". + +- netif_set_default(struct netif *netif) + + Registers the default network interface. + +- netif_set_up(struct netif *netif) + + When the netif is fully configured this function must be called. + +- dhcp_start(struct netif *netif) + + Creates a new DHCP client for this interface on the first call. + Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at + the predefined regular intervals after starting the client. + + You can peek in the netif->dhcp struct for the actual DHCP status. + + +--- Optimalization hints + +The first thing you want to optimize is the lwip_standard_checksum() +routine from src/core/inet.c. You can override this standard +function with the #define LWIP_CHKSUM . + +There are C examples given in inet.c or you might want to +craft an assembly function for this. RFC1071 is a good +introduction to this subject. + +Other significant improvements can be made by supplying +assembly or inline replacements for htons() and htonl() +if you're using a little-endian architecture. +#define LWIP_PLATFORM_BYTESWAP 1 +#define LWIP_PLATFORM_HTONS(x) +#define LWIP_PLATFORM_HTONL(x) + +Check your network interface driver if it reads at +a higher speed than the maximum wire-speed. If the +hardware isn't serviced frequently and fast enough +buffer overflows are likely to occur. + +E.g. when using the cs8900 driver, call cs8900if_service(ethif) +as frequently as possible. When using an RTOS let the cs8900 interrupt +wake a high priority task that services your driver using a binary +semaphore or event flag. Some drivers might allow additional tuning +to match your application and network. + +For a production release it is recommended to set LWIP_STATS to 0. +Note that speed performance isn't influenced much by simply setting +high values to the memory options. + +For more optimization hints take a look at the lwIP wiki. + +--- Zero-copy MACs + +To achieve zero-copy on transmit, the data passed to the raw API must +remain unchanged until sent. Because the send- (or write-)functions return +when the packets have been enqueued for sending, data must be kept stable +after that, too. + +This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions +must *not* be reused by the application unless their ref-count is 1. + +For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, +but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while +PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). + +Also, data passed to tcp_write without the copy-flag must not be changed! + +Therefore, be careful which type of PBUF you use and if you copy TCP data +or not! diff --git a/Shared/lwip/doc/savannah.txt b/Shared/lwip/doc/savannah.txt new file mode 100644 index 0000000..409905b --- /dev/null +++ b/Shared/lwip/doc/savannah.txt @@ -0,0 +1,135 @@ +Daily Use Guide for using Savannah for lwIP + +Table of Contents: + +1 - Obtaining lwIP from the CVS repository +2 - Committers/developers CVS access using SSH (to be written) +3 - Merging from DEVEL branch to main trunk (stable branch) +4 - How to release lwIP + + + +1 Obtaining lwIP from the CVS repository +---------------------------------------- + +To perform an anonymous CVS checkout of the main trunk (this is where +bug fixes and incremental enhancements occur), do this: + +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip + +Or, obtain a stable branch (updated with bug fixes only) as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7 -d lwip-0.7 lwip + +Or, obtain a specific (fixed) release as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7_0 -d lwip-0.7.0 lwip + +3 Committers/developers CVS access using SSH +-------------------------------------------- + +The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. +As such, CVS commits to the server occur through a SSH tunnel for project members. +To create a SSH2 key pair in UNIX-like environments, do this: + +ssh-keygen -t dsa + +Under Windows, a recommended SSH client is "PuTTY", freely available with good +documentation and a graphic user interface. Use its key generator. + +Now paste the id_dsa.pub contents into your Savannah account public key list. Wait +a while so that Savannah can update its configuration (This can take minutes). + +Try to login using SSH: + +ssh -v your_login@cvs.sv.gnu.org + +If it tells you: + +Authenticating with public key "your_key_name"... +Server refused to allocate pty + +then you could login; Savannah refuses to give you a shell - which is OK, as we +are allowed to use SSH for CVS only. Now, you should be able to do this: + +export CVS_RSH=ssh +cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip + +after which you can edit your local files with bug fixes or new features and +commit them. Make sure you know what you are doing when using CVS to make +changes on the repository. If in doubt, ask on the lwip-members mailing list. + +(If SSH asks about authenticity of the host, you can check the key + fingerprint against http://savannah.nongnu.org/cvs/?group=lwip) + + +3 Merging from DEVEL branch to main trunk (stable) +-------------------------------------------------- + +Merging is a delicate process in CVS and requires the +following disciplined steps in order to prevent conflicts +in the future. Conflicts can be hard to solve! + +Merging from branch A to branch B requires that the A branch +has a tag indicating the previous merger. This tag is called +'merged_from_A_to_B'. After merging, the tag is moved in the +A branch to remember this merger for future merge actions. + +IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE +REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE +MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME). + +Merge all changes in DEVEL since our last merge to main: + +In the working copy of the main trunk: +cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL + +(This will apply the changes between 'merged_from_DEVEL_to_main' +and 'DEVEL' to your work set of files) + +We can now commit the merge result. +cvs commit -R -m "Merged from DEVEL to main." + +If this worked out OK, we now move the tag in the DEVEL branch +to this merge point, so we can use this point for future merges: + +cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip + +4 How to release lwIP +--------------------- + +First, checkout a clean copy of the branch to be released. Tag this set with +tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example). + +Login CVS using pserver authentication, then export a clean copy of the +tagged tree. Export is similar to a checkout, except that the CVS metadata +is not created locally. + +export CVS_RSH=ssh +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_6_3 -d lwip-0.6.3 lwip + +Archive this directory using tar, gzip'd, bzip2'd and zip'd. + +tar czvf lwip-0.6.3.tar.gz lwip-0.6.3 +tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3 +zip -r lwip-0.6.3.zip lwip-0.6.3 + +Now, sign the archives with a detached GPG binary signature as follows: + +gpg -b lwip-0.6.3.tar.gz +gpg -b lwip-0.6.3.tar.bz2 +gpg -b lwip-0.6.3.zip + +Upload these files using anonymous FTP: +ncftp ftp://savannah.gnu.org/incoming/savannah/lwip + +ncftp>mput *0.6.3.* + +Additionally, you may post a news item on Savannah, like this: + +A new 0.6.3 release is now available here: +http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3 + +You will have to submit this via the user News interface, then approve +this via the Administrator News interface. \ No newline at end of file diff --git a/Shared/lwip/doc/snmp_agent.txt b/Shared/lwip/doc/snmp_agent.txt new file mode 100644 index 0000000..2653230 --- /dev/null +++ b/Shared/lwip/doc/snmp_agent.txt @@ -0,0 +1,181 @@ +SNMPv1 agent for lwIP + +Author: Christiaan Simons + +This is a brief introduction how to use and configure the SNMP agent. +Note the agent uses the raw-API UDP interface so you may also want to +read rawapi.txt to gain a better understanding of the SNMP message handling. + +0 Agent Capabilities +==================== + +SNMPv1 per RFC1157 + This is an old(er) standard but is still widely supported. + For SNMPv2c and v3 have a greater complexity and need many + more lines of code. IMHO this breaks the idea of "lightweight IP". + + Note the S in SNMP stands for "Simple". Note that "Simple" is + relative. SNMP is simple compared to the complex ISO network + management protocols CMIP (Common Management Information Protocol) + and CMOT (CMip Over Tcp). + +MIB II per RFC1213 + The standard lwIP stack management information base. + This is a required MIB, so this is always enabled. + When builing lwIP without TCP, the mib-2.tcp group is omitted. + The groups EGP, CMOT and transmission are disabled by default. + + Most mib-2 objects are not writable except: + sysName, sysLocation, sysContact, snmpEnableAuthenTraps. + Writing to or changing the ARP and IP address and route + tables is not possible. + + Note lwIP has a very limited notion of IP routing. It currently + doen't have a route table and doesn't have a notion of the U,G,H flags. + Instead lwIP uses the interface list with only one default interface + acting as a single gateway interface (G) for the default route. + + The agent returns a "virtual table" with the default route 0.0.0.0 + for the default interface and network routes (no H) for each + network interface in the netif_list. + All routes are considered to be up (U). + +Loading additional MIBs + MIBs can only be added in compile-time, not in run-time. + There is no MIB compiler thus additional MIBs must be hand coded. + +Large SNMP message support + The packet decoding and encoding routines are designed + to use pbuf-chains. Larger payloads than the minimum + SNMP requirement of 484 octets are supported if the + PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your + local requirement. + +1 Building the Agent +==================== + +First of all you'll need to add the following define +to your local lwipopts.h: + +#define LWIP_SNMP 1 + +and add the source files in lwip/src/core/snmp +and some snmp headers in lwip/src/include/lwip to your makefile. + +Note you'll might need to adapt you network driver to update +the mib2 variables for your interface. + +2 Running the Agent +=================== + +The following function calls must be made in your program to +actually get the SNMP agent running. + +Before starting the agent you should supply pointers +to non-volatile memory for sysContact, sysLocation, +and snmpEnableAuthenTraps. You can do this by calling + +snmp_set_syscontact() +snmp_set_syslocation() +snmp_set_snmpenableauthentraps() + +Additionally you may want to set + +snmp_set_sysdescr() +snmp_set_sysobjid() (if you have a private MIB) +snmp_set_sysname() + +Also before starting the agent you need to setup +one or more trap destinations using these calls: + +snmp_trap_dst_enable(); +snmp_trap_dst_ip_set(); + +In the lwIP initialisation sequence call snmp_init() just after +the call to udp_init(). + +Exactly every 10 msec the SNMP uptime timestamp must be updated with +snmp_inc_sysuptime(). You should call this from a timer interrupt +or a timer signal handler depending on your runtime environment. + +An alternative way to update the SNMP uptime timestamp is to do a call like +snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but call to +a lower frequency). Another one is to not call snmp_inc_sysuptime() or +snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. +This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside +snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only +when it's queried (any function which need "sysuptime" have to call +snmp_get_sysuptime). + + +3 Private MIBs +============== + +If want to extend the agent with your own private MIB you'll need to +add the following define to your local lwipopts.h: + +#define SNMP_PRIVATE_MIB 1 + +You must provide the private_mib.h and associated files yourself. +Note we don't have a "MIB compiler" that generates C source from a MIB, +so you're required to do some serious coding if you enable this! + +Note the lwIP enterprise ID (26381) is assigned to the lwIP project, +ALL OBJECT IDENTIFIERS LIVING UNDER THIS ID ARE ASSIGNED BY THE lwIP +MAINTAINERS! + +If you need to create your own private MIB you'll need +to apply for your own enterprise ID with IANA: http://www.iana.org/numbers.html + +You can set it by passing a struct snmp_obj_id to the agent +using snmp_set_sysobjid(&my_object_id), just before snmp_init(). + +Note the object identifiers for thes MIB-2 and your private MIB +tree must be kept in sorted ascending (lexicographical) order. +This to ensure correct getnext operation. + +An example for a private MIB is part of the "minimal Unix" project: +contrib/ports/unix/proj/minimal/lwip_prvmib.c + +The next chapter gives a more detailed description of the +MIB-2 tree and the optional private MIB. + +4 The Gory Details +================== + +4.0 Object identifiers and the MIB tree. + +We have three distinct parts for all object identifiers: + +The prefix + .iso.org.dod.internet + +the middle part + .mgmt.mib-2.ip.ipNetToMediaTable.ipNetToMediaEntry.ipNetToMediaPhysAddress + +and the index part + .1.192.168.0.1 + +Objects located above the .internet hierarchy aren't supported. +Currently only the .mgmt sub-tree is available and +when the SNMP_PRIVATE_MIB is enabled the .private tree +becomes available too. + +Object identifiers from incoming requests are checked +for a matching prefix, middle part and index part +or are expanded(*) for GetNext requests with short +or inexisting names in the request. +(* we call this "expansion" but this also +resembles the "auto-completion" operation) + +The middle part is usually located in ROM (const) +to preserve precious RAM on small microcontrollers. +However RAM location is possible for a dynamically +changing private tree. + +The index part is handled by functions which in +turn use dynamically allocated index trees from RAM. +These trees are updated by e.g. the etharp code +when new entries are made or removed form the ARP cache. + +/** @todo more gory details */ diff --git a/Shared/lwip/doc/sys_arch.txt b/Shared/lwip/doc/sys_arch.txt new file mode 100644 index 0000000..847cd77 --- /dev/null +++ b/Shared/lwip/doc/sys_arch.txt @@ -0,0 +1,267 @@ +sys_arch interface for lwIP 0.6++ + +Author: Adam Dunkels + +The operating system emulation layer provides a common interface +between the lwIP code and the underlying operating system kernel. The +general idea is that porting lwIP to new architectures requires only +small changes to a few header files and a new sys_arch +implementation. It is also possible to do a sys_arch implementation +that does not rely on any underlying operating system. + +The sys_arch provides semaphores and mailboxes to lwIP. For the full +lwIP functionality, multiple threads support can be implemented in the +sys_arch, but this is not required for the basic lwIP +functionality. Previous versions of lwIP required the sys_arch to +implement timer scheduling as well but as of lwIP 0.5 this is +implemented in a higher layer. + +In addition to the source file providing the functionality of sys_arch, +the OS emulation layer must provide several header files defining +macros used throughout lwip. The files required and the macros they +must define are listed below the sys_arch description. + +Semaphores can be either counting or binary - lwIP works with both +kinds. Mailboxes are used for message passing and can be implemented +either as a queue which allows multiple messages to be posted to a +mailbox, or as a rendez-vous point where only one message can be +posted at a time. lwIP works with both kinds, but the former type will +be more efficient. A message in a mailbox is just a pointer, nothing +more. + +Semaphores are represented by the type "sys_sem_t" which is typedef'd +in the sys_arch.h file. Mailboxes are equivalently represented by the +type "sys_mbox_t". lwIP does not place any restrictions on how +sys_sem_t or sys_mbox_t are represented internally. + +Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that +allows both using pointers or actual OS structures to be used. This way, memory +required for such types can be either allocated in place (globally or on the +stack) or on the heap (allocated internally in the "*_new()" functions). + +The following functions must be implemented by the sys_arch: + +- void sys_init(void) + + Is called to initialize the sys_arch layer. + +- err_t sys_sem_new(sys_sem_t *sem, u8_t count) + + Creates a new semaphore. The semaphore is allocated to the memory that 'sem' + points to (which can be both a pointer or the actual OS structure). + The "count" argument specifies the initial state of the semaphore (which is + either 0 or 1). + If the semaphore has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_sem_free(sys_sem_t *sem) + + Deallocates a semaphore. + +- void sys_sem_signal(sys_sem_t *sem) + + Signals a semaphore. + +- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) + + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). If the "timeout" argument is zero, the thread should be + blocked until the semaphore is signalled. + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. + +- int sys_sem_valid(sys_sem_t *sem) + + Returns 1 if the semaphore is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_sem_set_invalid(sys_sem_t *sem) + + Invalidate a semaphore so that sys_sem_valid() returns 0. + ATTENTION: This does NOT mean that the semaphore shall be deallocated: + sys_sem_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +- err_t sys_mbox_new(sys_mbox_t *mbox, int size) + + Creates an empty mailbox for maximum "size" elements. Elements stored + in mailboxes are pointers. You have to define macros "_MBOX_SIZE" + in your lwipopts.h, or ignore this parameter in your implementation + and use a default size. + If the mailbox has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_mbox_free(sys_mbox_t *mbox) + + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. + +- void sys_mbox_post(sys_mbox_t *mbox, void *msg) + + Posts the "msg" to the mailbox. This function have to block until + the "msg" is really posted. + +- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) + + Try to post the "msg" to the mailbox. Returns ERR_MEM if this one + is full, else, ERR_OK if the "msg" is posted. + +- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) + + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). If "timeout" is 0, the thread should + be blocked until a message arrives. The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. + +- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) + + This is similar to sys_arch_mbox_fetch, however if a message is not + present in the mailbox, it immediately returns with the code + SYS_MBOX_EMPTY. On success 0 is returned. + + To allow for efficient implementations, this can be defined as a + function-like macro in sys_arch.h instead of a normal function. For + example, a naive implementation could be: + #define sys_arch_mbox_tryfetch(mbox,msg) \ + sys_arch_mbox_fetch(mbox,msg,1) + although this would introduce unnecessary delays. + +- int sys_mbox_valid(sys_mbox_t *mbox) + + Returns 1 if the mailbox is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_mbox_set_invalid(sys_mbox_t *mbox) + + Invalidate a mailbox so that sys_mbox_valid() returns 0. + ATTENTION: This does NOT mean that the mailbox shall be deallocated: + sys_mbox_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +If threads are supported by the underlying operating system and if +such functionality is needed in lwIP, the following function will have +to be implemented as well: + +- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) + + Starts a new thread named "name" with priority "prio" that will begin its + execution in the function "thread()". The "arg" argument will be passed as an + argument to the thread() function. The stack size to used for this thread is + the "stacksize" parameter. The id of the new thread is returned. Both the id + and the priority are system dependent. + +- sys_prot_t sys_arch_protect(void) + + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. + +- void sys_arch_unprotect(sys_prot_t pval) + + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. + +For some configurations, you also need: + +- u32_t sys_now(void) + + This optional function returns the current time in milliseconds (don't care + for wraparound, this is only used for time diffs). + Not implementing this function means you cannot use some modules (e.g. TCP + timestamps, internal timeouts for NO_SYS==1). + + +Note: + +Be carefull with using mem_malloc() in sys_arch. When malloc() refers to +mem_malloc() you can run into a circular function call problem. In mem.c +mem_init() tries to allcate a semaphore using mem_malloc, which of course +can't be performed when sys_arch uses mem_malloc. + +------------------------------------------------------------------------------- +Additional files required for the "OS support" emulation layer: +------------------------------------------------------------------------------- + +cc.h - Architecture environment, some compiler specific, some + environment specific (probably should move env stuff + to sys_arch.h.) + + Typedefs for the types used by lwip - + u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t + + Compiler hints for packing lwip's structures - + PACK_STRUCT_FIELD(x) + PACK_STRUCT_STRUCT + PACK_STRUCT_BEGIN + PACK_STRUCT_END + + Platform specific diagnostic output - + LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. + LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. + Portability defines for printf formatters: + U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F + + "lightweight" synchronization mechanisms - + SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. + SYS_ARCH_PROTECT(x) - enter protection mode. + SYS_ARCH_UNPROTECT(x) - leave protection mode. + + If the compiler does not provide memset() this file must include a + definition of it, or include a file which defines it. + + This file must either include a system-local which defines + the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO + to make lwip/arch.h define the codes which are used throughout. + + +perf.h - Architecture specific performance measurement. + Measurement calls made throughout lwip, these can be defined to nothing. + PERF_START - start measuring something. + PERF_STOP(x) - stop measuring something, and record the result. + +sys_arch.h - Tied to sys_arch.c + + Arch dependent types for the following objects: + sys_sem_t, sys_mbox_t, sys_thread_t, + And, optionally: + sys_prot_t + + Defines to set vars of sys_mbox_t and sys_sem_t to NULL. + SYS_MBOX_NULL NULL + SYS_SEM_NULL NULL diff --git a/Shared/lwip/lwip-base-version b/Shared/lwip/lwip-base-version new file mode 100644 index 0000000..b48d5b6 --- /dev/null +++ b/Shared/lwip/lwip-base-version @@ -0,0 +1 @@ +666e84eef281d0059377d0f5029c1c550488f829 diff --git a/Shared/lwip/src/core/def.c b/Shared/lwip/src/core/def.c new file mode 100644 index 0000000..352b552 --- /dev/null +++ b/Shared/lwip/src/core/def.c @@ -0,0 +1,108 @@ +/** + * @file + * Common functions used throughout the stack. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +/** + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * #define LWIP_PLATFORM_BYTESWAP 1 + * #define LWIP_PLATFORM_HTONS(x) + * #define LWIP_PLATFORM_HTONL(x) + * + * Note ntohs() and ntohl() are merely references to the htonx counterparts. + */ + +#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) + +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); +} + +/** + * Convert an u16_t from network- to host byte order. + * + * @param n u16_t in network byte order + * @return n in host byte order + */ +u16_t +lwip_ntohs(u16_t n) +{ + return lwip_htons(n); +} + +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +/** + * Convert an u32_t from network- to host byte order. + * + * @param n u32_t in network byte order + * @return n in host byte order + */ +u32_t +lwip_ntohl(u32_t n) +{ + return lwip_htonl(n); +} + +#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/Shared/lwip/src/core/inet_chksum.c b/Shared/lwip/src/core/inet_chksum.c new file mode 100644 index 0000000..8bc42c1 --- /dev/null +++ b/Shared/lwip/src/core/inet_chksum.c @@ -0,0 +1,545 @@ +/** + * @file + * Incluse internet checksum functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" + +#include +#include + +/* These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * #define LWIP_CHKSUM + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +u16_t lwip_standard_chksum(void *dataptr, int len); +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +u16_t +lwip_standard_chksum(void *dataptr, u16_t len) +{ + u32_t acc; + u16_t src; + u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ + +u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (u16_t *)(void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ + +u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (u16_t *)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (u32_t *)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + + /* iterate through all pbuf in chain */ + for(q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip_addr_t *src, ip_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dst destination ipv6 address (used for checksum of pseudo header) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip6_addr_t *src, ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV6 */ + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + u16_t chklen; + + /* iterate through all pbuf in chain */ + for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo_partial: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. Will only compute for a + * portion of the payload. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dst destination ipv6 address (used for checksum of pseudo header) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param chksum_len number of payload bytes used to compute chksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + return ~LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/Shared/lwip/src/core/init.c b/Shared/lwip/src/core/init.c new file mode 100644 index 0000000..c24c027 --- /dev/null +++ b/Shared/lwip/src/core/init.c @@ -0,0 +1,345 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp_msg.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/timers.h" +#include "netif/etharp.h" +#include "lwip/ip6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/api.h" + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_IGMP) + #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (!LWIP_NETCONN && LWIP_SOCKET) + #error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0)) + #error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT + #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) + #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF + #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_ACCEPTCONN != SOF_ACCEPTCONN + #error "SO_ACCEPTCONN != SOF_ACCEPTCONN" +#endif +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#if SO_LINGER != SOF_LINGER + #error "WARNING: SO_LINGER != SOF_LINGER" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef MEMP_NUM_API_MSG + #error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN +#if MEMP_MEM_MALLOC +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* MEMP_MEM_MALLOC */ +#endif /* LWIP_NETCONN */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ + +/** + * Perform Sanity check of user-configurable values, and initialize all modules. + */ +void +lwip_init(void) +{ + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_SOCKET + lwip_socket_init(); +#endif /* LWIP_SOCKET */ + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_SNMP + snmp_init(); +#endif /* LWIP_SNMP */ +#if LWIP_AUTOIP + autoip_init(); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + ip6_init(); + nd6_init(); +#if LWIP_IPV6_MLD + mld6_init(); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/Shared/lwip/src/core/ipv4/icmp.c b/Shared/lwip/src/core/ipv4/icmp.c new file mode 100644 index 0000000..af47153 --- /dev/null +++ b/Shared/lwip/src/core/ipv4/icmp.c @@ -0,0 +1,338 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the icmp header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + s16_t hlen; + + ICMP_STATS_INC(icmp.recv); + snmp_inc_icmpinmsgs(); + + iphdr = (struct ip_hdr *)ip_current_header(); + hlen = IPH_HL(iphdr) * 4; + if (p->len < sizeof(u16_t)*2) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + break; + case ICMP_ECHO: +#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING + { + int accepted = 1; +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip_addr_ismulticast(ip_current_dest_addr())) { + accepted = 0; + } +#endif /* LWIP_MULTICAST_PING */ +#if !LWIP_BROADCAST_PING + /* broadcast destination address? */ + if (ip_addr_isbroadcast(ip_current_dest_addr(), inp)) { + accepted = 0; + } +#endif /* LWIP_BROADCAST_PING */ + /* broadcast or multicast destination address not acceptd? */ + if (!accepted) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); + ICMP_STATS_INC(icmp.err); + pbuf_free(p); + return; + } + } +#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + snmp_inc_icmpinerrors(); + return; + } +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* switch p->payload to ip header */ + if (pbuf_header(p, hlen)) { + LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0); + goto memerr; + } + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto memerr; + } + LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", + (r->len >= hlen + sizeof(struct icmp_echo_hdr))); + /* copy the whole packet including ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); + goto memerr; + } + iphdr = (struct ip_hdr *)r->payload; + /* switch r->payload back to icmp header */ + if (pbuf_header(r, -hlen)) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header */ + if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + ip_addr_copy(iphdr->src, *ip_current_dest_addr()); + ip_addr_copy(iphdr->dest, *ip_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + /* adjust the checksum */ + if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of echo replies attempted to send */ + snmp_inc_icmpoutechoreps(); + + if(pbuf_header(p, hlen)) { + LWIP_ASSERT("Can't move over header in packet", 0); + } else { + err_t ret; + /* send an ICMP packet, src addr is the dest addr of the curren packet */ + ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); + } + } + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + snmp_inc_icmpinerrors(); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +memerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + snmp_inc_icmpinerrors(); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip_addr_t iphdr_src; + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + /* calculate checksum */ + icmphdr->chksum = 0; + icmphdr->chksum = inet_chksum(icmphdr, q->len); + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of destination unreachable messages attempted to send */ + snmp_inc_icmpouttimeexcds(); + ip_addr_copy(iphdr_src, iphdr->src); + ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/Shared/lwip/src/core/ipv4/ip4.c b/Shared/lwip/src/core/ipv4/ip4.c new file mode 100644 index 0000000..1acc255 --- /dev/null +++ b/Shared/lwip/src/core/ipv4/ip4.c @@ -0,0 +1,924 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#define LWIP_INLINE_IP_CHKSUM 1 +#endif +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** Global data for both IPv4 and IPv6 */ +struct ip_globals ip_data; + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip_route(ip_addr_t *dest) +{ + struct netif *netif; + +#ifdef LWIP_HOOK_IP4_ROUTE + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* network mask matches? */ + if (netif_is_up(netif)) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + if ((netif_default == NULL) || (!netif_is_up(netif_default))) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + snmp_inc_ipoutnoroutes(); + return NULL; + } + /* no matching netif found, use default netif */ + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @param dest the destination IP address + * @return 1: can forward 0: discard + */ +static int +ip_canforward(struct pbuf *p) +{ + u32_t addr = htonl(ip4_addr_get_u32(ip_current_dest_addr())); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + + if (!ip_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip_addr_islinklocal(ip_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), + ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip_route(ip_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), + ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + snmp_inc_ipinhdrerrors(); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), + ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + snmp_inc_ipforwdatagrams(); + + PERF_STOP("ip_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip_frag(p, netif, ip_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { + /* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ip_current_dest_addr()); + return; +return_noroute: + snmp_inc_ipoutnoroutes(); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP_STATS_INC(ip.recv); + snmp_inc_ipinreceives(); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = ntohs(IPH_LEN(iphdr)); + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipindiscards(); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } +#endif + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, iphdr_len); + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_dest), iphdr->dest); + ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_src), iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(ip_current_dest_addr())) { + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip_current_dest_addr()))) { + netif = inp; + } else { + netif = NULL; + } + } else +#endif /* LWIP_IGMP */ + { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { + /* unicast to this interface address? */ + if (ip_addr_cmp(ip_current_dest_addr(), &(netif->ip_addr)) || + /* or broadcast on this interface network address? */ + ip_addr_isbroadcast(ip_current_dest_addr(), netif)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if ((netif->autoip != NULL) && + ip_addr_cmp(ip_current_dest_addr(), &(netif->autoip->llipaddr))) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", + ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + if (check_ip_src && !ip_addr_isany(ip_current_src_addr())) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { if ((ip_addr_isbroadcast(ip_current_src_addr(), inp)) || + (ip_addr_ismulticast(ip_current_src_addr()))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + return ERR_OK; + } + } + + /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it + isn't for a local address */ + if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IPH_PROTO(iphdr) == IP_PROTO_TCP) { + netif = inp; + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp)) { + /* try to forward IP packet on (other) interfaces */ + ip_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", + ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ + p = ip_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); + ip_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + ip_data.current_netif = inp; + ip_data.current_ip4_header = iphdr; + ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */ + + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + snmp_inc_ipindelivers(); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + snmp_inc_ipindelivers(); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + snmp_inc_ipindelivers(); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ip_current_dest_addr()); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) && + !ip_addr_ismulticast(ip_current_dest_addr())) { + pbuf_header(p, iphdr_hlen); /* Move to ip header, no check necessary. */ + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinunknownprotos(); + } + } + + /* @todo: this is not really necessary... */ + ip_data.current_netif = NULL; + ip_data.current_ip4_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip_addr_set_any(ip_current_src_addr()); + ip_addr_set_any(ip_current_dest_addr()); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + snmp_inc_ipoutrequests(); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(proto, ttl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (ip_addr_isany(src)) { + ip_addr_copy(iphdr->src, netif->ip_addr); + } else { + /* src cannot be NULL here */ + ip_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + iphdr->_chksum = chk_sum; /* network order */ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); +#endif +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip_addr_cmp(dest, &netif->ip_addr)) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p, dest); + } +#if LWIP_IGMP + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p, dest); + } +#endif /* LWIP_IGMP */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + IPH_V(iphdr), + IPH_HL(iphdr), + IPH_TOS(iphdr), + ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + ntohs(IPH_ID(iphdr)), + ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, + ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + IPH_TTL(iphdr), + IPH_PROTO(iphdr), + ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/Shared/lwip/src/core/ipv4/ip4_addr.c b/Shared/lwip/src/core/ipv4/ip4_addr.c new file mode 100644 index 0000000..8f633ff --- /dev/null +++ b/Shared/lwip/src/core/ipv4/ip4_addr.c @@ -0,0 +1,312 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const ip_addr_t ip_addr_any = { IPADDR_ANY }; +const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast(u32_t addr, const struct netif *netif) +{ + ip_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) { + return 0; + /* on the same (sub) network... */ + } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(&netif->netmask)) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip_addr_t val; + + if (ipaddr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return (0); + } + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return (0); + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return (0); + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, htonl(val)); + } + return (1); +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char * +ipaddr_ntoa(const ip_addr_t *addr) +{ + static char str[16]; + return ipaddr_ntoa_r(addr, str, 16); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for(n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = '0' + rem; + } while(*ap); + while(i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} diff --git a/Shared/lwip/src/core/ipv4/ip_frag.c b/Shared/lwip/src/core/ipv4/ip_frag.c new file mode 100644 index 0000000..8d18434 --- /dev/null +++ b/Shared/lwip/src/core/ipv4/ip_frag.c @@ -0,0 +1,863 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + snmp_inc_ipreasmfails(); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reass struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no wholes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no wholes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) { + valid = 0; + } else { + /* and check that there are no wholes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + struct ip_reassdata *ipr_prev = NULL; + + IPFRAG_STATS_INC(ip_frag.recv); + snmp_inc_ipreasmreqds(); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if(ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set calculate the correct checksum? */ + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while(r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; +#endif + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + return ERR_MEM; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = (struct ip_hdr *)rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if(pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + +#if IP_FRAG_USES_STATIC_BUF + if (last) { + pbuf_realloc(rambuf, left + IP_HLEN); + } + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it.A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + snmp_inc_ipfragcreates(); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + return ERR_MEM; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + snmp_inc_ipfragoks(); + return ERR_OK; +} +#endif /* IP_FRAG */ diff --git a/Shared/lwip/src/core/ipv6/icmp6.c b/Shared/lwip/src/core/ipv6/icmp6.c new file mode 100644 index 0000000..ea82682 --- /dev/null +++ b/Shared/lwip/src/core/ipv6/icmp6.c @@ -0,0 +1,337 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/stats.h" + +#include + +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif +#if LWIP_ICMP6_DATASIZE == 0 +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/* Forward declarations */ +static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); + + +/** + * Process an input ICMPv6 message. Called by ip6_input. + * + * Will generate a reply for echo requests. Other messages are forwarded + * to nd6_input, or mld6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +icmp6_input(struct pbuf *p, struct netif *inp) +{ + struct icmp6_hdr *icmp6hdr; + struct pbuf * r; + ip6_addr_t * reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ + if (p->len < sizeof(struct icmp6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + +#if LWIP_ICMP6_CHECKSUM_CHECK + if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), + ip6_current_dest_addr()) != 0) { + /* Checksum failed */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.chkerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* LWIP_ICMP6_CHECKSUM_CHECK */ + + switch (icmp6hdr->type) { + case ICMP6_TYPE_NA: /* Neighbor advertisement */ + case ICMP6_TYPE_NS: /* Neighbor solicitation */ + case ICMP6_TYPE_RA: /* Router advertisement */ + case ICMP6_TYPE_RD: /* Redirect */ + case ICMP6_TYPE_PTB: /* Packet too big */ + nd6_input(p, inp); + return; + break; + case ICMP6_TYPE_RS: +#if LWIP_IPV6_FORWARD + /* TODO implement router functionality */ +#endif + break; +#if LWIP_IPV6_MLD + case ICMP6_TYPE_MLQ: + case ICMP6_TYPE_MLR: + case ICMP6_TYPE_MLD: + mld6_input(p, inp); + return; + break; +#endif + case ICMP6_TYPE_EREQ: +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* LWIP_MULTICAST_PING */ + + /* Allocate reply. */ + r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); + if (r == NULL) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + + /* Copy echo request. */ + if (pbuf_copy(r, p) != ERR_OK) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.err); + return; + } + + /* Determine reply source IPv6 address. */ +#if LWIP_MULTICAST_PING + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + reply_src = ip6_select_source_address(inp, ip6_current_src_addr()); + if (reply_src == NULL) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else +#endif /* LWIP_MULTICAST_PING */ + { + reply_src = ip6_current_dest_addr(); + } + + /* Set fields in reply. */ + ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; + ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; + ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, + IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); + + /* Send reply. */ + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(r, reply_src, ip6_current_src_addr(), + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); + pbuf_free(r); + + break; + default: + ICMP6_STATS_INC(icmp6.proterr); + ICMP6_STATS_INC(icmp6.drop); + break; + } + + pbuf_free(p); +} + + +/** + * Send an icmpv6 'destination unreachable' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the unreachable type + */ +void +icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); +} + +/** + * Send an icmpv6 'packet too big' packet. + * + * @param p the input packet for which the 'packet too big' should be sent, + * p->payload pointing to the IPv6 header + * @param mtu the maximum mtu that we can accept + */ +void +icmp6_packet_too_big(struct pbuf *p, u32_t mtu) +{ + icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); +} + +/** + * Send an icmpv6 'time exceeded' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the time exceeded type + */ +void +icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); +} + +/** + * Send an icmpv6 'parameter problem' packet. + * + * @param p the input packet for which the 'param problem' should be sent, + * p->payload pointing to the IP header + * @param c ICMPv6 code for the param problem type + * @param pointer the pointer to the byte where the parameter is found + */ +void +icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) +{ + icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); +} + +/** + * Send an ICMPv6 packet in response to an incoming packet. + * + * @param p the input packet for which the response should be sent, + * p->payload pointing to the IPv6 header + * @param code Code of the ICMPv6 header + * @param data Additional 32-bit parameter in the ICMPv6 header + * @param type Type of the ICMPv6 header + */ +static void +icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) +{ + struct pbuf *q; + struct icmp6_hdr *icmp6hdr; + ip6_addr_t *reply_src, *reply_dest; + ip6_addr_t reply_src_local, reply_dest_local; + struct ip6_hdr *ip6hdr; + struct netif *netif; + + /* ICMPv6 header + IPv6 header + data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", + (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + + icmp6hdr = (struct icmp6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = data; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* Get the destination address and netif for this ICMP message. */ + if ((ip_current_netif() == NULL) || + ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { + /* Special case, as ip6_current_xxx is either NULL, or points + * to a different packet than the one that expired. + * We must use the addresses that are stored in the expired packet. */ + ip6hdr = (struct ip6_hdr *)p->payload; + /* copy from packed address to aligned address */ + ip6_addr_copy(reply_dest_local, ip6hdr->src); + ip6_addr_copy(reply_src_local, ip6hdr->dest); + reply_dest = &reply_dest_local; + reply_src = &reply_src_local; + netif = ip6_route(reply_src, reply_dest); + if (netif == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else { + netif = ip_current_netif(); + reply_dest = ip6_current_src_addr(); + + /* Select an address to use as source. */ + reply_src = ip6_select_source_address(netif, reply_dest); + if (reply_src == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + + /* calculate checksum */ + icmp6hdr->chksum = 0; + icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, + reply_src, reply_dest); + + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(q); +} + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/Shared/lwip/src/core/ipv6/ip6.c b/Shared/lwip/src/core/ipv6/ip6.c new file mode 100644 index 0000000..1eb91f9 --- /dev/null +++ b/Shared/lwip/src/core/ipv6/ip6.c @@ -0,0 +1,1034 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6_frag.h" +#include "lwip/icmp6.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/dhcp6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + + +/** + * Finds the appropriate network interface for a given IPv6 address. It tries to select + * a netif following a sequence of heuristics: + * 1) if there is only 1 netif, return it + * 2) if the destination is a link-local address, try to match the src address to a netif. + * this is a tricky case because with multiple netifs, link-local addresses only have + * meaning within a particular subnet/link. + * 3) tries to match the destination subnet to a configured address + * 4) tries to find a router + * 5) tries to match the source address to the netif + * 6) returns the default netif, if configured + * + * @param src the source IPv6 address, if known + * @param dest the destination IPv6 address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip6_route(struct ip6_addr *src, struct ip6_addr *dest) +{ + struct netif *netif; + s8_t i; + + /* If single netif configuration, fast return. */ + if ((netif_list != NULL) && (netif_list->next == NULL)) { + return netif_list; + } + + /* Special processing for link-local addresses. */ + if (ip6_addr_islinklocal(dest)) { + if (ip6_addr_isany(src)) { + /* Use default netif. */ + return netif_default; + } + + /* Try to find the netif for the source address. */ + for(netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* netif not found, use default netif */ + return netif_default; + } + + /* See if the destination subnet matches a configured address. */ + for(netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* Get the netif for a suitable router. */ + i = nd6_select_router(dest, NULL); + if (i >= 0) { + if (default_router_list[i].neighbor_entry != NULL) { + if (default_router_list[i].neighbor_entry->netif != NULL) { + return default_router_list[i].neighbor_entry->netif; + } + } + } + + /* try with the netif that matches the source address. */ + if (!ip6_addr_isany(src)) { + for(netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + } + + /* no matching netif found, use default netif */ + return netif_default; +} + +/** + * Select the best IPv6 source address for a given destination + * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior + * is assumed. + * + * @param netif the netif on which to send a packet + * @param dest the destination we are trying to reach + * @return the most suitable source address to use, or NULL if no suitable + * source address is found + */ +ip6_addr_t * +ip6_select_source_address(struct netif *netif, ip6_addr_t * dest) +{ + ip6_addr_t * src = NULL; + u8_t i; + + /* If dest is link-local, choose a link-local source. */ + if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + } + + /* Choose a site-local with matching prefix. */ + if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + } + + /* Choose a unique-local with matching prefix. */ + if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + } + + /* Choose a global with best matching prefix. */ + if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isglobal(netif_ip6_addr(netif, i))) { + if (src == NULL) { + src = netif_ip6_addr(netif, i); + } + else { + /* Replace src only if we find a prefix match. */ + /* TODO find longest matching prefix. */ + if ((!(ip6_addr_netcmp(src, dest))) && + ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { + src = netif_ip6_addr(netif, i); + } + } + } + } + if (src != NULL) { + return src; + } + } + + /* Last resort: see if arbitrary prefix matches. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + + return NULL; +} + +#if LWIP_IPV6_FORWARD +/** + * Forwards an IPv6 packet. It finds an appropriate route for the + * packet, decrements the HL value of the packet, and outputs + * the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IPv6 header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + /* do not forward link-local addresses */ + if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip6_route(IP6_ADDR_ANY, ip6_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* decrement HL */ + IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); + /* send ICMP6 if HL == 0 */ + if (IP6H_HOPLIM(iphdr) == 0) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_time_exceeded(p, ICMP6_TE_HL); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + if (netif->mtu && (p->tot_len > netif->mtu)) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_packet_too_big(p, netif->mtu); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); + + /* transmit pbuf on chosen interface */ + netif->output_ip6(netif, p, ip6_current_dest_addr()); + IP6_STATS_INC(ip6.fw); + IP6_STATS_INC(ip6.xmit); + return; +} +#endif /* LWIP_IPV6_FORWARD */ + + +/** + * This function is called by the network interface device driver when + * an IPv6 packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip6_forward). + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IPv6 packet (p->payload points to IPv6 header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip6_input(struct pbuf *p, struct netif *inp) +{ + struct ip6_hdr *ip6hdr; + struct netif *netif; + u8_t nexth; + u16_t hlen; /* the current header length */ + u8_t i; +#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ + @todo + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP6_STATS_INC(ip6.recv); + + /* identify the IP header */ + ip6hdr = (struct ip6_hdr *)p->payload; + if (IP6H_V(ip6hdr) != 6) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", + IP6H_V(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { + if (IP6_HLEN > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + IP6_HLEN, p->len)); + } + if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + IP6H_PLEN(ip6hdr) + IP6_HLEN, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); + + /* copy IP addresses to aligned ip6_addr_t */ + ip6_addr_copy(ip_data.current_iphdr_dest.ip6, ip6hdr->dest); + ip6_addr_copy(ip_data.current_iphdr_src.ip6, ip6hdr->src); + + /* current header pointer. */ + ip_data.current_ip6_header = ip6hdr; + + /* In netif, used in case we need to send ICMPv6 packets back. */ + ip_data.current_netif = inp; + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* Always joined to multicast if-local and link-local all-nodes group. */ + if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || + ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { + netif = inp; + } +#if LWIP_IPV6_MLD + else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { + netif = inp; + } +#else /* LWIP_IPV6_MLD */ + else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { + /* Filter solicited node packets when MLD is not enabled + * (for Neighbor discovery). */ + netif = NULL; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + netif = inp; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + break; + } + } + } +#endif /* LWIP_IPV6_MLD */ + else { + netif = NULL; + } + } + else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + /* interface is up? */ + if (netif_is_up(netif)) { + /* unicast to this interface address? address configured? */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { + /* exit outer loop */ + goto netif_found; + } + } + } + if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + /* Do not match link-local addresses to other netifs. */ + netif = NULL; + break; + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); +netif_found: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", + netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); + } + + /* "::" packet source address? (used in duplicate address detection) */ + if (ip6_addr_isany(ip6_current_src_addr()) && + (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { + /* packet source is not valid */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + /* if we're pretending we are everyone for TCP, assume the packet is for source interface if it + isn't for a local address */ + if (netif == NULL && (inp->flags & NETIF_FLAG_PRETEND_TCP) && IP6H_NEXTH(ip6hdr) == IP6_NEXTH_TCP) { + netif = inp; + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); +#if LWIP_IPV6_FORWARD + /* non-multicast packet? */ + if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* try to forward IP packet on (other) interfaces */ + ip6_forward(p, ip6hdr, inp); + } +#endif /* LWIP_IPV6_FORWARD */ + pbuf_free(p); + goto ip6_input_cleanup; + } + + /* current netif pointer. */ + ip_data.current_netif = netif; + + /* Save next header type. */ + nexth = IP6H_NEXTH(ip6hdr); + + /* Init header length. */ + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Process known option extension headers, if present. */ + while (nexth != IP6_NEXTH_NONE) + { + switch (nexth) { + case IP6_NEXTH_HOPBYHOP: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -hlen); + break; + case IP6_NEXTH_DESTOPTS: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -hlen); + break; + case IP6_NEXTH_ROUTING: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -hlen); + break; + + case IP6_NEXTH_FRAGMENT: + { + struct ip6_frag_hdr * frag_hdr; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); + + frag_hdr = (struct ip6_frag_hdr *)p->payload; + + /* Get next header type. */ + nexth = frag_hdr->_nexth; + + /* Fragment Header length. */ + hlen = 8; + ip_data.current_ip_header_tot_len += hlen; + + /* Make sure this header fits in current pbuf. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_FRAG_STATS_INC(ip6_frag.lenerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto ip6_input_cleanup; + } + + /* Offset == 0 and more_fragments == 0? */ + if (((frag_hdr->_fragment_offset & IP6_FRAG_OFFSET_MASK) == 0) && + ((frag_hdr->_fragment_offset & IP6_FRAG_MORE_FLAG) == 0)) { + + /* This is a 1-fragment packet, usually a packet that we have + * already reassembled. Skip this header anc continue. */ + pbuf_header(p, -hlen); + } + else { +#if LWIP_IPV6_REASS + + /* reassemble the packet */ + p = ip6_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + goto ip6_input_cleanup; + } + + /* Returned p point to IPv6 header. + * Update all our variables and pointers and continue. */ + ip6hdr = (struct ip6_hdr *)p->payload; + nexth = IP6H_NEXTH(ip6hdr); + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + pbuf_header(p, -IP6_HLEN); + +#else /* LWIP_IPV6_REASS */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.opterr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; +#endif /* LWIP_IPV6_REASS */ + } + break; + } + default: + goto options_done; + break; + } + } +options_done: + + /* p points to IPv6 header again. */ + pbuf_header(p, ip_data.current_ip_header_tot_len); + + /* send to upper layers */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); + ip6_debug_print(p); + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (nexth) { + case IP6_NEXTH_NONE: + pbuf_free(p); + break; +#if LWIP_UDP + case IP6_NEXTH_UDP: +#if LWIP_UDPLITE + case IP6_NEXTH_UDPLITE: +#endif /* LWIP_UDPLITE */ + /* Point to payload. */ + pbuf_header(p, -ip_data.current_ip_header_tot_len); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP6_NEXTH_TCP: + /* Point to payload. */ + pbuf_header(p, -ip_data.current_ip_header_tot_len); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP6 + case IP6_NEXTH_ICMP6: + /* Point to payload. */ + pbuf_header(p, -ip_data.current_ip_header_tot_len); + icmp6_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP6 + /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ + if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && + (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { + icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); + } +#endif /* LWIP_ICMP */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", IP6H_NEXTH(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.proterr); + IP6_STATS_INC(ip6.drop); + break; + } + } + +ip6_input_cleanup: + ip_data.current_netif = NULL; + ip_data.current_ip6_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip6_addr_set_any(&ip_data.current_iphdr_src.ip6); + ip6_addr_set_any(&ip_data.current_iphdr_dest.ip6); + + return ERR_OK; +} + + +/** + * Sends an IPv6 packet on a network interface. This function constructs + * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is + * used as source (usually during network startup). If the source IPv6 address it + * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network + * interface is filled in as source address. If the destination IPv6 address is + * IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points + * to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IPv6/LINK headers + * returns errors returned by netif->output + */ +err_t +ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest_addr; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + /* Should the IPv6 header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + /* generate IPv6 header */ + if (pbuf_header(p, IP6_HLEN)) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + ip6hdr = (struct ip6_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", + (p->len >= sizeof(struct ip6_hdr))); + + IP6H_HOPLIM_SET(ip6hdr, hl); + IP6H_NEXTH_SET(ip6hdr, nexth); + + /* dest cannot be NULL here */ + ip6_addr_copy(ip6hdr->dest, *dest); + + IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); + IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); + + if (src == NULL) { + src = IP6_ADDR_ANY; + } + else if (ip6_addr_isany(src)) { + src = ip6_select_source_address(netif, dest); + if ((src == NULL) || ip6_addr_isany(src)) { + /* No appropriate source address was found for this packet. */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + } + /* src cannot be NULL here */ + ip6_addr_copy(ip6hdr->src, *src); + + } else { + /* IP header already included in p */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(dest_addr, ip6hdr->dest); + dest = &dest_addr; + } + + IP6_STATS_INC(ip6.xmit); + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip6_debug_print(p); + +#if ENABLE_LOOPBACK + /* TODO implement loopback for v6 + if (ip6_addr_cmp(dest, netif_ip6_addr(0))) { + return netif_loop_output(netif, p, dest); + }*/ +#endif /* ENABLE_LOOPBACK */ +#if LWIP_IPV6_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { + return ip6_frag(p, netif, dest); + } +#endif /* LWIP_IPV6_FRAG */ + + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()")); + return netif->output_ip6(netif, p, dest); +} + +/** + * Simple interface to ip6_output_if. It finds the outgoing network + * interface and calls upon ip6_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + + /* pbufs passed to IPv6 must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if (dest != IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + return ip6_output_if(p, src, dest, hl, tc, nexth, netif); +} + + +#if LWIP_NETIF_HWADDRHINT +/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip6_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + err_t err; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if (dest != IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if LWIP_IPV6_MLD +/** + * Add a hop-by-hop options header with a router alert option and padding. + * + * Used by MLD when sending a Multicast listener report/done message. + * + * @param p the packet to which we will prepend the options header + * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) + * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) + * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise + */ +err_t +ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value) +{ + struct ip6_hbh_hdr * hbh_hdr; + + /* Move pointer to make room for hop-by-hop options header. */ + if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + hbh_hdr = (struct ip6_hbh_hdr *)p->payload; + + /* Set fields. */ + hbh_hdr->_nexth = nexth; + hbh_hdr->_hlen = 0; + hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; + hbh_hdr->_ra_opt_dlen = 2; + hbh_hdr->_ra_opt_data = value; + hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; + hbh_hdr->_padn_opt_dlen = 0; + + return ERR_OK; +} +#endif /* LWIP_IPV6_MLD */ + +#if IP6_DEBUG +/* Print an IPv6 header by using LWIP_DEBUGF + * @param p an IPv6 packet, p->payload pointing to the IPv6 header + */ +void +ip6_debug_print(struct pbuf *p) +{ + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + + LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", + IP6H_V(ip6hdr), + IP6H_TC(ip6hdr), + IP6H_FL(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", + IP6H_PLEN(ip6hdr), + IP6H_NEXTH(ip6hdr), + IP6H_HOPLIM(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->src)), + IP6_ADDR_BLOCK2(&(ip6hdr->src)), + IP6_ADDR_BLOCK3(&(ip6hdr->src)), + IP6_ADDR_BLOCK4(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->src)), + IP6_ADDR_BLOCK6(&(ip6hdr->src)), + IP6_ADDR_BLOCK7(&(ip6hdr->src)), + IP6_ADDR_BLOCK8(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->dest)), + IP6_ADDR_BLOCK2(&(ip6hdr->dest)), + IP6_ADDR_BLOCK3(&(ip6hdr->dest)), + IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->dest)), + IP6_ADDR_BLOCK6(&(ip6hdr->dest)), + IP6_ADDR_BLOCK7(&(ip6hdr->dest)), + IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP6_DEBUG */ + +#endif /* LWIP_IPV6 */ diff --git a/Shared/lwip/src/core/ipv6/ip6_addr.c b/Shared/lwip/src/core/ipv6/ip6_addr.c new file mode 100644 index 0000000..65d2798 --- /dev/null +++ b/Shared/lwip/src/core/ipv6/ip6_addr.c @@ -0,0 +1,251 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Functions for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + +/* used by IP6_ADDR_ANY in ip6_addr.h */ +const ip6_addr_t ip6_addr_any = { { 0ul, 0ul, 0ul, 0ul } }; + +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) +#endif + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii represenation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + u32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char * s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) { + if (*s == ':') + zero_blocks--; + else if (!isxdigit(*s)) + break; + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } if (s[1] == ':') { + s++; + /* "::" found, set zeros */ + while (zero_blocks-- > 0) { + if (current_block_index & 0x1) { + addr_index++; + } + else { + if (addr) { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + } + } + } else if (isxdigit(*s)) { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? *s - '0' : + 10 + (islower(*s) ? *s - 'a' : *s - 'A')); + } else { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) { + for (addr_index = 0; addr_index < 4; addr_index++) { + addr->addr[addr_index] = htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) { + return 0; + } + + return 1; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char * +ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return ip6addr_ntoa_r(addr, str, 40); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + u32_t current_block_index, current_block_value; + s32_t zero_flag, i; + + i = 0; + zero_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) { + /* get the current 16-bit block */ + current_block_value = htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + if (current_block_value == 0) { + /* generate empty block "::" */ + if (!zero_flag) { + if (current_block_index > 0) { + zero_flag = 1; + buf[i++] = ':'; + if (i >= buflen) return NULL; + } + } + } + else { + if (current_block_index > 0) { + buf[i++] = ':'; + if (i >= buflen) return NULL; + } + + if ((current_block_value & 0xf000) == 0) { + zero_flag = 1; + } + else { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) return NULL; + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) return NULL; + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) return NULL; + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) return NULL; + + zero_flag = 0; + } + } + + buf[i] = 0; + + return buf; +} +#endif /* LWIP_IPV6 */ diff --git a/Shared/lwip/src/core/ipv6/ip6_frag.c b/Shared/lwip/src/core/ipv6/ip6_frag.c new file mode 100644 index 0000000..a43fd61 --- /dev/null +++ b/Shared/lwip/src/core/ipv6/ip6_frag.c @@ -0,0 +1,697 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" +#include "lwip/ip6_frag.h" +#include "lwip/ip6.h" +#include "lwip/icmp6.h" +#include "lwip/nd6.h" + +#include "lwip/pbuf.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IPv6 header, since it replaces + * the Fragment Header in memory in incoming fragments to keep + * track of the various fragments. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* static variables */ +static struct ip6_reassdata *reassdatagrams; +static u16_t ip6_reass_pbufcount; + +/* Forward declarations. */ +static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); +#if IP_REASS_FREE_OLDEST +static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); +#endif /* IP_REASS_FREE_OLDEST */ + +void +ip6_reass_tmr(void) +{ + struct ip6_reassdata *r, *tmp; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + r = r->next; + } else { + /* reassembly timed out */ + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip6_reass_free_complete_datagram(tmp); + } + } +} + +/** + * Free a datagram (struct ip6_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), + * sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + */ +static void +ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) +{ + struct ip6_reassdata *prev; + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip6_reass_helper *iprh; + +#if LWIP_ICMP6 + iprh = (struct ip6_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, move back to the original header (we are now pointing to Fragment header). */ + if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) { + LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); + } + else { + icmp6_time_exceeded(p, ICMP6_TE_FRAG); + } + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP6 */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip6_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + + /* Then, unchain the struct ip6_reassdata from the list and free it. */ + if (ipr == reassdatagrams) { + reassdatagrams = ipr->next; + } else { + prev = reassdatagrams; + while (prev != NULL) { + if (prev->next == ipr) { + break; + } + prev = prev->next; + } + if (prev != NULL) { + prev->next = ipr->next; + } + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* Finally, update number of pbufs in reassembly queue */ + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); + ip6_reass_pbufcount -= pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram ipr is not freed! + * + * @param ipr ip6_reassdata for the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + */ +static void +ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) +{ + struct ip6_reassdata *r, *oldest; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the current datagram! */ + do { + r = oldest = reassdatagrams; + while (r != NULL) { + if (r != ipr) { + if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + r = r->next; + } + if (oldest != NULL) { + ip6_reass_free_complete_datagram(oldest); + } + } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL)); +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Reassembles incoming IPv6 fragments into an IPv6 datagram. + * + * @param p points to the IPv6 Fragment Header + * @param len the length of the payload (after Fragment Header) + * @return NULL if reassembly is incomplete, pbuf pointing to + * IPv6 Header if reassembly is complete + */ +struct pbuf * +ip6_reass(struct pbuf *p) +{ + struct ip6_reassdata *ipr, *ipr_prev; + struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct ip6_frag_hdr * frag_hdr; + u16_t offset, len; + u8_t clen, valid = 1; + struct pbuf *q; + + IP6_FRAG_STATS_INC(ip6_frag.recv); + + frag_hdr = (struct ip6_frag_hdr *) p->payload; + + clen = pbuf_clen(p); + + offset = ntohs(frag_hdr->_fragment_offset); + + /* Calculate fragment length from IPv6 payload length. + * Adjust for headers before Fragment Header. + * And finally adjust by Fragment Header length. */ + len = ntohs(ip6_current_header()->_plen); + len -= ((u8_t*)p->payload - (u8_t*)ip6_current_header()) - IP6_HLEN; + len -= IP6_FRAG_HLEN; + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if ((frag_hdr->_identification == ipr->identification) && + ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr->src)) && + ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr->dest))) { + IP6_FRAG_STATS_INC(ip6_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + /* Make room and try again. */ + ip6_reass_remove_oldest_datagram(ipr, clen); + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + memset(ipr, 0, sizeof(struct ip6_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + + /* Use the current IPv6 header for src/dest address reference. + * Eventually, we will replace it when we get the first fragment + * (it might be this one, in any case, it is done later). */ + ipr->iphdr = (struct ip6_hdr *)ip6_current_header(); + + /* copy the fragmented packet id. */ + ipr->identification = frag_hdr->_identification; + + /* copy the nexth field */ + ipr->nexth = frag_hdr->_nexth; + } + + /* Check if we are allowed to enqueue more datagrams. */ + if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + ip6_reass_remove_oldest_datagram(ipr, clen); + if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* @todo: send ICMPv6 time exceeded here? */ + /* drop this pbuf */ + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + /* Overwrite Fragment Header with our own helper struct. */ + iprh = (struct ip6_reass_helper *)p->payload; + iprh->next_pbuf = NULL; + iprh->start = (offset & IP6_FRAG_OFFSET_MASK); + iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; + + /* find the right place to insert this pbuf */ + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip6_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + if (iprh_prev != NULL) { + if (iprh->start < iprh_prev->end) { + /* fragment overlaps with previous, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ + iprh_prev->next_pbuf = p; + } else { + /* fragment with the lowest offset */ + ipr->p = p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no gaps. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = p; + } + } + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip6_reass_pbufcount += clen; + + /* Remember IPv6 header if this is the first fragment. */ + if (iprh->start == 0) { + ipr->iphdr = (struct ip6_hdr *)ip6_current_header(); + } + + /* If this is the last fragment, calculate total packet length. */ + if ((offset & IP6_FRAG_MORE_FLAG) == 0) { + ipr->datagram_len = iprh->end; + } + + /* Additional validity tests: we have received first and last fragment. */ + iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; + if (iprh_tmp->start != 0) { + valid = 0; + } + if (ipr->datagram_len == 0) { + valid = 0; + } + + /* Final validity test: no gaps between current and last fragment. */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while ((q != NULL) && valid) { + iprh = (struct ip6_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + + if (valid) { + /* All fragments have been received */ + + /* chain together the pbufs contained within the ip6_reassdata list. */ + iprh = (struct ip6_reass_helper*) ipr->p->payload; + while(iprh != NULL) { + + if (iprh->next_pbuf != NULL) { + /* Save next helper struct (will be hidden in next step). */ + iprh_tmp = (struct ip6_reass_helper*) iprh->next_pbuf->payload; + + /* hide the fragment header for every succeding fragment */ + pbuf_header(iprh->next_pbuf, -IP6_FRAG_HLEN); + pbuf_cat(ipr->p, iprh->next_pbuf); + } + else { + iprh_tmp = NULL; + } + + iprh = iprh_tmp; + } + + /* Adjust datagram length by adding header lengths. */ + ipr->datagram_len += ((u8_t*)ipr->p->payload - (u8_t*)ipr->iphdr) + + IP6_FRAG_HLEN + - IP6_HLEN ; + + /* Set payload length in ip header. */ + ipr->iphdr->_plen = htons(ipr->datagram_len); + + /* Get the furst pbuf. */ + p = ipr->p; + + /* Restore Fragment Header in first pbuf. Mark as "single fragment" + * packet. Restore nexth. */ + frag_hdr = (struct ip6_frag_hdr *) p->payload; + frag_hdr->_nexth = ipr->nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = 0; + frag_hdr->_identification = 0; + + /* release the sources allocate for the fragment queue entry */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); + ipr_prev->next = ipr->next; + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* adjust the number of pbufs currently queued for reassembly. */ + ip6_reass_pbufcount -= pbuf_clen(p); + + /* Move pbuf back to IPv6 header. */ + if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) { + LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); + pbuf_free(p); + return NULL; + } + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + return NULL; + +nullreturn: + pbuf_free(p); + return NULL; +} + +#endif /* LWIP_IPV6 ^^ LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG + +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip6_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ip6_frag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip6_frag_free_pbuf_custom_ref(pcr); +} + +/** + * Fragment an IPv6 datagram if too large for the netif or path MTU. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p + * + * @param p ipv6 packet to send + * @param netif the netif on which to send + * @param dest destination ipv6 address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest) +{ + struct ip6_hdr *original_ip6hdr; + struct ip6_hdr *ip6hdr; + struct ip6_frag_hdr * frag_hdr; + struct pbuf *rambuf; + struct pbuf *newpbuf; + static u32_t identification; + u16_t nfb; + u16_t left, cop; + u16_t mtu; + u16_t fragment_offset = 0; + u16_t last; + u16_t poff = IP6_HLEN; + u16_t newpbuflen = 0; + u16_t left_to_copy; + + identification++; + + original_ip6hdr = (struct ip6_hdr *)p->payload; + + mtu = nd6_get_destination_mtu(dest, netif); + + /* TODO we assume there are no options in the unfragmentable part (IPv6 header). */ + left = p->tot_len - IP6_HLEN; + + nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; + + while (left) { + last = (left <= nfb); + + /* Fill this fragment */ + cop = last ? left : nfb; + + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP6_HLEN + IP6_FRAG_HLEN))); + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + p->tot_len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip6_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip6_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; + + /* Set headers */ + frag_hdr->_nexth = original_ip6hdr->_nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = htonl(identification); + + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); + IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + IP6_FRAG_STATS_INC(ip6_frag.xmit); + netif->output_ip6(netif, rambuf, dest); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= cop; + fragment_offset += cop; + } + return ERR_OK; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/Shared/lwip/src/core/ipv6/nd6.c b/Shared/lwip/src/core/ipv6/nd6.c new file mode 100644 index 0000000..513db98 --- /dev/null +++ b/Shared/lwip/src/core/ipv6/nd6.c @@ -0,0 +1,1790 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/stats.h" + +#include + + +/* Router tables. */ +struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; +struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; +struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; +struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; + +/* Default values, can be updated by a RA message. */ +u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; +u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* TODO implement this value in timer */ + +/* Index for cache entries. */ +static u8_t nd6_cached_neighbor_index; +static u8_t nd6_cached_destination_index; + +/* Multicast address holder. */ +static ip6_addr_t multicast_address; + +/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ +static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; + +/* Forward declarations. */ +static s8_t nd6_find_neighbor_cache_entry(ip6_addr_t * ip6addr); +static s8_t nd6_new_neighbor_cache_entry(void); +static void nd6_free_neighbor_cache_entry(s8_t i); +static s8_t nd6_find_destination_cache_entry(ip6_addr_t * ip6addr); +static s8_t nd6_new_destination_cache_entry(void); +static s8_t nd6_is_prefix_in_netif(ip6_addr_t * ip6addr, struct netif * netif); +static s8_t nd6_get_router(ip6_addr_t * router_addr, struct netif * netif); +static s8_t nd6_new_router(ip6_addr_t * router_addr, struct netif * netif); +static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); +static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); + +#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 +#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 +static void nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags); +static void nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags); +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +static void nd6_send_rs(struct netif * netif); +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +#if LWIP_ND6_QUEUEING +static void nd6_free_q(struct nd6_q_entry *q); +#else /* LWIP_ND6_QUEUEING */ +#define nd6_free_q(q) pbuf_free(q) +#endif /* LWIP_ND6_QUEUEING */ +static void nd6_send_q(s8_t i); + + +/** + * Process an incoming neighbor discovery message + * + * @param p the nd packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +nd6_input(struct pbuf *p, struct netif *inp) +{ + u8_t msg_type; + s8_t i; + + ND6_STATS_INC(nd6.recv); + + msg_type = *((u8_t *)p->payload); + switch (msg_type) { + case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ + { + struct na_header * na_hdr; + struct lladdr_option * lladdr_opt; + + /* Check that na header fits in packet. */ + if (p->len < (sizeof(struct na_header))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + na_hdr = (struct na_header *)p->payload; + + /* Unsolicited NA?*/ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* This is an unsolicited NA. + * link-layer changed? + * part of DAD mechanism? */ + + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* If the target address matches this netif, it is a DAD response. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + /* We are using a duplicate address. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + +#if LWIP_IPV6_MLD + /* Leave solicited node multicast group. */ + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]); + mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address); +#endif /* LWIP_IPV6_MLD */ + + + + +#if LWIP_IPV6_AUTOCONFIG + /* Check to see if this address was autoconfigured. */ + if (!ip6_addr_islinklocal(ip6_current_dest_addr())) { + i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (i >= 0) { + /* Mark this prefix as duplicate, so that we don't use it + * to generate this address again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + pbuf_free(p); + return; + } + } +#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ + + /* This is an unsolicited NA, most likely there was a LLADDR change. */ + i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + if (i >= 0) { + if (na_hdr->flags & ND6_FLAG_OVERRIDE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + } + } + else { + /* This is a solicited NA. + * neighbor address resolution response? + * neighbor unreachability detection response? */ + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + + /* Find the cache entry corresponding to this na. */ + i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + if (i < 0) { + /* We no longer care about this target address. drop it. */ + pbuf_free(p); + return; + } + + /* Update cache entry. */ + neighbor_cache[i].netif = inp; + neighbor_cache[i].counter.reachable_time = reachable_time; + if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || + (neighbor_cache[i].state == ND6_INCOMPLETE)) { + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + neighbor_cache[i].state = ND6_REACHABLE; + + /* Send queued packets, if any. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + } + + break; /* ICMP6_TYPE_NA */ + } + case ICMP6_TYPE_NS: /* Neighbor solicitation. */ + { + struct ns_header * ns_hdr; + struct lladdr_option * lladdr_opt; + u8_t accepted; + + /* Check that ns header fits in packet. */ + if (p->len < sizeof(struct ns_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ns_hdr = (struct ns_header *)p->payload; + + /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ + lladdr_opt = NULL; + if (p->len >= (sizeof(struct ns_header) + sizeof(struct lladdr_option))) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + } + + /* Check if the target address is configured on the receiving netif. */ + accepted = 0; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || + (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && + ip6_addr_isany(ip6_current_src_addr()))) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + accepted = 1; + break; + } + } + + /* NS not for us? */ + if (!accepted) { + pbuf_free(p); + return; + } + + /* Check for ANY address in src (DAD algorithm). */ + if (ip6_addr_isany(ip6_current_src_addr())) { + /* Sender is validating this address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + /* Send a NA back so that the sender does not use this address. */ + nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); + if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { + /* We shouldn't use this address either. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + } + } + } + } + else { + /* Sender is trying to resolve our address. */ + /* Verify that they included their own link-layer address. */ + if (lladdr_opt == NULL) { + /* Not a valid message. */ + pbuf_free(p); + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + return; + } + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if ( i>= 0) { + /* We already have a record for the solicitor. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + + /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + else + { + /* Add their IPv6 address and link-layer address to neighbor cache. + * We will need it at least to send a unicast NA message, but most + * likely we will also be communicating with this node soon. */ + i = nd6_new_neighbor_cache_entry(); + if (i < 0) { + /* We couldn't assign a cache entry for this neighbor. + * we won't be able to reply. drop it. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address)); + + /* Send back a NA for us. Allocate the reply pbuf. */ + nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + } + + break; /* ICMP6_TYPE_NS */ + } + case ICMP6_TYPE_RA: /* Router Advertisement. */ + { + struct ra_header * ra_hdr; + u8_t * buffer; /* Used to copy options. */ + u16_t offset; + + /* Check that RA header fits in packet. */ + if (p->len < sizeof(struct ra_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ra_hdr = (struct ra_header *)p->payload; + + /* If we are sending RS messages, stop. */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + inp->rs_count = 0; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + /* Get the matching default router entry. */ + i = nd6_get_router(ip6_current_src_addr(), inp); + if (i < 0) { + /* Create a new router entry. */ + i = nd6_new_router(ip6_current_src_addr(), inp); + } + + if (i < 0) { + /* Could not create a new router entry. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Re-set invalidation timer. */ + default_router_list[i].invalidation_timer = ra_hdr->router_lifetime; + + /* Re-set default timer values. */ +#if LWIP_ND6_ALLOW_RA_UPDATES + if (ra_hdr->retrans_timer > 0) { + retrans_timer = ra_hdr->retrans_timer; + } + if (ra_hdr->reachable_time > 0) { + reachable_time = ra_hdr->reachable_time; + } +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + + /* TODO set default hop limit... */ + /* ra_hdr->current_hop_limit;*/ + + /* Update flags in local entry (incl. preference). */ + default_router_list[i].flags = ra_hdr->flags; + + /* Offset to options. */ + offset = sizeof(struct ra_header); + + /* Process each option. */ + while ((p->tot_len - offset) > 0) { + if (p->len == p->tot_len) { + /* no need to copy from contiguous pbuf */ + buffer = &((u8_t*)p->payload)[offset]; + } else { + buffer = nd6_ra_buffer; + pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset); + } + switch (buffer[0]) { + case ND6_OPTION_TYPE_SOURCE_LLADDR: + { + struct lladdr_option * lladdr_opt; + lladdr_opt = (struct lladdr_option *)buffer; + if ((default_router_list[i].neighbor_entry != NULL) && + (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { + SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); + default_router_list[i].neighbor_entry->state = ND6_REACHABLE; + default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; + } + break; + } + case ND6_OPTION_TYPE_MTU: + { + struct mtu_option * mtu_opt; + mtu_opt = (struct mtu_option *)buffer; + if (mtu_opt->mtu >= 1280) { +#if LWIP_ND6_ALLOW_RA_UPDATES + inp->mtu = mtu_opt->mtu; +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + } + break; + } + case ND6_OPTION_TYPE_PREFIX_INFO: + { + struct prefix_option * prefix_opt; + prefix_opt = (struct prefix_option *)buffer; + + if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) { + /* Add to on-link prefix list. */ + + /* Get a memory-aligned copy of the prefix. */ + ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix)); + + /* find cache entry for this prefix. */ + i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (i < 0) { + /* Create a new cache entry. */ + i = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp); + } + if (i >= 0) { + prefix_list[i].invalidation_timer = prefix_opt->valid_lifetime; + +#if LWIP_IPV6_AUTOCONFIG + if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { + /* Mark prefix as autonomous, so that address autoconfiguration can take place. + * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + break; + } + case ND6_OPTION_TYPE_ROUTE_INFO: + { + /* TODO implement preferred routes. + struct route_option * route_opt; + route_opt = (struct route_option *)buffer;*/ + + break; + } + default: + /* Unrecognized option, abort. */ + ND6_STATS_INC(nd6.proterr); + break; + } + offset += 8 * ((u16_t)buffer[1]); + } + + break; /* ICMP6_TYPE_RA */ + } + case ICMP6_TYPE_RD: /* Redirect */ + { + struct redirect_header * redir_hdr; + struct lladdr_option * lladdr_opt; + + /* Check that Redir header fits in packet. */ + if (p->len < sizeof(struct redirect_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + redir_hdr = (struct redirect_header *)p->payload; + + lladdr_opt = NULL; + if (p->len >= (sizeof(struct redirect_header) + sizeof(struct lladdr_option))) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); + } + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address)); + + /* Find dest address in cache */ + i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Set the new target address. */ + ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); + + /* If Link-layer address of other router is given, try to add to neighbor cache. */ + if (lladdr_opt != NULL) { + if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { + /* Copy target address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address)); + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if (i < 0) { + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + if (i >= 0) { + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + } + } + break; /* ICMP6_TYPE_RD */ + } + case ICMP6_TYPE_PTB: /* Packet too big */ + { + struct icmp6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr * ip6hdr; /* IPv6 header of the packet which caused the error */ + + /* Check that ICMPv6 header + IPv6 header fit in payload */ + if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest)); + + /* Look for entry in destination cache. */ + i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Change the Path MTU. */ + destination_cache[i].pmtu = icmp6hdr->data; + + break; /* ICMP6_TYPE_PTB */ + } + + default: + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + break; /* default */ + } + + pbuf_free(p); +} + + +/** + * Periodic timer for Neighbor discovery functions: + * + * - Update neighbor reachability states + * - Update destination cache entries age + * - Update invalidation timers of default routers and on-link prefixes + * - Perform duplicate address detection (DAD) for our addresses + * - Send router solicitations + */ +void +nd6_tmr(void) +{ + s8_t i; +#if LWIP_IPV6_AUTOCONFIG + s8_t j; +#endif + struct netif * netif; + + /* Process neighbor entries. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + switch (neighbor_cache[i].state) { + case ND6_INCOMPLETE: + if (neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } + else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST); + } + break; + case ND6_REACHABLE: + /* Send queued packets, if any are left. Should have been sent already. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { + /* Change to stale state. */ + neighbor_cache[i].state = ND6_STALE; + neighbor_cache[i].counter.stale_time = 0; + } + else { + neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_STALE: + neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL; + break; + case ND6_DELAY: + if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) { + /* Change to PROBE state. */ + neighbor_cache[i].state = ND6_PROBE; + neighbor_cache[i].counter.probes_sent = 0; + } + else { + neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_PROBE: + if (neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } + else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0); + } + break; + case ND6_NO_ENTRY: + default: + /* Do nothing. */ + break; + } + } + + /* Process destination entries. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + destination_cache[i].age++; + } + + /* Process router entries. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (default_router_list[i].neighbor_entry != NULL) { + /* Active entry. */ + if (default_router_list[i].invalidation_timer > 0) { + default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + } + if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Less than 1 second remainig. Clear this entry. */ + default_router_list[i].neighbor_entry->isrouter = 0; + default_router_list[i].neighbor_entry = NULL; + default_router_list[i].invalidation_timer = 0; + default_router_list[i].flags = 0; + } + } + } + + /* Process prefix entries. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + prefix_list[i].invalidation_timer = 0; + } + if ((prefix_list[i].invalidation_timer > 0) && + (prefix_list[i].netif != NULL)) { + prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + +#if LWIP_IPV6_AUTOCONFIG + /* Initiate address autoconfiguration for this prefix, if conditions are met. */ + if (prefix_list[i].netif->ip6_autoconfig_enabled && + (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && + !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { + /* Try to get an address on this netif that is invalid. + * Skip 0 index (link-local address) */ + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDRESS_STATE_INVALID) { + /* Generate an address using this prefix and interface ID from link-local address. */ + prefix_list[i].netif->ip6_addr[j].addr[0] = prefix_list[i].prefix.addr[0]; + prefix_list[i].netif->ip6_addr[j].addr[1] = prefix_list[i].prefix.addr[1]; + prefix_list[i].netif->ip6_addr[j].addr[2] = prefix_list[i].netif->ip6_addr[0].addr[2]; + prefix_list[i].netif->ip6_addr[j].addr[3] = prefix_list[i].netif->ip6_addr[0].addr[3]; + + /* Mark it as tentative (DAD will be performed if configured). */ + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); + + /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + + /* Process our own addresses, if DAD configured. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_istentative(netif->ip6_addr_state[i])) { + if ((netif->ip6_addr_state[i] & 0x07) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { + /* No NA received in response. Mark address as valid. */ + netif->ip6_addr_state[i] = IP6_ADDR_PREFERRED; + /* TODO implement preferred and valid lifetimes. */ + } + else if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_IPV6_MLD + if ((netif->ip6_addr_state[i] & 0x07) == 0) { + /* Join solicited node multicast group. */ + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]); + mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address); + } +#endif /* LWIP_IPV6_MLD */ + /* Send a NS for this address. */ + nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); + (netif->ip6_addr_state[i])++; + /* TODO send max 1 NS per tmr call? enable return*/ + /*return;*/ + } + } + } + } + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send router solicitation messages, if necessary. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP)) { + nd6_send_rs(netif); + netif->rs_count--; + } + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +} + +/** + * Send a neighbor solicitation message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) +{ + struct ns_header * ns_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + ip6_addr_t * src_addr; + + if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + } else { + src_addr = IP6_ADDR_ANY; + } + + /* Allocate a packet. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + sizeof(struct lladdr_option), PBUF_RAM); + if ((p == NULL) || (p->len < (sizeof(struct ns_header) + sizeof(struct lladdr_option)))) { + /* We couldn't allocate a suitable pbuf for the ns. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + ns_hdr = (struct ns_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + + ns_hdr->type = ICMP6_TYPE_NS; + ns_hdr->code = 0; + ns_hdr->chksum = 0; + ns_hdr->reserved = 0; + ip6_addr_set(&(ns_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + target_addr = &multicast_address; + } + + ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + target_addr); + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, (src_addr == IP6_ADDR_ANY) ? NULL : src_addr, target_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +/** + * Send a neighbor advertisement message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) +{ + struct na_header * na_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + ip6_addr_t * src_addr; + ip6_addr_t * dest_addr; + + /* Use link-local address as source address. */ + /* src_addr = &(netif->ip6_addr[0]); */ + /* Use target address as source address. */ + src_addr = target_addr; + + /* Allocate a packet. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + sizeof(struct lladdr_option), PBUF_RAM); + if ((p == NULL) || (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option)))) { + /* We couldn't allocate a suitable pbuf for the ns. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + na_hdr = (struct na_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + na_hdr->type = ICMP6_TYPE_NA; + na_hdr->code = 0; + na_hdr->chksum = 0; + na_hdr->flags = flags & 0xf0; + na_hdr->reserved[0] = 0; + na_hdr->reserved[1] = 0; + na_hdr->reserved[2] = 0; + ip6_addr_set(&(na_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; + lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + dest_addr = &multicast_address; + } + else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { + ip6_addr_set_allnodes_linklocal(&multicast_address); + dest_addr = &multicast_address; + } + else { + dest_addr = ip6_current_src_addr(); + } + + na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + dest_addr); + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, dest_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +/** + * Send a router solicitation message + * + * @param netif the netif on which to send the message + */ +static void +nd6_send_rs(struct netif * netif) +{ + struct rs_header * rs_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + ip6_addr_t * src_addr; + u16_t packet_len; + + /* Link-local source address, or unspecified address? */ + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + src_addr = netif_ip6_addr(netif, 0); + } + else { + src_addr = IP6_ADDR_ANY; + } + + /* Generate the all routers target address. */ + ip6_addr_set_allrouters_linklocal(&multicast_address); + + /* Allocate a packet. */ + packet_len = sizeof(struct rs_header); + if (src_addr != IP6_ADDR_ANY) { + packet_len += sizeof(struct lladdr_option); + } + p = pbuf_alloc(PBUF_IP, packet_len, PBUF_RAM); + if ((p == NULL) || (p->len < packet_len)) { + /* We couldn't allocate a suitable pbuf for the ns. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + rs_hdr = (struct rs_header *)p->payload; + + rs_hdr->type = ICMP6_TYPE_RS; + rs_hdr->code = 0; + rs_hdr->chksum = 0; + rs_hdr->reserved = 0; + + if (src_addr != IP6_ADDR_ANY) { + /* Include our hw address. */ + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + + rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + &multicast_address); + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, &multicast_address, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +/** + * Search for a neighbor cache entry + * + * @param ip6addr the IPv6 address of the neighbor + * @return The neighbor cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_neighbor_cache_entry(ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { + return i; + } + } + return -1; +} + +/** + * Create a new neighbor cache entry. + * + * If no unused entry is found, will try to recycle an old entry + * according to ad-hoc "age" heuristic. + * + * @return The neighbor cache entry index that was created, -1 if no + * entry could be created + */ +static s8_t +nd6_new_neighbor_cache_entry(void) +{ + s8_t i; + s8_t j; + u32_t time; + + + /* First, try to find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].state == ND6_NO_ENTRY) { + return i; + } + } + + /* We need to recycle an entry. in general, do not recycle if it is a router. */ + + /* Next, try to find a Stale entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_STALE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Probe entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_PROBE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Delayed entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_DELAY) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find the oldest reachable entry. */ + time = 0xfffffffful; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_REACHABLE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.reachable_time < time) { + j = i; + time = neighbor_cache[i].counter.reachable_time; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry without queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ( + (neighbor_cache[i].q == NULL) && + (neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry with queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* No more entries to try. */ + return -1; +} + +/** + * Will free any resources associated with a neighbor cache + * entry, and will mark it as unused. + * + * @param i the neighbor cache entry index to free + */ +static void +nd6_free_neighbor_cache_entry(s8_t i) +{ + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + + /* Free any queued packets. */ + if (neighbor_cache[i].q != NULL) { + nd6_free_q(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } + + neighbor_cache[i].state = ND6_NO_ENTRY; + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = NULL; + neighbor_cache[i].counter.reachable_time = 0; + ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); +} + +/** + * Search for a destination cache entry + * + * @param ip6addr the IPv6 address of the destination + * @return The destination cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_destination_cache_entry(ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { + return i; + } + } + return -1; +} + +/** + * Create a new destination cache entry. If no unused entry is found, + * will recycle oldest entry. + * + * @return The destination cache entry index that was created, -1 if no + * entry was created + */ +static s8_t +nd6_new_destination_cache_entry(void) +{ + s8_t i, j; + u32_t age; + + /* Find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { + return i; + } + } + + /* Find oldest entry. */ + age = 0; + j = LWIP_ND6_NUM_DESTINATIONS - 1; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (destination_cache[i].age > age) { + j = i; + } + } + + return j; +} + +/** + * Determine whether an address matches an on-link prefix. + * + * @param ip6addr the IPv6 address to match + * @return 1 if the address is on-link, 0 otherwise + */ +static s8_t +nd6_is_prefix_in_netif(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if ((prefix_list[i].netif == netif) && + (prefix_list[i].invalidation_timer > 0) && + ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { + return 1; + } + } + /* Check to see if address prefix matches a (manually?) configured address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { + return 1; + } + } + return 0; +} + +/** + * Select a default router for a destination. + * + * @param ip6addr the destination address + * @param netif the netif for the outgoing packet, if known + * @return the default router entry index, or -1 if no suitable + * router is found + */ +s8_t +nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + /* last_router is used for round-robin router selection (as recommended + * in RFC). This is more robust in case one router is not reachable, + * we are not stuck trying to resolve it. */ + static s8_t last_router; + (void)ip6addr; /* TODO match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ + + /* TODO: implement default router preference */ + + /* Look for reachable routers. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0) && + (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { + return i; + } + } + + /* Look for router in other reachability states, but still valid according to timer. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0)) { + return i; + } + } + + /* Look for any router for which we have any information at all. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if (default_router_list[i].neighbor_entry != NULL && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { + return i; + } + } + + /* no suitable router found. */ + return -1; +} + +/** + * Find an entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is found, if known + * @return the index of the router entry, or -1 if not found + */ +static s8_t +nd6_get_router(ip6_addr_t * router_addr, struct netif * netif) +{ + s8_t i; + + /* Look for router. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if ((default_router_list[i].neighbor_entry != NULL) && + ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && + ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { + return i; + } + } + + /* router not found. */ + return -1; +} + +/** + * Create a new entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is connected, if known + * @return the index on the router table, or -1 if could not be created + */ +static s8_t +nd6_new_router(ip6_addr_t * router_addr, struct netif * netif) +{ + s8_t router_index; + s8_t neighbor_index; + + /* Do we have a neighbor entry for this router? */ + neighbor_index = nd6_find_neighbor_cache_entry(router_addr); + if (neighbor_index < 0) { + /* Create a neighbor entry for this router. */ + neighbor_index = nd6_new_neighbor_cache_entry(); + if (neighbor_index < 0) { + /* Could not create neighbor entry for this router. */ + return -1; + } + ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); + neighbor_cache[neighbor_index].netif = netif; + neighbor_cache[neighbor_index].q = NULL; + neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; + neighbor_cache[neighbor_index].counter.probes_sent = 0; + } + + /* Mark neighbor as router. */ + neighbor_cache[neighbor_index].isrouter = 1; + + /* Look for empty entry. */ + for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { + if (default_router_list[router_index].neighbor_entry == NULL) { + default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); + return router_index; + } + } + + /* Could not create a router entry. */ + + /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ + neighbor_cache[neighbor_index].isrouter = 0; + + /* router not found. */ + return -1; +} + +/** + * Find the cached entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not found + */ +static s8_t +nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +{ + s8_t i; + + /* Look for prefix in list. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && + (prefix_list[i].netif == netif)) { + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Creates a new entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not created + */ +static s8_t +nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +{ + s8_t i; + + /* Create new entry. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((prefix_list[i].netif == NULL) || + (prefix_list[i].invalidation_timer == 0)) { + /* Found empty prefix entry. */ + prefix_list[i].netif = netif; + ip6_addr_set(&(prefix_list[i].prefix), prefix); +#if LWIP_IPV6_AUTOCONFIG + prefix_list[i].flags = 0; +#endif + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Determine the next hop for a destination. Will determine if the + * destination is on-link, else a suitable on-link router is selected. + * + * The last entry index is cached for fast entry search. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the neighbor cache entry for the next hop, ERR_RTE if no + * suitable next hop was found, ERR_MEM if no cache entry + * could be created + */ +s8_t +nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t addr_hint = *(netif->addr_hint); + if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { + nd6_cached_destination_index = addr_hint; + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look for ip6addr in destination cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + /* the cached entry index is the right one! */ + /* do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + /* Search destination cache. */ + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + /* found destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } + else { + /* Not found. Create a new destination entry. */ + i = nd6_new_destination_cache_entry(); + if (i >= 0) { + /* got new destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Could not create a destination cache entry. */ + return ERR_MEM; + } + + /* Copy dest address to destination cache. */ + ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); + + /* Now find the next hop. is it a neighbor? */ + if (ip6_addr_islinklocal(ip6addr) || + nd6_is_prefix_in_netif(ip6addr, netif)) { + /* Destination in local link. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); + } + else { + /* We need to select a router. */ + i = nd6_select_router(ip6addr, netif); + if (i < 0) { + /* No router found. */ + ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); + return ERR_RTE; + } + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); + } + } + } + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + *(netif->addr_hint) = nd6_cached_destination_index; + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look in neighbor cache for the next-hop address. */ + if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), + &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + /* Cache hit. */ + /* Do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); + if (i >= 0) { + /* Found a matching record, make it new cached entry. */ + nd6_cached_neighbor_index = i; + } + else { + /* Neighbor not in cache. Make a new entry. */ + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + /* got new neighbor entry. make it our new cached index. */ + nd6_cached_neighbor_index = i; + } else { + /* Could not create a neighbor cache entry. */ + return ERR_MEM; + } + + /* Initialize fields. */ + ip6_addr_copy(neighbor_cache[i].next_hop_address, + destination_cache[nd6_cached_destination_index].next_hop_addr); + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = netif; + neighbor_cache[i].state = ND6_INCOMPLETE; + neighbor_cache[i].counter.probes_sent = 0; + } + } + + /* Reset this destination's age. */ + destination_cache[nd6_cached_destination_index].age = 0; + + return nd6_cached_neighbor_index; +} + +/** + * Queue a packet for a neighbor. + * + * @param neighbor_index the index in the neighbor cache table + * @param q packet to be queued + * @return ERR_OK if succeeded, ERR_MEM if out of memory + */ +err_t +nd6_queue_packet(s8_t neighbor_index, struct pbuf * q) +{ + err_t result = ERR_MEM; + struct pbuf *p; + int copy_needed = 0; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *new_entry, *r; +#endif /* LWIP_ND6_QUEUEING */ + + if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { + return ERR_ARG; + } + + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ +#if LWIP_ND6_QUEUEING + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); +#else /* LWIP_ND6_QUEUEING */ + pbuf_free(neighbor_cache[neighbor_index].q); + neighbor_cache[neighbor_index].q = NULL; +#endif /* LWIP_ND6_QUEUEING */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + } + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet was copied/ref'd? */ + if (p != NULL) { + /* queue packet ... */ +#if LWIP_ND6_QUEUEING + /* allocate a new nd6 queue entry */ + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + } + if (new_entry != NULL) { + new_entry->next = NULL; + new_entry->p = p; + if(neighbor_cache[neighbor_index].q != NULL) { + /* queue was already existent, append the new entry to the end */ + r = neighbor_cache[neighbor_index].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + neighbor_cache[neighbor_index].q = new_entry; + } + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; + } else { + /* the pool MEMP_ND6_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); + /* { result == ERR_MEM } through initialization */ + } +#else /* LWIP_ND6_QUEUEING */ + /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ + if (neighbor_cache[neighbor_index].q != NULL) { + pbuf_free(neighbor_cache[neighbor_index].q); + } + neighbor_cache[neighbor_index].q = p; + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; +#endif /* LWIP_ND6_QUEUEING */ + } else { + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } + + return result; +} + +#if LWIP_ND6_QUEUEING +/** + * Free a complete queue of nd6 q entries + * + * @param q a queue of nd6_q_entry to free + */ +static void +nd6_free_q(struct nd6_q_entry *q) +{ + struct nd6_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ND6_QUEUE, r); + } +} +#endif /* LWIP_ND6_QUEUEING */ + +/** + * Send queued packets for a neighbor + * + * @param i the neighbor to send packets to + */ +static void +nd6_send_q(s8_t i) +{ + struct ip6_hdr *ip6hdr; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *q; +#endif /* LWIP_ND6_QUEUEING */ + + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + +#if LWIP_ND6_QUEUEING + while (neighbor_cache[i].q != NULL) { + /* remember first in queue */ + q = neighbor_cache[i].q; + /* pop first item off the queue */ + neighbor_cache[i].q = q->next; + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(q->p->payload); + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr()); + /* free the queued IP packet */ + pbuf_free(q->p); + /* now queue entry can be freed */ + memp_free(MEMP_ND6_QUEUE, q); + } +#else /* LWIP_ND6_QUEUEING */ + if (neighbor_cache[i].q != NULL) { + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr()); + /* free the queued IP packet */ + pbuf_free(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } +#endif /* LWIP_ND6_QUEUEING */ +} + + +/** + * Get the Path MTU for a destination. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the Path MTU, if known, or the netif default MTU + */ +u16_t +nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + if (destination_cache[i].pmtu > 0) { + return destination_cache[i].pmtu; + } + } + + if (netif != NULL) { + return netif->mtu; + } + + return 1280; /* Minimum MTU */ +} + + +#if LWIP_ND6_TCP_REACHABILITY_HINTS +/** + * Provide the Neighbor discovery process with a hint that a + * destination is reachable. Called by tcp_receive when ACKs are + * received or sent (as per RFC). This is useful to avoid sending + * NS messages every 30 seconds. + * + * @param ip6addr the destination address which is know to be reachable + * by an upper layer protocol (TCP) + */ +void +nd6_reachability_hint(ip6_addr_t * ip6addr) +{ + s8_t i; + + /* Find destination in cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + i = nd6_cached_destination_index; + ND6_STATS_INC(nd6.cachehit); + } + else { + i = nd6_find_destination_cache_entry(ip6addr); + } + if (i < 0) { + return; + } + + /* Find next hop neighbor in cache. */ + if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + i = nd6_cached_neighbor_index; + ND6_STATS_INC(nd6.cachehit); + } + else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); + } + if (i < 0) { + return; + } + + /* Set reachability state. */ + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; +} +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#endif /* LWIP_IPV6 */ diff --git a/Shared/lwip/src/core/mem.c b/Shared/lwip/src/core/mem.c new file mode 100644 index 0000000..f4fd409 --- /dev/null +++ b/Shared/lwip/src/core/mem.c @@ -0,0 +1,660 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include + +#if MEM_USE_POOLS +/* lwIP head implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { +#if MEM_USE_POOLS_TRY_BIGGER_POOL +again: +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_sizes[poolnr]) { + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + return NULL; + } + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already + taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + poolnr++; + goto again; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + + /* and put it in the pool we saved earlier */ + fprintf(stderr,"mem_free ###################\n"); + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if(sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if(newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if(mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Adam's mem_malloc() plus solution for bug #17922 + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if(size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + mem = (struct mem *)(void *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or excact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while(local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, count * size); + } + return p; +} + +#endif /* !MEM_LIBC_MALLOC */ diff --git a/Shared/lwip/src/core/memp.c b/Shared/lwip/src/core/memp.c new file mode 100644 index 0000000..1323463 --- /dev/null +++ b/Shared/lwip/src/core/memp.c @@ -0,0 +1,485 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/tcp_impl.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/api_msg.h" +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/timers.h" +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip_frag.h" +#include "lwip/snmp_structs.h" +#include "lwip/snmp_msg.h" +#include "lwip/dns.h" +#include "netif/ppp_oe.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" + +#include + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +/** This array holds the first free element of each pool. + * Elements form a linked list. */ +static struct memp *memp_tab[MEMP_MAX]; + +#else /* MEMP_MEM_MALLOC */ + +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_MEM_MALLOC */ + +/** This array holds the element sizes of each pool. */ +#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC +static +#endif +const u16_t memp_sizes[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), +#include "lwip/memp_std.h" +}; + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +/** This array holds the number of elements in each pool. */ +static const u16_t memp_num[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (num), +#include "lwip/memp_std.h" +}; + +/** This array holds a textual description of each pool. */ +#ifdef LWIP_DEBUG +static const char *memp_desc[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (desc), +#include "lwip/memp_std.h" +}; +#endif /* LWIP_DEBUG */ + +#if MEMP_SEPARATE_POOLS + +/** This creates each memory pool. These are named memp_memory_XXX_base (where + * XXX is the name of the pool defined in memp_std.h). + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; + */ +#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ + [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; +#include "lwip/memp_std.h" + +/** This array holds the base of each memory pool. */ +static u8_t *const memp_bases[] = { +#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, +#include "lwip/memp_std.h" +}; + +#else /* MEMP_SEPARATE_POOLS */ + +/** This is the actual memory used by the pools (all pools in one big block). */ +static u8_t memp_memory[MEM_ALIGNMENT - 1 +#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) +#include "lwip/memp_std.h" +]; + +#endif /* MEMP_SEPARATE_POOLS */ + +#if MEMP_SANITY_CHECK +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(void) +{ + s16_t i; + struct memp *t, *h; + + for (i = 0; i < MEMP_MAX; i++) { + t = memp_tab[i]; + if(t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + } + return 1; +} +#endif /* MEMP_SANITY_CHECK*/ +#if MEMP_OVERFLOW_CHECK +#if defined(LWIP_DEBUG) && MEMP_STATS +static const char * memp_overflow_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) "/"desc, +#include "lwip/memp_std.h" + }; +#endif + +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + +#if !MEMP_SEPARATE_POOLS + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { +#if MEMP_SEPARATE_POOLS + p = (struct memp *)(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_overflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +#if !MEMP_SEPARATE_POOLS + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { +#if MEMP_SEPARATE_POOLS + p = (struct memp *)(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_underflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} + +/** + * Initialize the restricted areas of all memp elements in every pool. + */ +static void +memp_overflow_init(void) +{ + u16_t i, j; + struct memp *p; + u8_t *m; + +#if !MEMP_SEPARATE_POOLS + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { +#if MEMP_SEPARATE_POOLS + p = (struct memp *)(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + for (j = 0; j < memp_num[i]; ++j) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize this module. + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + struct memp *memp; + u16_t i, j; + + for (i = 0; i < MEMP_MAX; ++i) { + MEMP_STATS_AVAIL(used, i, 0); + MEMP_STATS_AVAIL(max, i, 0); + MEMP_STATS_AVAIL(err, i, 0); + MEMP_STATS_AVAIL(avail, i, memp_num[i]); + } + +#if !MEMP_SEPARATE_POOLS + memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + /* for every pool: */ + for (i = 0; i < MEMP_MAX; ++i) { + memp_tab[i] = NULL; +#if MEMP_SEPARATE_POOLS + memp = (struct memp*)memp_bases[i]; +#endif /* MEMP_SEPARATE_POOLS */ + /* create a linked list of memp elements */ + for (j = 0; j < memp_num[i]; ++j) { + memp->next = memp_tab[i]; + memp_tab[i] = memp; + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + } +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(); + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * the debug version has two more parameters: + * @param file file name calling this function + * @param line number of line where this function is called + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + memp = memp_tab[type]; + + if (memp != NULL) { + memp_tab[type] = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + MEMP_STATS_INC_USED(used, type); + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); + MEMP_STATS_INC(err, type); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + if (mem == NULL) { + return; + } + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#else + memp_overflow_check_element_overflow(memp, type); + memp_overflow_check_element_underflow(memp, type); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + + MEMP_STATS_DEC(used, type); + + memp->next = memp_tab[type]; + memp_tab[type] = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity()); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +} + +#endif /* MEMP_MEM_MALLOC */ diff --git a/Shared/lwip/src/core/netif.c b/Shared/lwip/src/core/netif.c new file mode 100644 index 0000000..dcc8758 --- /dev/null +++ b/Shared/lwip/src/core/netif.c @@ -0,0 +1,913 @@ +/** + * @file + * lwIP network interface abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#if ENABLE_LOOPBACK +#include "lwip/sys.h" +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_IPV6_MLD +#include "lwip/mld6.h" +#endif /* LWIP_IPV6_MLD */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#if LWIP_IPV6 +static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +#if LWIP_HAVE_LOOPIF +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; + netif->output = netif_loop_output; + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF + ip_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); + +#if NO_SYS + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack. + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input) +{ +#if LWIP_IPV6 + u32_t i; +#endif + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + ip6_addr_set_zero(&netif->ip6_addr[i]); + netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); + } + netif->output_ip6 = netif_null_output_ip6; +#endif /* LWIP_IPV6 */ + netif->flags = 0; +#if LWIP_DHCP + /* netif not under DHCP control by default */ + netif->dhcp = NULL; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /* netif not under AutoIP control by default */ + netif->autoip = NULL; +#endif /* LWIP_AUTOIP */ +#if LWIP_IPV6_AUTOCONFIG + /* IPv6 address autoconfiguration not enabled by default */ + netif->ip6_autoconfig_enabled = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_IPV6_DHCP6 + /* netif not under DHCPv6 control by default */ + netif->dhcp6 = NULL; +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->mld_mac_filter = NULL; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + + netif_set_addr(netif, ipaddr, netmask, gw); + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + snmp_inc_iflist(); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", + netif->name[0], netif->name[1])); + ip_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip_addr_debug_print(NETIF_DEBUG, gw); + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +/** + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw) +{ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); +} + +/** + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ + if (netif == NULL) { + return; + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* stop MLD processing */ + mld6_stop(netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + snmp_delete_ipaddridx_tree(netif); + + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmpNetif; + for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { + if (tmpNetif->next == netif) { + tmpNetif->next = netif->next; + break; + } + } + if (tmpNetif == NULL) + return; /* we didn't find any netif today */ + } + snmp_dec_iflist(); + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = name[2] - '0'; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +int netif_is_named (struct netif *netif, const char name[3]) +{ + u8_t num = name[2] - '0'; + + return (!memcmp(netif->name, name, 2) && netif->num == num); +} + +/** + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* TODO: Handling of obsolete pcbs */ + /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ +#if LWIP_TCP + struct tcp_pcb *pcb; + struct tcp_pcb_listen *lpcb; + + /* address is actually being changed? */ + if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { + /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); + pcb = tcp_active_pcbs; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr)) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + /* PCB bound to current local interface address? */ + if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) && + (ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr); + } + } + } +#endif + snmp_delete_ipaddridx_tree(netif); + snmp_delete_iprteidx_tree(0,netif); + /* set new IP address to netif */ + ip_addr_set(&(netif->ip_addr), ipaddr); + snmp_insert_ipaddridx_tree(netif); + snmp_insert_iprteidx_tree(0,netif); + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->ip_addr), + ip4_addr2_16(&netif->ip_addr), + ip4_addr3_16(&netif->ip_addr), + ip4_addr4_16(&netif->ip_addr))); +} + +/** + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, ip_addr_t *gw) +{ + ip_addr_set(&(netif->gw), gw); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->gw), + ip4_addr2_16(&netif->gw), + ip4_addr3_16(&netif->gw), + ip4_addr4_16(&netif->gw))); +} + +void netif_set_pretend_tcp (struct netif *netif, u8_t pretend) +{ + if (pretend) { + netif->flags |= NETIF_FLAG_PRETEND_TCP; + } else { + netif->flags &= ~NETIF_FLAG_PRETEND_TCP; + } +} + +/** + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, ip_addr_t *netmask) +{ + snmp_delete_iprteidx_tree(0, netif); + /* set new netmask to netif */ + ip_addr_set(&(netif->netmask), netmask); + snmp_insert_iprteidx_tree(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->netmask), + ip4_addr2_16(&netif->netmask), + ip4_addr3_16(&netif->netmask), + ip4_addr4_16(&netif->netmask))); +} + +/** + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + snmp_delete_iprteidx_tree(1, netif); + } else { + /* install default route */ + snmp_insert_iprteidx_tree(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * Bring an interface up, available for processing + * traffic. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif /* LWIP_SNMP */ + + NETIF_STATUS_CALLBACK(netif); + + if (netif->flags & NETIF_FLAG_LINK_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups( netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send Router Solicitation messages. */ + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + } + } +} + +/** + * Bring an interface down, disabling any traffic processing. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif + +#if LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_ARP */ + NETIF_STATUS_CALLBACK(netif); + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * Called by a driver when its link goes up + */ +void netif_set_link_up(struct netif *netif ) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + if (netif->dhcp) { + dhcp_network_changed(netif); + } +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(netif); + } +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups( netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + } + NETIF_LINK_CALLBACK(netif); + } +} + +/** + * Called by a driver when its link goes down + */ +void netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @param ipaddr the ip address to send the packet to (not used) + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ipaddr); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + + SYS_ARCH_PROTECT(lev); + if(netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + snmp_add_ifoutoctets(stats_if, p->tot_len); + snmp_inc_ifoutucastpkts(stats_if); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback((tcpip_callback_fn)netif_poll, netif); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + struct pbuf *in; + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = netif->loop_first; + if (in != NULL) { + struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = pbuf_clen(in); + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; + } + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + } + SYS_ARCH_UNPROTECT(lev); + + if (in != NULL) { + LINK_STATS_INC(link.recv); + snmp_add_ifinoctets(stats_if, in->tot_len); + snmp_inc_ifinucastpkts(stats_if); + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + } + /* go on while there is a packet on the list */ + } while (netif->loop_first != NULL); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_IPV6 +s8_t +netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { + return i; + } + } + return -1; +} + +void +netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit) +{ + u8_t i, addr_index, min_len; + + /* Link-local prefix. */ + netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul); + netif->ip6_addr[0].addr[1] = 0; + + /* Generate interface ID. */ + if (from_mac_48bit) { + /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ + netif->ip6_addr[0].addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | + ((u32_t)(netif->hwaddr[1]) << 16) | + ((u32_t)(netif->hwaddr[2]) << 8) | + (0xff)); + netif->ip6_addr[0].addr[3] = htonl((0xfeul << 24) | + ((u32_t)(netif->hwaddr[3]) << 16) | + ((u32_t)(netif->hwaddr[4]) << 8) | + (netif->hwaddr[5])); + } + else { + /* Use hwaddr directly as interface ID. */ + netif->ip6_addr[0].addr[2] = 0; + netif->ip6_addr[0].addr[3] = 0; + + min_len = netif->hwaddr_len < 8 ? netif->hwaddr_len : 8; + addr_index = 3; + for (i = 0; i < min_len; i++) { + if (i == 4) { + addr_index--; + } + netif->ip6_addr[0].addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); + } + } + + /* Set address state. */ +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* Will perform duplicate address detection (DAD). */ + netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE; +#else + /* Consider address valid. */ + netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED; +#endif /* LWIP_IPV6_AUTOCONFIG */ +} + +static err_t +netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr) +{ + (void)netif; + (void)p; + (void)ipaddr; + + return ERR_IF; +} +#endif /* LWIP_IPV6 */ diff --git a/Shared/lwip/src/core/pbuf.c b/Shared/lwip/src/core/pbuf.c new file mode 100644 index 0000000..1e5e53b --- /dev/null +++ b/Shared/lwip/src/core/pbuf.c @@ -0,0 +1,1179 @@ +/** + * @file + * Packet buffer management + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "arch/perf.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/tcp_impl.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 0; + SYS_ARCH_UNPROTECT(old_level); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if(!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccesfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Initialize a custom pbuf (already allocated). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len)) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns succesful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0){ + increment_magnitude = -header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)(p + 1))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccesfully */ + return 1; + } + /* pbuf types refering to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccesfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ + +u8_t +pbuf_clen(struct pbuf *p) +{ + u8_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(old_level); + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + ++(p->ref); + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ + +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (void*)p_to, (void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_from->next == NULL), return ERR_VAL;); + } + if((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +/** + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /** Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(struct pbuf* p, u16_t offset) +{ + u16_t copy_from = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= copy_from)) { + copy_from -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > copy_from)) { + return ((u8_t*)q->payload)[copy_from]; + } + return 0; +} + +/** Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at wich to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > start)) { + u16_t i; + for(i = 0; i < n; i++) { + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; + } + return 0xffff; +} + +/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for(i = start_offset; i <= max; ) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } else { + i += plus; + } + } + } + return 0xFFFF; +} + +/** Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/Shared/lwip/src/core/stats.c b/Shared/lwip/src/core/stats.c new file mode 100644 index 0000000..06fbe0f --- /dev/null +++ b/Shared/lwip/src/core/stats.c @@ -0,0 +1,181 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" + +#include + +struct stats_ lwip_stats; + +void stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEMP_STATS + const char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + int i; + for (i = 0; i < MEMP_MAX; i++) { + lwip_stats.memp[i].name = memp_names[i]; + } +#endif /* MEMP_STATS */ +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS +void +stats_display_igmp(struct stats_igmp *igmp, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); +} +#endif /* IGMP_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + if(index < MEMP_MAX) { + stats_display_mem(mem, memp_names[index]); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP6_FRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + ND6_STATS_DISPLAY(); + IP6_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + MLD6_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + ICMP6_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/Shared/lwip/src/core/tcp.c b/Shared/lwip/src/core/tcp.c new file mode 100644 index 0000000..7379d77 --- /dev/null +++ b/Shared/lwip/src/core/tcp.c @@ -0,0 +1,1856 @@ +/** + * @file + * Transmission Control Protocol for IP + * + * This file contains common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/snmp.h" +#include "lwip/tcp.h" +#include "lwip/tcp_impl.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" + +#include + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +const char * const tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* last local TCP port */ +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +const u8_t tcp_backoff[13] = + { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +#define NUM_TCP_PCB_LISTS 4 +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +/** Only used for temporary storage. */ +struct tcp_pcb *tcp_tmp_pcb; + +u8_t tcp_active_pcbs_changed; + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_tmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + err_t err; + + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + memp_free(MEMP_TCP_PCB, pcb); + } + return ERR_OK; + } + } + + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + if (pcb->local_port != 0 || pcb->bound_to_netif) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; + case LISTEN: + err = ERR_OK; + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + pcb = NULL; + break; + case SYN_SENT: + err = ERR_OK; + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + snmp_inc_tcpattemptfails(); + break; + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpattemptfails(); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + err = ERR_OK; + pcb = NULL; + break; + } + + if (pcb != NULL && err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + /* @todo: When implementing SO_LINGER, this must be changed somehow: + If SOF_LINGER is set, the data should be sent and acked before close returns. + This can only be valid for sequential APIs, not for the raw API. */ + tcp_output(pcb); + } + return err; +} + +/** + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ +#if TCP_DEBUG + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + if (pcb->state <= 10) { + //return ERR_OK; + tcp_debug_print_state(pcb->state); + } + +#endif /* TCP_DEBUG */ + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds, + * the PCB should not be referenced any more. + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + int send_rst = reset && (pcb->state != CLOSED); + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + TCP_PCB_REMOVE_ACTIVE(pcb); + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + if (send_rst) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); + } + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + } +} + +/** + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * Binds the connection to a local portnumber and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } + + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* @todo: check accept_any_ip_version */ + if (IP_PCB_IPVER_EQ(pcb, cpcb) && + (ipX_addr_isany(PCB_ISIPV6(pcb), &cpcb->local_ip) || + ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr)) || + ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, ip_2_ipX(ipaddr)))) { + return ERR_USE; + } + } + } + } + } + + pcb->bound_to_netif = 0; + if (!ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr))) { + ipX_addr_set(PCB_ISIPV6(pcb), &pcb->local_ip, ip_2_ipX(ipaddr)); + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} + +err_t +tcp_bind_to_netif(struct tcp_pcb *pcb, const char ifname[3]) +{ + LWIP_ERROR("tcp_bind_if: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + /* Check if the interface is already in use */ + for (int i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for(struct tcp_pcb *cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (IP_PCB_IPVER_EQ(pcb, cpcb) && + cpcb->bound_to_netif && + !memcmp(cpcb->local_netif, ifname, sizeof(cpcb->local_netif))) { + return ERR_USE; + } + } + } + + pcb->bound_to_netif = 1; + ipX_addr_set_any(PCB_ISIPV6(pcb), &pcb->local_ip); + pcb->local_port = 0; + memcpy(pcb->local_netif, ifname, sizeof(pcb->local_netif)); + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind_to_netif: bind to interface %c%c%c\n", ifname[0], ifname[1], ifname[2])); + return ERR_OK; +} + +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(err); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen(tpcb); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb_listen *lpcb; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); + + /* already listening? */ + if (pcb->state == LISTEN) { + return pcb; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR) && !pcb->have_local_netif) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + IP_PCB_IPVER_EQ(pcb, lpcb)) { + if (ipX_addr_cmp(PCB_ISIPV6(pcb), &lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + return NULL; + } + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + return NULL; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->bound_to_netif = pcb->bound_to_netif; + lpcb->local_port = pcb->local_port; + memcpy(lpcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif)); + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + ip_set_option(lpcb, SOF_ACCEPTCONN); + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; +#if LWIP_IPV6 + PCB_ISIPV6(lpcb) = PCB_ISIPV6(pcb); + lpcb->accept_any_ip_version = 0; +#endif /* LWIP_IPV6 */ + ipX_addr_copy(PCB_ISIPV6(pcb), lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0 || pcb->bound_to_netif) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + lpcb->backlog = (backlog ? backlog : 1); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + return (struct tcp_pcb *)lpcb; +} + +#if LWIP_IPV6 +/** + * Same as tcp_listen_with_backlog, but allows to accept IPv4 and IPv6 + * connections, if the pcb's local address is set to ANY. + */ +struct tcp_pcb * +tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb *lpcb; + + lpcb = tcp_listen_with_backlog(pcb, backlog); + if ((lpcb != NULL) && + ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + /* The default behavior is to accept connections on either + * IPv4 or IPv6, if not bound. */ + /* @see NETCONN_FLAG_IPV6_V6ONLY for changing this behavior */ + ((struct tcp_pcb_listen*)lpcb)->accept_any_ip_version = 1; + } + return lpcb; +} +#endif /* LWIP_IPV6 */ + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); + pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", + len <= 0xffff - pcb->rcv_wnd ); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND) { + pcb->rcv_wnd = TCP_WND; + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", + len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + +again: + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (or on error) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + LWIP_ERROR("tcp_connect: cannot connect pcb bound to netif", !pcb->bound_to_netif, return ERR_VAL); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + if (ipaddr != NULL) { + ipX_addr_set(PCB_ISIPV6(pcb), &pcb->remote_ip, ip_2_ipX(ipaddr)); + } else { + return ERR_VAL; + } + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + /* no local IP address set, yet. */ + struct netif *netif; + ipX_addr_t *local_ip; + ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the address as local address of the pcb. */ + ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + IP_PCB_IPVER_EQ(cpcb, pcb) && + ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, &pcb->local_ip) && + ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->remote_ip, ip_2_ipX(ipaddr))) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + iss = tcp_next_iss(); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_lbb = iss - 1; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; + pcb->ssthresh = pcb->mss * 10; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + snmp_inc_tcpactiveopens(); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + u16_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx == TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + pcb->persist_cnt++; + if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + tcp_zero_window_probe(pcb); + } + } else { + /* Increase the retransmission timer if it is running */ + if(pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F + " ssthresh %"U16_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if(ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + ++pcb_remove; + ++pcb_reset; + } + else if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + tcp_keepalive(pcb); + pcb->keep_cnt_sent++; + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_err_fn err_fn; + void *err_arg; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); + } + + err_fn = pcb->errf; + err_arg = pcb->callback_arg; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while(pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; + pcb->refused_data = NULL; + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ + pcb->refused_data = refused_data; + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + + mprio = TCP_PRIO_MAX; + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= prio && + pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + u32_t iss; + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed twice before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: timewait PCB was freed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + pcb->snd_queuelen = 0; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->tos = 0; + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sa = 0; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + iss = tcp_next_iss(); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + pcb->polltmr = 0; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + + pcb->keep_cnt_sent = 0; + } + return pcb; +} + +/** + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +#if LWIP_IPV6 +/** + * Creates a new TCP-over-IPv6 protocol control block but doesn't + * place it on any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new_ip6(void) +{ + struct tcp_pcb * pcb; + pcb = tcp_alloc(TCP_PRIO_NORMAL); + ip_set_v6(pcb, 1); + return pcb; +} +#endif /* LWIP_IPV6 */ + +/** + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->callback_arg = arg; +} +#if LWIP_CALLBACK_API + +/** + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; +} + +/** + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; +} + +/** + * Used to specify the function that should be called when a fatal error + * has occured on the connection. + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occured on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; +} + +/** + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->accept = accept; +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((!lpcb->bound_to_netif && !pcb->bound_to_netif && + (lpcb->local_port == pcb->local_port) && + IP_PCB_IPVER_EQ(pcb, lpcb) && + (ipX_addr_isany(PCB_ISIPV6(lpcb), &lpcb->local_ip) || + ipX_addr_cmp(PCB_ISIPV6(lpcb), &pcb->local_ip, &lpcb->local_ip))) || + (lpcb->bound_to_netif && pcb->bound_to_netif && + !memcmp(lpcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif)))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(void) +{ + static u32_t iss = 6510; + + iss += tcp_ticks; /* XXX */ + return iss; +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calcluates the effective send mss that can be used for a specific IP address + * by using ip_route to determin the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest +#if LWIP_IPV6 + , ipX_addr_t *src, u8_t isipv6 +#endif /* LWIP_IPV6 */ + ) +{ + u16_t mss_s; + struct netif *outif; + s16_t mtu; + + outif = ipX_route(isipv6, src, dest); +#if LWIP_IPV6 + if (isipv6) { + /* First look in destination cache, to see if there is a Path MTU. */ + mtu = nd6_get_destination_mtu(ipX_2_ip6(dest), outif); + } else +#endif /* LWIP_IPV6 */ + { + if (outif == NULL) { + return sendmss; + } + mtu = outif->mtu; + } + + if (mtu != 0) { + mss_s = mtu - IP_HLEN - TCP_HLEN; +#if LWIP_IPV6 + /* for IPv6, substract the difference in header size */ + mss_s -= (IP6_HLEN - IP_HLEN); +#endif /* LWIP_IPV6 */ + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(tcphdr->src), ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + TCPH_FLAGS(tcphdr) >> 5 & 1, + TCPH_FLAGS(tcphdr) >> 4 & 1, + TCPH_FLAGS(tcphdr) >> 3 & 1, + TCPH_FLAGS(tcphdr) >> 2 & 1, + TCPH_FLAGS(tcphdr) >> 1 & 1, + TCPH_FLAGS(tcphdr) & 1, + ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/Shared/lwip/src/core/tcp_in.c b/Shared/lwip/src/core/tcp_in.c new file mode 100644 index 0000000..44c2bcc --- /dev/null +++ b/Shared/lwip/src/core/tcp_in.c @@ -0,0 +1,1677 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#if LWIP_ND6_TCP_REACHABILITY_HINTS +#include "lwip/nd6.h" +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static u32_t seqno, ackno; +static u8_t flags; +static u16_t tcplen; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); +static err_t tcp_timewait_input(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the TCP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen; + err_t err; +#if CHECKSUM_CHECK_TCP + u16_t chksum; +#endif /* CHECKSUM_CHECK_TCP */ + + PERF_START; + + TCP_STATS_INC(tcp.recv); + snmp_inc_tcpinsegs(); + + tcphdr = (struct tcp_hdr *)p->payload; + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* Check that TCP header fits in payload */ + if (p->len < sizeof(struct tcp_hdr)) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) || + ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + /* Verify TCP checksum. */ + chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len, + ipX_current_src_addr(), ipX_current_dest_addr()); + if (chksum != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + chksum)); + tcp_debug_print(tcphdr); + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } +#endif /* CHECKSUM_CHECK_TCP */ + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + hdrlen = TCPH_HDRLEN(tcphdr); + if(pbuf_header(p, -(hdrlen * 4))){ + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = ntohs(tcphdr->src); + tcphdr->dest = ntohs(tcphdr->dest); + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); + tcphdr->wnd = ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + IP_PCB_IPVER_INPUT_MATCH(pcb) && + ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) && + ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + IP_PCB_IPVER_INPUT_MATCH(pcb) && + ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) && + ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + struct tcp_pcb_listen *netif_pcb = NULL; + struct tcp_pcb *netif_pcb_prev = NULL; + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->bound_to_netif) { + if (IP_PCB_IPVER_INPUT_MATCH(lpcb) && netif_is_named(inp, lpcb->local_netif)) { + netif_pcb = lpcb; + netif_pcb_prev = prev; + } + } + else if (lpcb->local_port == tcphdr->dest) { +#if LWIP_IPV6 + if (lpcb->accept_any_ip_version) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; +#endif /* SO_REUSE */ + } else +#endif /* LWIP_IPV6 */ + if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) { + if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) { + /* found an exact match */ + break; + } else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; + #endif /* SO_REUSE */ + } + } + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb == NULL && netif_pcb) { + lpcb = netif_pcb; + prev = netif_pcb_prev; + } + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (pcb->acked > 0) { + TCP_EVENT_SENT(pcb, pcb->acked, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + + if (recv_data != NULL) { + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + /* Try to send something out. */ + + // printf("tcp_output %p",pcb); +// if (pcb->state > 10 ) { +// goto aborted; +// } + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + + if (pcb->state <= 10 ) { + tcp_debug_print_state(pcb->state); + }else { + goto aborted; + } + +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * @return ERR_OK if the segment was processed + * another err_t on error + * + * @note the return value is not (yet?) used in tcp_input() + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return ERR_OK; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return ERR_ABRT; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ +#if LWIP_IPV6 + PCB_ISIPV6(npcb) = ip_current_is_v6(); +#endif /* LWIP_IPV6 */ + ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr()); + ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr()); + npcb->bound_to_netif = pcb->bound_to_netif; + npcb->local_port = tcphdr->dest; + memcpy(npcb->local_netif, pcb->local_netif, sizeof(pcb->local_netif)); + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + npcb->snd_wnd = tcphdr->wnd; + npcb->snd_wnd_max = tcphdr->wnd; + npcb->ssthresh = npcb->snd_wnd; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API + npcb->accept = pcb->accept; +#endif /* LWIP_CALLBACK_API */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, + &npcb->remote_ip, PCB_ISIPV6(npcb)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + snmp_inc_tcppassiveopens(); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } + return tcp_output(npcb); + } + return ERR_OK; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return ERR_OK; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + return ERR_OK; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + return tcp_output(pcb); + } + return ERR_OK; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt+pcb->rcv_wnd)) { + acceptable = 1; + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wnd_max = tcphdr->wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, + PCB_ISIPV6(pcb)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + /* Set ssthresh again after changing pcb->mss (already set in tcp_connect + * but for the default value of pcb->mss) */ + pcb->ssthresh = pcb->mss * 10; + + pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + pcb->unacked = rseg->next; + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when sucessfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + u16_t old_cwnd; + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); +#endif + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + old_cwnd = pcb->cwnd; + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (pcb->acked != 0) { + pcb->acked--; + } + + pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } + else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, is places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + struct pbuf *p; + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { + pcb->snd_wnd = tcphdr->wnd; + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < tcphdr->wnd) { + pcb->snd_wnd_max = tcphdr->wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != tcphdr->wnd) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + pcb->acked = 0; + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Update the send buffer space. Diff between the two can never exceed 64K? */ + pcb->acked = (u16_t)(ackno - pcb->lastack); + + pcb->snd_buf += pcb->acked; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); + } else { + u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowlegdes them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else + pcb->rtime = 0; + + pcb->polltmr = 0; + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (PCB_ISIPV6(pcb)) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + } else { + /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ + pcb->acked = 0; + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if(pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if(pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)){ + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + inseg.len = pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (PCB_ISIPV6(pcb)) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for(next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lenghts are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno; + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not withing the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ + tcp_ack_now(pcb); + } + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u16_t c, max_c; + u16_t mss; + u8_t *opts, opt; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + opts = (u8_t *)tcphdr + TCP_HLEN; + + /* Parse the TCP MSS option, if present. */ + if(TCPH_HDRLEN(tcphdr) > 0x5) { + max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; + for (c = 0; c < max_c; ) { + opt = opts[c]; + switch (opt) { + case 0x00: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case 0x01: + /* NOP option. */ + ++c; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case 0x02: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (opts[c + 2] << 8) | opts[c + 3]; + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + /* Advance to next option */ + c += 0x04; + break; +#if LWIP_TCP_TIMESTAMPS + case 0x08: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = (opts[c+2]) | (opts[c+3] << 8) | + (opts[c+4] << 16) | (opts[c+5] << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = ntohl(tsval); + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = ntohl(tsval); + } + /* Advance to next option */ + c += 0x0A; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + if (opts[c + 1] == 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + c += opts[c + 1]; + } + } + } +} + +#endif /* LWIP_TCP */ diff --git a/Shared/lwip/src/core/tcp_out.c b/Shared/lwip/src/core/tcp_out.c new file mode 100644 index 0000000..4a1e626 --- /dev/null +++ b/Shared/lwip/src/core/tcp_out.c @@ -0,0 +1,1503 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif + +/* Forward declarations.*/ +static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(pcb->local_port); + tcphdr->dest = htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = htons(pcb->rcv_ann_wnd); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = htons(pcb->local_port); + seg->tcphdr->dest = htons(pcb->remote_port); + seg->tcphdr->seqno = htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that willo enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + * @param + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + /* always create MSS-sized pbufs */ + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE)); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#endif /* TCP_OVERSIZE */ +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2); + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); + seg = last_unsent; + oversize_used = oversize < len ? oversize : len; + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = space < len - pos ? space : len - pos; + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + last_unsent->oversize_left += oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } else { + /* Data is not copied */ + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + concat_p->payload = (u8_t*)arg + pos; + } + + pos += seglen; + queuelen += pbuf_clen(concat_p); + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = left > max_len ? max_len : left; +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((u8_t*)arg + pos, seglen); +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + p2->payload = (u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + * @param optdata pointer to TCP options, or NULL. + * @param optlen length of TCP options in bytes. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* tcp_enqueue_flags is always called with either SYN or FIN in flags. + * We need one available snd_buf byte to do that. + * This means we can't send FIN while snd_buf==0. A better fix would be to + * not include SYN and FIN sequence numbers in the snd_buf count. */ + if (pcb->snd_buf == 0) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + pcb->snd_buf--; + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = htonl(sys_now()); + opts[2] = htonl(pcb->ts_recent); +} +#endif + +/** Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + struct pbuf *p; + u8_t optlen = 0; +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); + if (p == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + /* remove ACK flags from the PCB, as we send an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + + /* NB. MSS option is only sent on SYNs, so ignore it here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); +#endif +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, + IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + pbuf_free(p); + + return ERR_OK; +} + +/** + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + //fixme + //if (seg->tcphdr != NULL){ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + //} + + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F + ", cwnd %"U16_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* data available and window allows it to be sent? */ + while (seg != NULL && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + pcb->unsent = seg->next; + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ + tcp_output_segment(seg, pcb); + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + */ +static void +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) +{ + u16_t len; + u32_t *opts; + + /** @bug Exclude retransmitted segments from this count. */ + snmp_inc_tcpoutsegs(); + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ + seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb)); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime == -1) { + pcb->rtime = 0; + } + + /* If we don't have a local IP address, we get one by + calling ip_route(). */ + if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + struct netif *netif; + ipX_addr_t *local_ip; + ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + return; + } + ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip); + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if TCP_CHECKSUM_ON_COPY + { + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, + seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + } +#else /* TCP_CHECKSUM_ON_COPY */ +#if CHECKSUM_GEN_TCP + seg->tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* CHECKSUM_GEN_TCP */ +#endif /* TCP_CHECKSUM_ON_COPY */ + TCP_STATS_INC(tcp.xmit); + +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + pcb->tos, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst_impl(u32_t seqno, u32_t ackno, + ipX_addr_t *local_ip, ipX_addr_t *remote_ip, + u16_t local_port, u16_t remote_port +#if LWIP_IPV6 + , u8_t isipv6 +#endif /* LWIP_IPV6 */ + ) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(local_port); + tcphdr->dest = htons(remote_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); + tcphdr->wnd = PP_HTONS(TCP_WND); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + TCP_STATS_INC(tcp.xmit); + snmp_inc_tcpoutrsts(); + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = ipX_chksum_pseudo(isipv6, p, IP_PROTO_TCP, p->tot_len, + local_ip, remote_ip); +#endif + /* Send output with hardcoded TTL/HL since we have no access to the pcb */ + ipX_output(isipv6, p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + /* last unsent hasn't changed, no need to reset unsent_oversize */ + + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retramsmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + ++pcb->nrtx; + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + snmp_inc_tcpretranssegs(); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + if (pcb->cwnd > pcb->snd_wnd) { + pcb->ssthresh = pcb->snd_wnd / 2; + } else { + pcb->ssthresh = pcb->cwnd / 2; + } + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < 2*pcb->mss) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"U16_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, 2*pcb->mss)); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +void +tcp_keepalive(struct tcp_pcb *pcb) +{ + struct pbuf *p; +#if CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* CHECKSUM_GEN_TCP */ + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return; + } +#if CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; + + tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +void +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if(seg == NULL) { + seg = pcb->unsent; + } + if(seg == NULL) { + return; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} +#endif /* LWIP_TCP */ diff --git a/Shared/lwip/src/core/timers.c b/Shared/lwip/src/core/timers.c new file mode 100644 index 0000000..c8ead4e --- /dev/null +++ b/Shared/lwip/src/core/timers.c @@ -0,0 +1,546 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timers.h" +#include "lwip/tcp_impl.h" + +#if LWIP_TIMERS + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/tcpip.h" + +#include "lwip/ip_frag.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +#if NO_SYS +static u32_t timeouts_last_time; +#endif /* NO_SYS */ + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +#if LWIP_IPV6 +/** + * Timer callback function that calls nd6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +nd6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n")); + nd6_tmr(); + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +} + +#if LWIP_IPV6_REASS +/** + * Timer callback function that calls ip6_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip6_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n")); + ip6_reass_tmr(); + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +} +#endif /* LWIP_IPV6_REASS */ + +#if LWIP_IPV6_MLD +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +mld6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n")); + mld6_tmr(); + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +} +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +/** Initialize this module */ +void sys_timeouts_init(void) +{ +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +#if LWIP_IPV6_REASS + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +#if NO_SYS + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +#endif +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } else { + for(t = next_timeout; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry, even though the timeout has not triggered yet. + * + * @note This function only works as expected if there is only one timeout + * calling 'handler' in the list of timeouts. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout(sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + next_timeout = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +#if NO_SYS + +/** Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +void +sys_check_timeouts(void) +{ + if (next_timeout) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do + { +#if PBUF_POOL_FREE_OOSEQ + PBUF_CHECK_FREE_OOSEQ(); +#endif /* PBUF_POOL_FREE_OOSEQ */ + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time = now; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + handler(arg); + } + } + /* repeat until all expired timers have been called */ + }while(had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +#else /* NO_SYS */ + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeo *tmptimeout; + sys_timeout_handler handler; + void *arg; + + again: + if (!next_timeout) { + time_needed = sys_arch_mbox_fetch(mbox, msg, 0); + } else { + if (next_timeout->time > 0) { + time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = next_timeout; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); + handler(arg); + UNLOCK_TCPIP_CORE(); + } + LWIP_TCPIP_THREAD_ALIVE(); + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < next_timeout->time) { + next_timeout->time -= time_needed; + } else { + next_timeout->time = 0; + } + } + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS */ diff --git a/Shared/lwip/src/core/udp.c b/Shared/lwip/src/core/udp.c new file mode 100644 index 0000000..ac0e56d --- /dev/null +++ b/Shared/lwip/src/core/udp.c @@ -0,0 +1,1151 @@ +/** + * @file + * User Datagram Protocol module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +/* udp.c + * + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/icmp6.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/dhcp.h" + +#include + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +#if 0 + struct udp_pcb *ipcb = udp_pcbs; + while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { + if (ipcb->local_port == udp_port) { + /* port is already used by another udp_pcb */ + udp_port++; + /* restart scanning all udp pcbs */ + ipcb = udp_pcbs; + } else { + /* go on with next udp pcb */ + ipcb = ipcb->next; + } + } + if (ipcb != NULL) { + return 0; + } + return udp_port; +#endif +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + u16_t src, dest; + u8_t local_match; + u8_t broadcast; + u8_t for_us; + + PERF_START; + + UDP_STATS_INC(udp.recv); + + /* Check minimum length (UDP header) */ + if (p->len < UDP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ +#if LWIP_IPV6 + broadcast = !ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp); +#else /* LWIP_IPV6 */ + broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), inp); +#endif /* LWIP_IPV6 */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = ntohs(udphdr->src); + dest = ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, ("udp (")); + ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_dest_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest))); + ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_src_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src))); + +#if LWIP_DHCP + pcb = NULL; + /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by + the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ + if (dest == DHCP_CLIENT_PORT) { + /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ + if (src == DHCP_SERVER_PORT) { + if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { + /* accept the packe if + (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! + - inp->dhcp->pcb->remote == ANY or iphdr->src + (no need to check for IPv6 since the dhcp struct always uses IPv4) */ + if (ipX_addr_isany(0, &inp->dhcp->pcb->remote_ip) || + ip_addr_cmp(ipX_2_ip(&(inp->dhcp->pcb->remote_ip)), ip_current_src_addr())) { + pcb = inp->dhcp->pcb; + } + } + } + } else +#endif /* LWIP_DHCP */ + { + prev = NULL; + local_match = 0; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + local_match = 0; + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if (pcb->local_port == dest) { + if ( +#if LWIP_IPV6 + ((PCB_ISIPV6(pcb) && (ip_current_is_v6()) && + (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip)) || +#if LWIP_IPV6_MLD + ip6_addr_ismulticast(ip6_current_dest_addr()) || +#endif /* LWIP_IPV6_MLD */ + ip6_addr_cmp(ipX_2_ip6(&pcb->local_ip), ip6_current_dest_addr()))) || + (!PCB_ISIPV6(pcb) && + (ip_current_header() != NULL) && +#else /* LWIP_IPV6 */ + (( +#endif /* LWIP_IPV6 */ + ((!broadcast && ipX_addr_isany(0, &pcb->local_ip)) || + ip_addr_cmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr()) || +#if LWIP_IGMP + ip_addr_ismulticast(ip_current_dest_addr()) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(pcb, SOF_BROADCAST) && + (ipX_addr_isany(0, &pcb->local_ip) || + ip_addr_netcmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr(), &inp->netmask))))))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast && + (ipX_addr_isany(0, &pcb->local_ip) || + ip_addr_netcmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr(), &inp->netmask))))))) { +#endif /* IP_SOF_BROADCAST_RECV */ + local_match = 1; + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + } + } + /* compare PCB remote addr+port to UDP source addr+port */ + if ((local_match != 0) && + (pcb->remote_port == src) && IP_PCB_IPVER_INPUT_MATCH(pcb) && + (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->remote_ip) || + ipX_addr_cmp(PCB_ISIPV6(pcb), &pcb->remote_ip, ipX_current_src_addr()))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL) { + for_us = 1; + } else { +#if LWIP_IPV6 + if (ip_current_is_v6()) { + for_us = netif_matches_ip6_addr(inp, ip6_current_dest_addr()); + } else +#endif /* LWIP_IPV6 */ + { + for_us = ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr()); + } + } + if (for_us) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if CHECKSUM_CHECK_UDP +#if LWIP_UDPLITE + if (ip_current_header_proto() == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ + u16_t chklen = ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + goto chkerr; + } + } + if (ipX_chksum_pseudo_partial(ip_current_is_v6(), p, IP_PROTO_UDPLITE, + p->tot_len, chklen, + ipX_current_src_addr(), ipX_current_dest_addr()) != 0) { + goto chkerr; + } + } else +#endif /* LWIP_UDPLITE */ + { + if (udphdr->chksum != 0) { + if (ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_UDP, p->tot_len, + ipX_current_src_addr(), + ipX_current_dest_addr()) != 0) { + goto chkerr; + } + } + } +#endif /* CHECKSUM_CHECK_UDP */ + if(pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + if (pcb != NULL) { + snmp_inc_udpindatagrams(); +#if SO_REUSE && SO_REUSE_RXTOALL + if ((broadcast || +#if LWIP_IPV6 + ip6_addr_ismulticast(ip6_current_dest_addr()) || +#endif /* LWIP_IPV6 */ + ip_addr_ismulticast(ip_current_dest_addr())) && + ip_get_option(pcb, SOF_REUSEADDR)) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && +#if LWIP_IPV6 + ((PCB_ISIPV6(mpcb) && + (ip6_addr_ismulticast(ip6_current_dest_addr()) || + ip6_addr_cmp(ipX_2_ip6(&mpcb->local_ip), ip6_current_dest_addr()))) || + (!PCB_ISIPV6(mpcb) && +#else /* LWIP_IPV6 */ + (( +#endif /* LWIP_IPV6 */ + ((!broadcast && ipX_addr_isany(0, &mpcb->local_ip)) || + ip_addr_cmp(ipX_2_ip(&mpcb->local_ip), ip_current_dest_addr()) || +#if LWIP_IGMP + ip_addr_ismulticast(ip_current_dest_addr()) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast))))) { +#endif /* IP_SOF_BROADCAST_RECV */ + /* pass a copy of the packet to all local matches */ + if (mpcb->recv.ip4 != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header(p, hdrs_len); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -hdrs_len); +#if LWIP_IPV6 + if (PCB_ISIPV6(mpcb)) { + mpcb->recv.ip6(mpcb->recv_arg, mpcb, q, ip6_current_src_addr(), src); + } + else +#endif /* LWIP_IPV6 */ + { + mpcb->recv.ip4(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -hdrs_len); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv.ip4 != NULL) { + /* now the recv function is responsible for freeing p */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr(), src); + } + else +#endif /* LWIP_IPV6 */ + { + pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP || LWIP_ICMP6 + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && +#if LWIP_IPV6 + !ip6_addr_ismulticast(ip6_current_dest_addr()) && +#endif /* LWIP_IPV6 */ + !ip_addr_ismulticast(ip_current_dest_addr())) { + /* move payload pointer back to ip header */ + pbuf_header(p, ip_current_header_tot_len() + UDP_HLEN); + icmp_port_unreach(ip_current_is_v6(), p); + } +#endif /* LWIP_ICMP || LWIP_ICMP6 */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpnoports(); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); + return; +#if CHECKSUM_CHECK_UDP +chkerr: + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + PERF_STOP("udp_input"); +#endif /* CHECKSUM_CHECK_UDP */ +} + +/** + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +/** Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +/** + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct netif *netif; + ipX_addr_t *dst_ip_route = ip_2_ipX(dst_ip); + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + +#if LWIP_IPV6 || LWIP_IGMP + if (ipX_addr_ismulticast(PCB_ISIPV6(pcb), dst_ip_route)) { + /* For multicast, find a netif based on source address. */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + dst_ip_route = &pcb->local_ip; + } else +#endif /* LWIP_IPV6 */ + { +#if LWIP_IGMP + dst_ip_route = ip_2_ipX(&pcb->multicast_ip); +#endif /* LWIP_IGMP */ + } + } +#endif /* LWIP_IPV6 || LWIP_IGMP */ + + /* find the outgoing network interface for this packet */ + netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip_route); + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ip_2_ipX(dst_ip)); + LWIP_DEBUGF(UDP_DEBUG, ("\n")); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct udp_hdr *udphdr; + ip_addr_t *src_ip; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + u8_t ip_proto; + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && +#if LWIP_IPV6 + !PCB_ISIPV6(pcb) && +#endif /* LWIP_IPV6 */ + ip_addr_isbroadcast(dst_ip, netif) ) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = htons(pcb->local_port); + udphdr->dest = htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if LWIP_IGMP + if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && +#if LWIP_IPV6 + ( +#if LWIP_IPV6_MLD + (PCB_ISIPV6(pcb) && + ip6_addr_ismulticast(ip_2_ip6(dst_ip))) || +#endif /* LWIP_IPV6_MLD */ + (!PCB_ISIPV6(pcb) && +#else /* LWIP_IPV6 */ + (( +#endif /* LWIP_IPV6 */ + ip_addr_ismulticast(dst_ip)))) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* LWIP_IGMP */ + + + /* PCB local address is IP_ANY_ADDR? */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) { + src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip))); + if (src_ip == NULL) { + /* No suitable source address was found. */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + /* p is still referenced by the caller, and will live on */ + } + return ERR_RTE; + } + } else { + /* use UDP PCB local IPv6 address as source address, if still valid. */ + if (netif_matches_ip6_addr(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { + /* Address isn't valid anymore. */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + /* p is still referenced by the caller, and will live on */ + } + return ERR_RTE; + } + src_ip = ipX_2_ip(&pcb->local_ip); + } + } + else +#endif /* LWIP_IPV6 */ + if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) { + /* local_ip doesn't match, drop the packet */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = ipX_2_ip(&(pcb->local_ip)); + } + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + chklen = UDP_HLEN; + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + udphdr->chksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDPLITE, + q->tot_len, chklen, ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } +#endif /* CHECKSUM_GEN_UDP */ + + ip_proto = IP_PROTO_UDPLITE; + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + /* Checksum is mandatory over IPv6. */ + if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, + q->tot_len, UDP_HLEN, ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, q->tot_len, + ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } +#endif /* CHECKSUM_GEN_UDP */ + ip_proto = IP_PROTO_UDP; + } + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ipX_output_if(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* TODO: must this be increased even if error occured? */ + snmp_inc_udpoutdatagrams(); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE, ip_2_ipX(ipaddr)); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + /* pcb may occur at most once in active list */ + LWIP_ASSERT("rebind == 0", rebind == 0); + /* pcb already in list, just rebind */ + rebind = 1; + } + + /* By default, we don't allow to bind to a port that any other udp + PCB is alread bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + else if (!ip_get_option(pcb, SOF_REUSEADDR) && + !ip_get_option(ipcb, SOF_REUSEADDR)) { +#else /* SO_REUSE */ + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + else { +#endif /* SO_REUSE */ + if ((ipcb->local_port == port) && IP_PCB_IPVER_EQ(pcb, ipcb) && + /* IP address matches, or one is IP_ADDR_ANY? */ + (ipX_addr_isany(PCB_ISIPV6(ipcb), &(ipcb->local_ip)) || + ipX_addr_isany(PCB_ISIPV6(ipcb), ip_2_ipX(ipaddr)) || + ipX_addr_cmp(PCB_ISIPV6(ipcb), &(ipcb->local_ip), ip_2_ipX(ipaddr)))) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + + ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr); + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } + pcb->local_port = port; + snmp_insert_udpidx_tree(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); + return ERR_OK; +} + +/** + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; +/** TODO: this functionality belongs in upper layers */ +#ifdef LWIP_UDP_TODO +#if LWIP_IPV6 + if (!PCB_ISIPV6(pcb)) +#endif /* LWIP_IPV6 */ + { + /* Nail down local IP for netconn_addr()/getsockname() */ + if (ip_addr_isany(ipX_2_ip(&pcb->local_ip)) && !ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) { + struct netif *netif; + + if ((netif = ip_route(ipX_2_ip(&pcb->remote_ip))) == NULL) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", + ip4_addr_get_u32(ipX_2_ip(&pcb->remote_ip)))); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } + /** TODO: this will bind the udp pcb locally, to the interface which + is used to route output packets to the remote address. However, we + might want to accept incoming packets on any interface! */ + ipX_addr_copy(0, pcb->local_ip, netif->ip_addr); + } else if (ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) { + ipX_addr_set_any(0, &pcb->local_ip); + } + } +#endif + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ + ipX_addr_set_any(PCB_ISIPV6(pcb), &pcb->remote_ip); + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for wich to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv.ip4 = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + snmp_delete_udpidx_tree(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; + } + return pcb; +} + +#if LWIP_IPV6 +/** + * Create a UDP PCB for IPv6. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new_ip6(void) +{ + struct udp_pcb *pcb; + pcb = udp_new(); + ip_set_v6(pcb, 1); + return pcb; +} +#endif /* LWIP_IPV6 */ + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(udphdr->src), ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + ntohs(udphdr->len), ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/Shared/lwip/src/include/ipv4/lwip/autoip.h b/Shared/lwip/src/include/ipv4/lwip/autoip.h new file mode 100644 index 0000000..e62b72e --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/autoip.h @@ -0,0 +1,118 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef __LWIP_AUTOIP_H__ +#define __LWIP_AUTOIP_H__ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +#define autoip_init() /* Compatibility define, no init needed. */ + +/** Set a struct autoip allocated by the application to work with */ +void autoip_set_struct(struct netif *netif, struct autoip *autoip); + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_AUTOIP */ + +#endif /* __LWIP_AUTOIP_H__ */ diff --git a/Shared/lwip/src/include/ipv4/lwip/icmp.h b/Shared/lwip/src/include/ipv4/lwip/icmp.h new file mode 100644 index 0000000..fa893b6 --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/icmp.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#if LWIP_IPV6 && LWIP_ICMP6 +#include "lwip/icmp6.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is splitted to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_ICMP */ + +#if (LWIP_IPV6 && LWIP_ICMP6) +#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ + icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ + icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) +#elif LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) +#else /* (LWIP_IPV6 && LWIP_ICMP6) || LWIP_ICMP*/ +#define icmp_port_unreach(isipv6, pbuf) +#endif /* (LWIP_IPV6 && LWIP_ICMP6) || LWIP_ICMP*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ICMP_H__ */ diff --git a/Shared/lwip/src/include/ipv4/lwip/igmp.h b/Shared/lwip/src/include/ipv4/lwip/igmp.h new file mode 100644 index 0000000..8aabac2 --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/igmp.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef __LWIP_IGMP_H__ +#define __LWIP_IGMP_H__ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions, these are passed to a netif's + * igmp_mac_filter callback function. */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest); +err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +void igmp_tmr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* __LWIP_IGMP_H__ */ diff --git a/Shared/lwip/src/include/ipv4/lwip/inet.h b/Shared/lwip/src/include/ipv4/lwip/inet.h new file mode 100644 index 0000000..7bff49b --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/inet.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** For compatibility with BSD code */ +struct in_addr { + u32_t s_addr; +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr) +#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ diff --git a/Shared/lwip/src/include/ipv4/lwip/ip4.h b/Shared/lwip/src/include/ipv4/lwip/ip4.h new file mode 100644 index 0000000..04b5b8a --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/ip4.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP4_H__ +#define __LWIP_IP4_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FIELD(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FIELD(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* dont fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FIELD(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FIELD(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(ip_addr_p_t src); + PACK_STRUCT_FIELD(ip_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl)) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + + +#define ip_init() /* Compatibility define, no init needed. */ +struct netif *ip_route(ip_addr_t *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, + struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ + +#define ip_netif_get_local_ipX(netif) (((netif) != NULL) ? ip_2_ipX(&((netif)->ip_addr)) : NULL) + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/Shared/lwip/src/include/ipv4/lwip/ip4_addr.h b/Shared/lwip/src/include/ipv4/lwip/ip4_addr.h new file mode 100644 index 0000000..b05ae53 --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/ip4_addr.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP4_ADDR_H__ +#define __LWIP_IP4_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +struct ip_addr { + u32_t addr; +}; + +/* This is the packed version of ip_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +typedef struct ip_addr ip_addr_t; +typedef struct ip_addr_packed ip_addr_p_t; + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + * for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IP address given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) +#endif + +/** Copy IP address - faster than ip_addr_set: no NULL check */ +#define ip_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) + +#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) +u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif); + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \ + ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) +#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) +#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) +#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ipaddr_aton(const char *cp, ip_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ipaddr_ntoa(const ip_addr_t *addr); +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/Shared/lwip/src/include/ipv4/lwip/ip_frag.h b/Shared/lwip/src/include/ipv4/lwip/ip_frag.h new file mode 100644 index 0000000..47eca9f --- /dev/null +++ b/Shared/lwip/src/include/ipv4/lwip/ip_frag.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef __LWIP_IP_FRAG_H__ +#define __LWIP_IP_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef __LWIP_PBUF_CUSTOM_REF__ +#define __LWIP_PBUF_CUSTOM_REF__ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* __LWIP_PBUF_CUSTOM_REF__ */ +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_FRAG_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/dhcp6.h b/Shared/lwip/src/include/ipv6/lwip/dhcp6.h new file mode 100644 index 0000000..4b905c5 --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/dhcp6.h @@ -0,0 +1,58 @@ +/** + * @file + * + * IPv6 address autoconfiguration as per RFC 4862. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * IPv6 address autoconfiguration as per RFC 4862. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef __LWIP_IP6_DHCP6_H__ +#define __LWIP_IP6_DHCP6_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + + +struct dhcp6 +{ + /*TODO: implement DHCP6*/ +}; + +#endif /* LWIP_IPV6_DHCP6 */ + +#endif /* __LWIP_IP6_DHCP6_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/ethip6.h b/Shared/lwip/src/include/ipv6/lwip/ethip6.h new file mode 100644 index 0000000..e7f412b --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/ethip6.h @@ -0,0 +1,68 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef __LWIP_ETHIP6_H__ +#define __LWIP_ETHIP6_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +err_t ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ + +#endif /* __LWIP_ETHIP6_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/icmp6.h b/Shared/lwip/src/include/ipv6/lwip/icmp6.h new file mode 100644 index 0000000..74bfdbe --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/icmp6.h @@ -0,0 +1,152 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef __LWIP_ICMP6_H__ +#define __LWIP_ICMP6_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +enum icmp6_type { + ICMP6_TYPE_DUR = 1, /* Destination unreachable */ + ICMP6_TYPE_PTB = 2, /* Packet too big */ + ICMP6_TYPE_TE = 3, /* Time exceeded */ + ICMP6_TYPE_PP = 4, /* Parameter problem */ + ICMP6_TYPE_PE1 = 100, /* Private experimentation */ + ICMP6_TYPE_PE2 = 101, /* Private experimentation */ + ICMP6_TYPE_RSV_ERR = 127, /* Reserved for expansion of error messages */ + + ICMP6_TYPE_EREQ = 128, /* Echo request */ + ICMP6_TYPE_EREP = 129, /* Echo reply */ + ICMP6_TYPE_MLQ = 130, /* Multicast listener query */ + ICMP6_TYPE_MLR = 131, /* Multicast listener report */ + ICMP6_TYPE_MLD = 132, /* Multicast listener done */ + ICMP6_TYPE_RS = 133, /* Router solicitation */ + ICMP6_TYPE_RA = 134, /* Router advertisement */ + ICMP6_TYPE_NS = 135, /* Neighbor solicitation */ + ICMP6_TYPE_NA = 136, /* Neighbor advertisement */ + ICMP6_TYPE_RD = 137, /* Redirect */ + ICMP6_TYPE_MRA = 151, /* Multicast router advertisement */ + ICMP6_TYPE_MRS = 152, /* Multicast router solicitation */ + ICMP6_TYPE_MRT = 153, /* Multicast router termination */ + ICMP6_TYPE_PE3 = 200, /* Private experimentation */ + ICMP6_TYPE_PE4 = 201, /* Private experimentation */ + ICMP6_TYPE_RSV_INF = 255 /* Reserved for expansion of informational messages */ +}; + +enum icmp6_dur_code { + ICMP6_DUR_NO_ROUTE = 0, /* No route to destination */ + ICMP6_DUR_PROHIBITED = 1, /* Communication with destination administratively prohibited */ + ICMP6_DUR_SCOPE = 2, /* Beyond scope of source address */ + ICMP6_DUR_ADDRESS = 3, /* Address unreachable */ + ICMP6_DUR_PORT = 4, /* Port unreachable */ + ICMP6_DUR_POLICY = 5, /* Source address failed ingress/egress policy */ + ICMP6_DUR_REJECT_ROUTE = 6 /* Reject route to destination */ +}; + +enum icmp6_te_code { + ICMP6_TE_HL = 0, /* Hop limit exceeded in transit */ + ICMP6_TE_FRAG = 1 /* Fragment reassembly time exceeded */ +}; + +enum icmp6_pp_code { + ICMP6_PP_FIELD = 0, /* Erroneous header field encountered */ + ICMP6_PP_HEADER = 1, /* Unrecognized next header type encountered */ + ICMP6_PP_OPTION = 2 /* Unrecognized IPv6 option encountered */ +}; + +/** This is the standard ICMP6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t data); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** This is the ICMP6 header adapted for echo req/resp. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_echo_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +void icmp6_input(struct pbuf *p, struct netif *inp); +void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); +void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); +void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); +void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* __LWIP_ICMP6_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/inet6.h b/Shared/lwip/src/include/ipv6/lwip/inet6.h new file mode 100644 index 0000000..dbf98df --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/inet6.h @@ -0,0 +1,92 @@ +/** + * @file + * + * INET v6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef __LWIP_INET6_H__ +#define __LWIP_INET6_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** For compatibility with BSD code */ +struct in6_addr { + union { + u8_t u8_addr[16]; + u32_t u32_addr[4]; + } un; +#define s6_addr un.u32_addr +}; + +#define IN6ADDR_ANY_INIT {0,0,0,0} +#define IN6ADDR_LOOPBACK_INIT {0,0,0,PP_HTONL(1)} + + +#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ + (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ + (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ + (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} +#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ + (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ + (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ + (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} +/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ +#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) + +/* directly map this to the lwip internal functions */ +#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet6_ntoa(addr) ip6addr_ntoa((ip6_addr_t*)&(addr)) +#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((ip6_addr_t*)&(addr), buf, buflen) + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* __LWIP_INET6_H__ */ + diff --git a/Shared/lwip/src/include/ipv6/lwip/ip6.h b/Shared/lwip/src/include/ipv6/lwip/ip6.h new file mode 100644 index 0000000..b199c95 --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/ip6.h @@ -0,0 +1,197 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef __LWIP_IP6_H__ +#define __LWIP_IP6_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip.h" +#include "lwip/ip6_addr.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP6_HLEN 40 + +#define IP6_NEXTH_HOPBYHOP 0 +#define IP6_NEXTH_TCP 6 +#define IP6_NEXTH_UDP 17 +#define IP6_NEXTH_ENCAPS 41 +#define IP6_NEXTH_ROUTING 43 +#define IP6_NEXTH_FRAGMENT 44 +#define IP6_NEXTH_ICMP6 58 +#define IP6_NEXTH_NONE 59 +#define IP6_NEXTH_DESTOPTS 60 +#define IP6_NEXTH_UDPLITE 136 + + +/* The IPv6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hdr { + /* version / traffic class / flow label */ + PACK_STRUCT_FIELD(u32_t _v_tc_fl); + /* payload length */ + PACK_STRUCT_FIELD(u16_t _plen); + /* next header */ + PACK_STRUCT_FIELD(u8_t _nexth); + /* hop limit */ + PACK_STRUCT_FIELD(u8_t _hoplim); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(ip6_addr_p_t src); + PACK_STRUCT_FIELD(ip6_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Hop-by-hop router alert option. */ +#define IP6_HBH_HLEN 8 +#define IP6_PAD1_OPTION 0 +#define IP6_PADN_ALERT_OPTION 1 +#define IP6_ROUTER_ALERT_OPTION 5 +#define IP6_ROUTER_ALERT_VALUE_MLD 0 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hbh_hdr { + /* next header */ + PACK_STRUCT_FIELD(u8_t _nexth); + /* header length */ + PACK_STRUCT_FIELD(u8_t _hlen); + /* router alert option type */ + PACK_STRUCT_FIELD(u8_t _ra_opt_type); + /* router alert option data len */ + PACK_STRUCT_FIELD(u8_t _ra_opt_dlen); + /* router alert option data */ + PACK_STRUCT_FIELD(u16_t _ra_opt_data); + /* PadN option type */ + PACK_STRUCT_FIELD(u8_t _padn_opt_type); + /* PadN option data len */ + PACK_STRUCT_FIELD(u8_t _padn_opt_dlen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Fragment header. */ +#define IP6_FRAG_HLEN 8 +#define IP6_FRAG_OFFSET_MASK 0xfff8 +#define IP6_FRAG_MORE_FLAG 0x0001 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_frag_hdr { + /* next header */ + PACK_STRUCT_FIELD(u8_t _nexth); + /* reserved */ + PACK_STRUCT_FIELD(u8_t reserved); + /* fragment offset */ + PACK_STRUCT_FIELD(u16_t _fragment_offset); + /* fragmented packet identification */ + PACK_STRUCT_FIELD(u32_t _identification); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) +#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) +#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff) +#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen)) +#define IP6H_NEXTH(hdr) ((hdr)->_nexth) +#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) +#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) + +#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl(((v) << 28) | ((tc) << 20) | (fl))) +#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen) +#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) +#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) + + +#define ip6_init() /* TODO should we init current addresses and header pointer? */ +struct netif *ip6_route(struct ip6_addr *src, struct ip6_addr *dest); +ip6_addr_t *ip6_select_source_address(struct netif *netif, ip6_addr_t * dest); +err_t ip6_input(struct pbuf *p, struct netif *inp); +err_t ip6_output(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, + u8_t hl, u8_t tc, u8_t nexth); +err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if LWIP_IPV6_MLD +err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); +#endif /* LWIP_IPV6_MLD */ + +#define ip6_netif_get_local_ipX(netif, dest) (((netif) != NULL) ? \ + ip6_2_ipX(ip6_select_source_address(netif, dest)) : NULL) + +#if IP6_DEBUG +void ip6_debug_print(struct pbuf *p); +#else +#define ip6_debug_print(p) +#endif /* IP6_DEBUG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* __LWIP_IP6_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/ip6_addr.h b/Shared/lwip/src/include/ipv6/lwip/ip6_addr.h new file mode 100644 index 0000000..89b5b81 --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/ip6_addr.h @@ -0,0 +1,286 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Structs and macros for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef __LWIP_IP6_ADDR_H__ +#define __LWIP_IP6_ADDR_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* This is the aligned version of ip6_addr_t, + used as local variable, on the stack, etc. */ +struct ip6_addr { + u32_t addr[4]; +}; + +/* This is the packed version of ip6_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_addr_packed { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip6_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip6_addr_t as well as on ip6_addr_p_t. */ +typedef struct ip6_addr ip6_addr_t; +typedef struct ip6_addr_packed ip6_addr_p_t; + + +/** IP6_ADDR_ANY can be used as a fixed IPv6 address + * for the wildcard + */ +extern const ip6_addr_t ip6_addr_any; +#define IP6_ADDR_ANY ((ip6_addr_t *)&ip6_addr_any) + + + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IPv6 partial address given by byte-parts. */ +#define IP6_ADDR(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IPv6 partial address given by byte-parts. +Little-endian version, stored in network order (no htonl). */ +#define IP6_ADDR(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0])) & 0xffff) +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1])) & 0xffff) +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2])) & 0xffff) +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3])) & 0xffff) + +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) + +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) + +/** Set address to ipv6 'any' (no need for htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +/** Set address to ipv6 loopback address */ +#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) +/** Safely copy one IPv6 address to another and change byte order + * from host- to network-order. */ +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0) + + + +/** + * Determine if two IPv6 address are on the same network. + * + * @arg addr1 IPv6 address 1 + * @arg addr2 IPv6 address 2 + * @return !0 if the network identifiers of both address match + */ +#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1])) + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) + +#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL) + +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || \ + (((ip6addr)->addr[0] == 0) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == 0) && \ + ((ip6addr)->addr[3] == 0))) + + +#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) + +#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) + +#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) + +#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) + +#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) +#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) +#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) +#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) +#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define IP6_MULTICAST_SCOPE_RESERVED 0x0 +#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 +#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 +#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 +#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 +#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 +#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 +#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 +#define IP6_MULTICAST_SCOPE_GLOBAL 0xe +#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf +#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff010000UL)) +#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff020000UL)) +#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff040000UL)) +#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff050000UL)) +#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff080000UL)) +#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff0e0000UL)) + +/* TODO define get/set for well-know multicast addresses, e.g. ff02::1 */ +#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) +#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) + +#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) +#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) + +#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) + +#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ + (ip6addr)->addr[3] = htonl(0xff000000UL | (htonl(if_id) & 0x00ffffffUL));}while(0) + +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + ((ip6addr)->addr[3] == htonl(0xff000000UL | (htonl((sn_addr)->addr[3]) & 0x00ffffffUL)))) + +/* IPv6 address states. */ +#define IP6_ADDR_INVALID 0x00 +#define IP6_ADDR_TENTATIVE 0x08 +#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ +#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ +#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ +#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ +#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ +#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ +#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ +#define IP6_ADDR_VALID 0x10 +#define IP6_ADDR_PREFERRED 0x30 +#define IP6_ADDR_DEPRECATED 0x50 + +#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) +#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) +#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ +#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) +#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) + +#define ip6_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F, \ + ipaddr != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) + +int ip6addr_aton(const char *cp, ip6_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip6addr_ntoa(const ip6_addr_t *addr); +char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); + + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* __LWIP_IP6_ADDR_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/ip6_frag.h b/Shared/lwip/src/include/ipv6/lwip/ip6_frag.h new file mode 100644 index 0000000..75898b8 --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/ip6_frag.h @@ -0,0 +1,102 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef __LWIP_IP6_FRAG_H__ +#define __LWIP_IP6_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + +/* The IPv6 reassembly timer interval in milliseconds. */ +#define IP6_REASS_TMR_INTERVAL 1000 + +/* IPv6 reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip6_reassdata { + struct ip6_reassdata *next; + struct pbuf *p; + struct ip6_hdr * iphdr; + u32_t identification; + u16_t datagram_len; + u8_t nexth; + u8_t timer; +}; + +#define ip6_reass_init() /* Compatibility define */ +void ip6_reass_tmr(void); +struct pbuf * ip6_reass(struct pbuf *p); + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ + +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef __LWIP_PBUF_CUSTOM_REF__ +#define __LWIP_PBUF_CUSTOM_REF__ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* __LWIP_PBUF_CUSTOM_REF__ */ + +err_t ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest); + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP6_FRAG_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/mld6.h b/Shared/lwip/src/include/ipv6/lwip/mld6.h new file mode 100644 index 0000000..abd86e5 --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/mld6.h @@ -0,0 +1,118 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef __LWIP_MLD6_H__ +#define __LWIP_MLD6_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct mld_group { + /** next link */ + struct mld_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip6_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/** Multicast listener report/query/done message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mld_header { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t max_resp_delay); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(ip6_addr_p_t multicast_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ + +/* MAC Filter Actions, these are passed to a netif's + * mld_mac_filter callback function. */ +#define MLD6_DEL_MAC_FILTER 0 +#define MLD6_ADD_MAC_FILTER 1 + + +#define mld6_init() /* TODO should we init tables? */ +err_t mld6_stop(struct netif *netif); +void mld6_report_groups(struct netif *netif); +void mld6_tmr(void); +struct mld_group *mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr); +void mld6_input(struct pbuf *p, struct netif *inp); +err_t mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr); +err_t mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ + +#endif /* __LWIP_MLD6_H__ */ diff --git a/Shared/lwip/src/include/ipv6/lwip/nd6.h b/Shared/lwip/src/include/ipv6/lwip/nd6.h new file mode 100644 index 0000000..28636e8 --- /dev/null +++ b/Shared/lwip/src/include/ipv6/lwip/nd6.h @@ -0,0 +1,369 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef __LWIP_ND6_H__ +#define __LWIP_ND6_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct for tables. */ +struct nd6_neighbor_cache_entry { + ip6_addr_t next_hop_address; + struct netif * netif; + u8_t lladdr[NETIF_MAX_HWADDR_LEN]; + /*u32_t pmtu;*/ +#if LWIP_ND6_QUEUEING + /** Pointer to queue of pending outgoing packets on this entry. */ + struct nd6_q_entry *q; +#else /* LWIP_ND6_QUEUEING */ + /** Pointer to a single pending outgoing packet on this entry. */ + struct pbuf *q; +#endif /* LWIP_ND6_QUEUEING */ + u8_t state; + u8_t isrouter; + union { + u32_t reachable_time; + u32_t delay_time; + u32_t probes_sent; + u32_t stale_time; + } counter; +}; + +struct nd6_destination_cache_entry { + ip6_addr_t destination_addr; + ip6_addr_t next_hop_addr; + u32_t pmtu; + u32_t age; +}; + +struct nd6_prefix_list_entry { + ip6_addr_t prefix; + struct netif * netif; + u32_t invalidation_timer; +#if LWIP_IPV6_AUTOCONFIG + u8_t flags; +#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 +#endif /* LWIP_IPV6_AUTOCONFIG */ +}; + +struct nd6_router_list_entry { + struct nd6_neighbor_cache_entry * neighbor_entry; + u32_t invalidation_timer; + u8_t flags; +}; + + +enum nd6_neighbor_cache_entry_state { + ND6_NO_ENTRY = 0, + ND6_INCOMPLETE, + ND6_REACHABLE, + ND6_STALE, + ND6_DELAY, + ND6_PROBE +}; + +#if LWIP_ND6_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct nd6_q_entry { + struct nd6_q_entry *next; + struct pbuf *p; +}; +#endif /* LWIP_ND6_QUEUEING */ + +/** Neighbor solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ns_header { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FIELD(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Neighbor advertisement message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct na_header { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u8_t flags); + PACK_STRUCT_FIELD(u8_t reserved[3]); + PACK_STRUCT_FIELD(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define ND6_FLAG_ROUTER (0x80) +#define ND6_FLAG_SOLICITED (0x40) +#define ND6_FLAG_OVERRIDE (0x20) + +/** Router solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rs_header { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Router advertisement message header. */ +#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) +#define ND6_RA_FLAG_OTHER_STATEFUL_CONFIG (0x40) +#define ND6_RA_FLAG_HOME_AGENT (0x20) +#define ND6_RA_PREFERENCE_MASK (0x18) +#define ND6_RA_PREFERENCE_HIGH (0x08) +#define ND6_RA_PREFERENCE_MEDIUM (0x00) +#define ND6_RA_PREFERENCE_LOW (0x18) +#define ND6_RA_PREFERENCE_DISABLED (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ra_header { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u8_t current_hop_limit); + PACK_STRUCT_FIELD(u8_t flags); + PACK_STRUCT_FIELD(u16_t router_lifetime); + PACK_STRUCT_FIELD(u32_t reachable_time); + PACK_STRUCT_FIELD(u32_t retrans_timer); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirect message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirect_header { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FIELD(ip6_addr_p_t target_address); + PACK_STRUCT_FIELD(ip6_addr_p_t destination_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Link-layer address option. */ +#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) +#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct lladdr_option { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t length); + PACK_STRUCT_FIELD(u8_t addr[NETIF_MAX_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Prefix information option. */ +#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) +#define ND6_PREFIX_FLAG_ON_LINK (0x80) +#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) +#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) +#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct prefix_option { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t length); + PACK_STRUCT_FIELD(u8_t prefix_length); + PACK_STRUCT_FIELD(u8_t flags); + PACK_STRUCT_FIELD(u32_t valid_lifetime); + PACK_STRUCT_FIELD(u32_t preferred_lifetime); + PACK_STRUCT_FIELD(u8_t reserved2[3]); + PACK_STRUCT_FIELD(u8_t site_prefix_length); + PACK_STRUCT_FIELD(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirected header option. */ +#define ND6_OPTION_TYPE_REDIR_HDR (0x04) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirected_header_option { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t length); + PACK_STRUCT_FIELD(u8_t reserved[6]); + /* Portion of redirected packet follows. */ + /* PACK_STRUCT_FIELD(u8_t redirected[8]); */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** MTU option. */ +#define ND6_OPTION_TYPE_MTU (0x05) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mtu_option { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t mtu); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Route information option. */ +#define ND6_OPTION_TYPE_ROUTE_INFO (24) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct route_option { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t length); + PACK_STRUCT_FIELD(u8_t prefix_length); + PACK_STRUCT_FIELD(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); + PACK_STRUCT_FIELD(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* the possible states of an IP address */ +#define IP6_ADDRESS_STATE_INVALID (0) +#define IP6_ADDRESS_STATE_VALID (0x4) +#define IP6_ADDRESS_STATE_PREFERRED (0x5) /* includes valid */ +#define IP6_ADDRESS_STATE_DEPRECATED (0x6) /* includes valid */ +#define IP6_ADDRESS_STATE_TENTATIV (0x8) + +/** 1 second period */ +#define ND6_TMR_INTERVAL 1000 + +/* Router tables. */ +/* TODO make these static? and entries accessible through API? */ +extern struct nd6_neighbor_cache_entry neighbor_cache[]; +extern struct nd6_destination_cache_entry destination_cache[]; +extern struct nd6_prefix_list_entry prefix_list[]; +extern struct nd6_router_list_entry default_router_list[]; + +/* Default values, can be updated by a RA message. */ +extern u32_t reachable_time; +extern u32_t retrans_timer; + +#define nd6_init() /* TODO should we init tables? */ +void nd6_tmr(void); +void nd6_input(struct pbuf *p, struct netif *inp); +s8_t nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif); +s8_t nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif); +u16_t nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif); +err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p); +#if LWIP_ND6_TCP_REACHABILITY_HINTS +void nd6_reachability_hint(ip6_addr_t * ip6addr); +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* __LWIP_ND6_H__ */ diff --git a/Shared/lwip/src/include/lwip/api.h b/Shared/lwip/src/include/lwip/api.h new file mode 100644 index 0000000..ac58eeb --- /dev/null +++ b/Shared/lwip/src/include/lwip/api.h @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_H__ +#define __LWIP_API_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define NETCONN_FLAG_WRITE_DELAYED 0x01 +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define NETCONN_FLAG_NO_AUTO_RECVED 0x08 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 +#if LWIP_IPV6 +/** If this flag is set then only IPv6 communication is allowed on the + netconn. As per RFC#3493 this features defaults to OFF allowing + dual-stack usage by default. */ +#define NETCONN_FLAG_IPV6_V6ONLY 0x20 +#endif /* LWIP_IPV6 */ + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) ((t)&0xF0) +#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) +#if LWIP_IPV6 +#define NETCONN_TYPE_IPV6 0x08 +#define NETCONNTYPE_ISIPV6(t) ((t)&0x08) +#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF7) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF7) == NETCONN_UDPNOCHKSUM) +#else /* LWIP_IPV6 */ +#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) +#endif /* LWIP_IPV6 */ + +/** Protocol family and type of the netconn */ +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, +#if LWIP_IPV6 + NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, +#endif /* LWIP_IPV6 */ + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM = 0x22, +#if LWIP_IPV6 + NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, + NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, + NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, +#endif /* LWIP_IPV6 */ + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +#if LWIP_IPV6 + , + NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ +#endif /* LWIP_IPV6 */ +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Use to inform the callback function about changes */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; + /** sem that is used to synchroneously execute functions in the core context */ + sys_sem_t op_completed; + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_DECL_PROTECT(lev); \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ +} while(0); + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +void netconn_recved(struct netconn *conn, u32_t length); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr, + ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if LWIP_DNS +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + +#define netconn_bind_ip6(conn, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_bind(conn, ip6_2_ip(ip6addr), port) : ERR_VAL) +#define netconn_connect_ip6(conn, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_connect(conn, ip6_2_ip(ip6addr), port) : ERR_VAL) +#define netconn_sendto_ip6(conn, buf, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_sendto(conn, buf, ip6_2_ip(ip6addr), port) : ERR_VAL) +#if LWIP_IPV6_MLD +#define netconn_join_leave_group_ip6(conn, multiaddr, srcaddr, join_or_leave) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_join_leave_group(conn, ip6_2_ip(multiaddr), ip6_2_ip(srcaddr), join_or_leave) :\ + ERR_VAL) +#endif /* LWIP_IPV6_MLD*/ +#endif /* LWIP_IPV6 */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_set_noautorecved(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0) +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_H__ */ diff --git a/Shared/lwip/src/include/lwip/api_msg.h b/Shared/lwip/src/include/lwip/api_msg.h new file mode 100644 index 0000000..8268036 --- /dev/null +++ b/Shared/lwip/src/include/lwip/api_msg.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for lwip_netconn_do_send */ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { + u8_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { + ip_addr_t *ipaddr; + u16_t port; + } bc; + /** used for lwip_netconn_do_getaddr */ + struct { + ipX_addr_t *ipaddr; + u16_t *port; + u8_t local; + } ad; + /** used for lwip_netconn_do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for lwip_netconn_do_recv */ + struct { + u32_t len; + } r; + /** used for lwip_netconn_do_close (/shutdown) */ + struct { + u8_t shut; + } sd; +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) + /** used for lwip_netconn_do_join_leave_group */ + struct { + ipX_addr_t *multiaddr; + ipX_addr_t *netif_addr; + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +}; + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(struct api_msg_msg *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ + const char *name; + /** Rhe resolved address is stored here */ + ip_addr_t *addr; + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t *sem; + /** Errors are given back here */ + err_t *err; +}; +#endif /* LWIP_DNS */ + +void lwip_netconn_do_newconn ( struct api_msg_msg *msg); +void lwip_netconn_do_delconn ( struct api_msg_msg *msg); +void lwip_netconn_do_bind ( struct api_msg_msg *msg); +void lwip_netconn_do_connect ( struct api_msg_msg *msg); +void lwip_netconn_do_disconnect ( struct api_msg_msg *msg); +void lwip_netconn_do_listen ( struct api_msg_msg *msg); +void lwip_netconn_do_send ( struct api_msg_msg *msg); +void lwip_netconn_do_recv ( struct api_msg_msg *msg); +void lwip_netconn_do_write ( struct api_msg_msg *msg); +void lwip_netconn_do_getaddr ( struct api_msg_msg *msg); +void lwip_netconn_do_close ( struct api_msg_msg *msg); +void lwip_netconn_do_shutdown ( struct api_msg_msg *msg); +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +void lwip_netconn_do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +void lwip_netconn_do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/Shared/lwip/src/include/lwip/arch.h b/Shared/lwip/src/include/lwip/arch.h new file mode 100644 index 0000000..5adae9e --- /dev/null +++ b/Shared/lwip/src/include/lwip/arch.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ARCH_H__ +#define __LWIP_ARCH_H__ + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ARCH_H__ */ diff --git a/Shared/lwip/src/include/lwip/debug.h b/Shared/lwip/src/include/lwip/debug.h new file mode 100644 index 0000000..0fe0413 --- /dev/null +++ b/Shared/lwip/src/include/lwip/debug.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEBUG_H__ +#define __LWIP_DEBUG_H__ + +#include "lwip/arch.h" +#include "lwip/opt.h" + +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG(message); \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* __LWIP_DEBUG_H__ */ + diff --git a/Shared/lwip/src/include/lwip/def.h b/Shared/lwip/src/include/lwip/def.h new file mode 100644 index 0000000..73a1b56 --- /dev/null +++ b/Shared/lwip/src/include/lwip/def.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEF_H__ +#define __LWIP_DEF_H__ + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LWIP_MAKE_U16(a, b) ((a << 8) | b) +#else +#define LWIP_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifndef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if LWIP_PLATFORM_BYTESWAP +#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) +#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) +#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) +#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t lwip_htons(u16_t x); +u16_t lwip_ntohs(u16_t x); +u32_t lwip_htonl(u32_t x); +u32_t lwip_ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_DEF_H__ */ + diff --git a/Shared/lwip/src/include/lwip/dhcp.h b/Shared/lwip/src/include/lwip/dhcp.h new file mode 100644 index 0000000..32d9338 --- /dev/null +++ b/Shared/lwip/src/include/lwip/dhcp.h @@ -0,0 +1,242 @@ +/** @file + */ + +#ifndef __LWIP_DHCP_H__ +#define __LWIP_DHCP_H__ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_LEN 128U + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** our connection to the DHCP server */ + struct udp_pcb *pcb; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */ + ip_addr_t offered_ip_addr; + ip_addr_t offered_sn_mask; + ip_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ + /* @todo: LWIP_DHCP_BOOTP_FILE configuration option? + integrate with possible TFTP-client for booting? */ +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FIELD(u8_t op); + PACK_STRUCT_FIELD(u8_t htype); + PACK_STRUCT_FIELD(u8_t hlen); + PACK_STRUCT_FIELD(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(ip_addr_p_t ciaddr); + PACK_STRUCT_FIELD(ip_addr_p_t yiaddr); + PACK_STRUCT_FIELD(ip_addr_p_t siaddr); + PACK_STRUCT_FIELD(ip_addr_p_t giaddr); + PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_OP_OFS 0 +#define DHCP_HTYPE_OFS 1 +#define DHCP_HLEN_OFS 2 +#define DHCP_HOPS_OFS 3 +#define DHCP_XID_OFS 4 +#define DHCP_SECS_OFS 8 +#define DHCP_FLAGS_OFS 10 +#define DHCP_CIADDR_OFS 12 +#define DHCP_YIADDR_OFS 16 +#define DHCP_SIADDR_OFS 20 +#define DHCP_GIADDR_OFS 24 +#define DHCP_CHADDR_OFS 28 +#define DHCP_SNAME_OFS 44 +#define DHCP_FILE_OFS 108 +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS DHCP_MSG_LEN +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_OFF 0 +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +#define DHCP_INFORMING 7 +#define DHCP_CHECKING 8 +#define DHCP_PERMANENT 9 +#define DHCP_BOUND 10 +/** not yet implemented #define DHCP_RELEASING 11 */ +#define DHCP_BACKING_OFF 12 + +/** AUTOIP cooperatation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/** DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*__LWIP_DHCP_H__*/ diff --git a/Shared/lwip/src/include/lwip/dns.h b/Shared/lwip/src/include/lwip/dns.h new file mode 100644 index 0000000..6c7d9b0 --- /dev/null +++ b/Shared/lwip/src/include/lwip/dns.h @@ -0,0 +1,124 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* The size used for the next line is rather a hack, but it prevents including socket.h in all files + that include memp.h, and that would possibly break portability (since socket.h defines some types + and constants possibly already define by the OS). + Calculation rule: + sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */ +#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1) + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, ip_addr_t *dnsserver); +ip_addr_t dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/Shared/lwip/src/include/lwip/err.h b/Shared/lwip/src/include/lwip/err.h new file mode 100644 index 0000000..ac90772 --- /dev/null +++ b/Shared/lwip/src/include/lwip/err.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ERR_H__ +#define __LWIP_ERR_H__ + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ + +#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN) + +#define ERR_ABRT -10 /* Connection aborted. */ +#define ERR_RST -11 /* Connection reset. */ +#define ERR_CLSD -12 /* Connection closed. */ +#define ERR_CONN -13 /* Not connected. */ + +#define ERR_ARG -14 /* Illegal argument. */ + +#define ERR_IF -15 /* Low-level netif error */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/Shared/lwip/src/include/lwip/inet_chksum.h b/Shared/lwip/src/include/lwip/inet_chksum.h new file mode 100644 index 0000000..e168788 --- /dev/null +++ b/Shared/lwip/src/include/lwip/inet_chksum.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_CHKSUM_H__ +#define __LWIP_INET_CHKSUM_H__ + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +#ifndef LWIP_CHKSUM_COPY +#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +#ifndef LWIP_CHKSUM_COPY_ALGORITHM +#define LWIP_CHKSUM_COPY_ALGORITHM 1 +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +#endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +#define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip_addr_t *src, ip_addr_t *dest); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, + u16_t proto_len, u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#if LWIP_IPV6 +u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip6_addr_t *src, ip6_addr_t *dest); +u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest); + +#define ipX_chksum_pseudo(isipv6, p, proto, proto_len, src, dest) \ + ((isipv6) ? \ + ip6_chksum_pseudo(p, proto, proto_len, ipX_2_ip6(src), ipX_2_ip6(dest)) :\ + inet_chksum_pseudo(p, proto, proto_len, ipX_2_ip(src), ipX_2_ip(dest))) +#define ipX_chksum_pseudo_partial(isipv6, p, proto, proto_len, chksum_len, src, dest) \ + ((isipv6) ? \ + ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ipX_2_ip6(src), ipX_2_ip6(dest)) :\ + inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ipX_2_ip(src), ipX_2_ip(dest))) + +#else /* LWIP_IPV6 */ + +#define ipX_chksum_pseudo(isipv6, p, proto, proto_len, src, dest) \ + inet_chksum_pseudo(p, proto, proto_len, src, dest) +#define ipX_chksum_pseudo_partial(isipv6, p, proto, proto_len, chksum_len, src, dest) \ + inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, src, dest) + +#endif /* LWIP_IPV6 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/Shared/lwip/src/include/lwip/init.h b/Shared/lwip/src/include/lwip/init.h new file mode 100644 index 0000000..4e2e285 --- /dev/null +++ b/Shared/lwip/src/include/lwip/init.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INIT_H__ +#define __LWIP_INIT_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 4U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 1U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 0U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INIT_H__ */ diff --git a/Shared/lwip/src/include/lwip/ip.h b/Shared/lwip/src/include/lwip/ip.h new file mode 100644 index 0000000..a0cd1d4 --- /dev/null +++ b/Shared/lwip/src/include/lwip/ip.h @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +#if LWIP_IPV6 +#define IP_PCB_ISIPV6_MEMBER u8_t isipv6; +#define IP_PCB_IPVER_EQ(pcb1, pcb2) ((pcb1)->isipv6 == (pcb2)->isipv6) +#define IP_PCB_IPVER_INPUT_MATCH(pcb) (ip_current_is_v6() ? \ + ((pcb)->isipv6 != 0) : \ + ((pcb)->isipv6 == 0)) +#define PCB_ISIPV6(pcb) ((pcb)->isipv6) +#else +#define IP_PCB_ISIPV6_MEMBER +#define IP_PCB_IPVER_EQ(pcb1, pcb2) 1 +#define IP_PCB_IPVER_INPUT_MATCH(pcb) 1 +#define PCB_ISIPV6(pcb) 0 +#endif /* LWIP_IPV6 */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + IP_PCB_ISIPV6_MEMBER \ + /* ip addresses in network byte order */ \ + ipX_addr_t local_ip; \ + ipX_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +/*#define SOF_DEBUG 0x01U Unimplemented: turn on debugging info recording */ +#define SOF_ACCEPTCONN 0x02U /* socket has had listen() */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +/*#define SOF_DONTROUTE 0x10U Unimplemented: just use interface addresses */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +/*#define SOF_USELOOPBACK 0x40U Unimplemented: bypass hardware when possible */ +#define SOF_LINGER 0x80U /* linger on close if data present */ +/*#define SOF_OOBINLINE 0x0100U Unimplemented: leave received OOB data in line */ +/*#define SOF_REUSEPORT 0x0200U Unimplemented: allow local address & port reuse */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/) + +/* Global variables of this module, kept in a struct for efficient access using base+index. */ +struct ip_globals +{ + /** The interface that provided the packet for the current callback invocation. */ + struct netif *current_netif; + /** Header of the input packet currently being processed. */ + const struct ip_hdr *current_ip4_header; +#if LWIP_IPV6 + /** Header of the input IPv6 packet currently being processed. */ + const struct ip6_hdr *current_ip6_header; +#endif /* LWIP_IPV6 */ + /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ + u16_t current_ip_header_tot_len; + /** Source IP address of current_header */ + ipX_addr_t current_iphdr_src; + /** Destination IP address of current_header */ + ipX_addr_t current_iphdr_dest; +}; +extern struct ip_globals ip_data; + + +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (ip_data.current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (ip_data.current_ip4_header) +/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ +#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) +/** Source IP address of current_header */ +#define ipX_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP address of current_header */ +#define ipX_current_dest_addr() (&ip_data.current_iphdr_dest) + +#if LWIP_IPV6 +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() (ip_data.current_ip6_header) +/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ +#define ip_current_is_v6() (ip6_current_header() != NULL) +/** Source IPv6 address of current_header */ +#define ip6_current_src_addr() (ipX_2_ip6(&ip_data.current_iphdr_src)) +/** Destination IPv6 address of current_header */ +#define ip6_current_dest_addr() (ipX_2_ip6(&ip_data.current_iphdr_dest)) +/** Get the transport layer protocol */ +#define ip_current_header_proto() (ip_current_is_v6() ? \ + IP6H_NEXTH(ip6_current_header()) :\ + IPH_PROTO(ip_current_header())) +/** Get the transport layer header */ +#define ipX_next_header_ptr() ((void*)((ip_current_is_v6() ? \ + (u8_t*)ip6_current_header() : (u8_t*)ip_current_header()) + ip_current_header_tot_len())) + +/** Set an IP_PCB to IPv6 (IPv4 is the default) */ +#define ip_set_v6(pcb, val) do{if(pcb != NULL) { pcb->isipv6 = val; }}while(0) + +/** Source IP4 address of current_header */ +#define ip_current_src_addr() (ipX_2_ip(&ip_data.current_iphdr_src)) +/** Destination IP4 address of current_header */ +#define ip_current_dest_addr() (ipX_2_ip(&ip_data.current_iphdr_dest)) + +#else /* LWIP_IPV6 */ + +/** Always returns FALSE when only supporting IPv4 */ +#define ip_current_is_v6() 0 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IPH_PROTO(ip_current_header()) +/** Get the transport layer header */ +#define ipX_next_header_ptr() ((void*)((u8_t*)ip_current_header() + ip_current_header_tot_len())) +/** Source IP4 address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP4 address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +#endif /* LWIP_IPV6 */ + +/** Union source address of current_header */ +#define ipX_current_src_addr() (&ip_data.current_iphdr_src) +/** Union destination address of current_header */ +#define ipX_current_dest_addr() (&ip_data.current_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if LWIP_IPV6 +#define ipX_output(isipv6, p, src, dest, ttl, tos, proto) \ + ((isipv6) ? \ + ip6_output(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto) : \ + ip_output(p, ipX_2_ip(src), ipX_2_ip(dest), ttl, tos, proto)) +#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ((isipv6) ? \ + ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip_output_if(p, (src), (dest), ttl, tos, proto, netif)) +#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \ + ((isipv6) ? \ + ip6_output_hinted(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto, addr_hint) : \ + ip_output_hinted(p, ipX_2_ip(src), ipX_2_ip(dest), ttl, tos, proto, addr_hint)) +#define ipX_route(isipv6, src, dest) \ + ((isipv6) ? \ + ip6_route(ipX_2_ip6(src), ipX_2_ip6(dest)) : \ + ip_route(ipX_2_ip(dest))) +#define ipX_netif_get_local_ipX(isipv6, netif, dest) \ + ((isipv6) ? \ + ip6_netif_get_local_ipX(netif, ipX_2_ip6(dest)) : \ + ip_netif_get_local_ipX(netif)) +#define ipX_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip_debug_print(p)) +#else /* LWIP_IPV6 */ +#define ipX_output(isipv6, p, src, dest, ttl, tos, proto) \ + ip_output(p, src, dest, ttl, tos, proto) +#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ip_output_if(p, src, dest, ttl, tos, proto, netif) +#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \ + ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ipX_route(isipv6, src, dest) \ + ip_route(ipX_2_ip(dest)) +#define ipX_netif_get_local_ipX(isipv6, netif, dest) \ + ip_netif_get_local_ipX(netif) +#define ipX_debug_print(is_ipv6, p) ip_debug_print(p) +#endif /* LWIP_IPV6 */ + +#define ipX_route_get_local_ipX(isipv6, src, dest, netif, ipXaddr) do { \ + (netif) = ipX_route(isipv6, src, dest); \ + (ipXaddr) = ipX_netif_get_local_ipX(isipv6, netif, dest); \ +}while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/Shared/lwip/src/include/lwip/ip_addr.h b/Shared/lwip/src/include/lwip/ip_addr.h new file mode 100644 index 0000000..7bd03cb --- /dev/null +++ b/Shared/lwip/src/include/lwip/ip_addr.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include "lwip/ip4_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_IPV6 +/* A union struct for both IP version's addresses. */ +typedef union { + ip_addr_t ip4; + ip6_addr_t ip6; +} ipX_addr_t; + +/** These functions only exist for type-safe conversion from ip_addr_t to + ip6_addr_t and back */ +#ifdef LWIP_ALLOW_STATIC_FN_IN_HEADER +static ip6_addr_t* ip_2_ip6(ip_addr_t *ipaddr) +{ return (ip6_addr_t*)ipaddr;} +static ip_addr_t* ip6_2_ip(ip6_addr_t *ip6addr) +{ return (ip_addr_t*)ip6addr; } +static ipX_addr_t* ip_2_ipX(ip_addr_t *ipaddr) +{ return (ipX_addr_t*)ipaddr; } +static ipX_addr_t* ip6_2_ipX(ip6_addr_t *ip6addr) +{ return (ipX_addr_t*)ip6addr; } +#else /* LWIP_ALLOW_STATIC_FN_IN_HEADER */ +#define ip_2_ip6(ipaddr) ((ip6_addr_t*)(ipaddr)) +#define ip6_2_ip(ip6addr) ((ip_addr_t*)(ip6addr)) +#define ip_2_ipX(ipaddr) ((ipX_addr_t*)ipaddr) +#define ip6_2_ipX(ip6addr) ((ipX_addr_t*)ip6addr) +#endif /* LWIP_ALLOW_STATIC_FN_IN_HEADER*/ +#define ipX_2_ip6(ip6addr) (&((ip6addr)->ip6)) +#define ipX_2_ip(ipaddr) (&((ipaddr)->ip4)) + +#define ipX_addr_copy(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_copy((dest).ip6, (src).ip6); }else{ \ + ip_addr_copy((dest).ip4, (src).ip4); }}while(0) +#define ipX_addr_set(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_set(ipX_2_ip6(dest), ipX_2_ip6(src)); }else{ \ + ip_addr_set(ipX_2_ip(dest), ipX_2_ip(src)); }}while(0) +#define ipX_addr_set_ipaddr(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_set(ipX_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip_addr_set(ipX_2_ip(dest), src); }}while(0) +#define ipX_addr_set_zero(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_zero(ipX_2_ip6(ipaddr)); }else{ \ + ip_addr_set_zero(ipX_2_ip(ipaddr)); }}while(0) +#define ipX_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_any(ipX_2_ip6(ipaddr)); }else{ \ + ip_addr_set_any(ipX_2_ip(ipaddr)); }}while(0) +#define ipX_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_loopback(ipX_2_ip6(ipaddr)); }else{ \ + ip_addr_set_loopback(ipX_2_ip(ipaddr)); }}while(0) +#define ipX_addr_set_hton(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_set_hton(ipX_2_ip6(ipaddr), (src)) ;}else{ \ + ip_addr_set_hton(ipX_2_ip(ipaddr), (src));}}while(0) +#define ipX_addr_cmp(is_ipv6, addr1, addr2) ((is_ipv6) ? \ + ip6_addr_cmp(ipX_2_ip6(addr1), ipX_2_ip6(addr2)) : \ + ip_addr_cmp(ipX_2_ip(addr1), ipX_2_ip(addr2))) +#define ipX_addr_isany(is_ipv6, ipaddr) ((is_ipv6) ? \ + ip6_addr_isany(ipX_2_ip6(ipaddr)) : \ + ip_addr_isany(ipX_2_ip(ipaddr))) +#define ipX_addr_ismulticast(is_ipv6, ipaddr) ((is_ipv6) ? \ + ip6_addr_ismulticast(ipX_2_ip6(ipaddr)) : \ + ip_addr_ismulticast(ipX_2_ip(ipaddr))) +#define ipX_addr_debug_print(is_ipv6, debug, ipaddr) do { if(is_ipv6) { \ + ip6_addr_debug_print(debug, ipX_2_ip6(ipaddr)); } else { \ + ip_addr_debug_print(debug, ipX_2_ip(ipaddr)); }}while(0) + +#else /* LWIP_IPV6 */ + +typedef ip_addr_t ipX_addr_t; +#define ipX_2_ip(ipaddr) (ipaddr) +#define ip_2_ipX(ipaddr) (ipaddr) + +#define ipX_addr_copy(is_ipv6, dest, src) ip_addr_copy(dest, src) +#define ipX_addr_set(is_ipv6, dest, src) ip_addr_set(dest, src) +#define ipX_addr_set_ipaddr(is_ipv6, dest, src) ip_addr_set(dest, src) +#define ipX_addr_set_zero(is_ipv6, ipaddr) ip_addr_set_zero(ipaddr) +#define ipX_addr_set_any(is_ipv6, ipaddr) ip_addr_set_any(ipaddr) +#define ipX_addr_set_loopback(is_ipv6, ipaddr) ip_addr_set_loopback(ipaddr) +#define ipX_addr_set_hton(is_ipv6, dest, src) ip_addr_set_hton(dest, src) +#define ipX_addr_cmp(is_ipv6, addr1, addr2) ip_addr_cmp(addr1, addr2) +#define ipX_addr_isany(is_ipv6, ipaddr) ip_addr_isany(ipaddr) +#define ipX_addr_ismulticast(is_ipv6, ipaddr) ip_addr_ismulticast(ipaddr) +#define ipX_addr_debug_print(is_ipv6, debug, ipaddr) ip_addr_debug_print(debug, ipaddr) + +#endif /* LWIP_IPV6 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/Shared/lwip/src/include/lwip/mem.h b/Shared/lwip/src/include/lwip/mem.h new file mode 100644 index 0000000..5bb906b --- /dev/null +++ b/Shared/lwip/src/include/lwip/mem.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_MEM_H__ +#define __LWIP_MEM_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif +/* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ +#ifndef mem_trim +#define mem_trim(mem, size) (mem) +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_trim is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_trim(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEM_H__ */ diff --git a/Shared/lwip/src/include/lwip/memp.h b/Shared/lwip/src/include/lwip/memp.h new file mode 100644 index 0000000..f0d0739 --- /dev/null +++ b/Shared/lwip/src/include/lwip/memp.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_MEMP_H__ +#define __LWIP_MEMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/memp_std.h" + MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_free(type, mem) mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEMP_H__ */ diff --git a/Shared/lwip/src/include/lwip/memp_std.h b/Shared/lwip/src/include/lwip/memp_std.h new file mode 100644 index 0000000..592a282 --- /dev/null +++ b/Shared/lwip/src/include/lwip/memp_std.h @@ -0,0 +1,135 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* IP_REASSEMBLY */ +#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || LWIP_IPV6_FRAG +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +#if LWIP_NETCONN +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS */ + +#if LWIP_SNMP +LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE") +LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE") +LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND") +LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE") +#endif /* LWIP_SNMP */ +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#if PPP_SUPPORT && PPPOE_SUPPORT +LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ + +#if LWIP_IPV6 && LWIP_ND6_QUEUEING +LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") +#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ + +#if LWIP_IPV6 && LWIP_IPV6_REASS +LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/Shared/lwip/src/include/lwip/netbuf.h b/Shared/lwip/src/include/lwip/netbuf.h new file mode 100644 index 0000000..d12fe27 --- /dev/null +++ b/Shared/lwip/src/include/lwip/netbuf.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +struct netbuf { + struct pbuf *p, *ptr; + ipX_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ipX_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, + struct netbuf *tail); + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (ipX_2_ip(&((buf)->addr))) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(ipX_2_ip(&((buf)->addr)), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (ipX_2_ip(&((buf)->toaddr))) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(ipX_2_ip(&((buf)->toaddr)), destaddr) +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#if LWIP_IPV6 +#define netbuf_fromaddr_ip6(buf) (ipX_2_ip6(&((buf)->addr))) +#define netbuf_set_fromaddr_ip6(buf, fromaddr) ip6_addr_set(ipX_2_ip6(&((buf)->addr)), fromaddr) +#define netbuf_destaddr_ip6(buf) (ipX_2_ip6(&((buf)->toaddr))) +#define netbuf_set_destaddr_ip6(buf, destaddr) ip6_addr_set(ipX_2_ip6(&((buf)->toaddr)), destaddr) +#endif /* LWIP_IPV6 */ + +#define netbuf_fromaddr_ipX(buf) (&((buf)->addr)) +#define netbuf_destaddr_ipX(buf) (&((buf)->toaddr)) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/Shared/lwip/src/include/lwip/netdb.h b/Shared/lwip/src/include/lwip/netdb.h new file mode 100644 index 0000000..7587e2f --- /dev/null +++ b/Shared/lwip/src/include/lwip/netdb.h @@ -0,0 +1,124 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIP_NETDB_H__ +#define __LWIP_NETDB_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessable error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* __LWIP_NETDB_H__ */ diff --git a/Shared/lwip/src/include/lwip/netif.h b/Shared/lwip/src/include/lwip/netif.h new file mode 100644 index 0000000..f977032 --- /dev/null +++ b/Shared/lwip/src/include/lwip/netif.h @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETIF_H__ +#define __LWIP_NETIF_H__ + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** must be the maximum of all used hardware address lengths + across all types of interfaces in use */ +#define NETIF_MAX_HWADDR_LEN 6U + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It is set by the startup code (for static IP configuration) or + * by dhcp/autoip when an address has been assigned. + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the netif is one end of a point-to-point connection. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** If set, the interface is configured using DHCP. + * Set by the DHCP code when starting or stopping DHCP. */ +#define NETIF_FLAG_DHCP 0x08U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x10U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x20U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x40U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x80U +/** Whether to pretend that we are every host for TCP packets. + * Set by netif_set_pretend_tcp. */ +#define NETIF_FLAG_PRETEND_TCP 0x100U + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr); +#if LWIP_IPV6 +/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'nd_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IPv6 address to which the packet shall be sent + */ +typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, + ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + ip_addr_t *group, u8_t action); +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** Function prototype for netif mld_mac_filter functions */ +typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, + ip6_addr_t *group, u8_t action); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; + +#if LWIP_IPV6 + /** Array of IPv6 addresses for this netif. */ + ip6_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; + /** The state of each IPv6 address (Tentative, Preferred, etc). + * @see ip6_addr.h */ + u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; +#endif /* LWIP_IPV6 */ + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_fn output; + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_IPV6 + /** This function is called by the IPv6 module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_ip6_fn output_ip6; +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif +#if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /** Number of Router Solicitation messages that remain to be sent. */ + u8_t rs_count; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_IPV6_DHCP6 + /** the DHCPv6 client state information for this netif */ + struct dhcp6 *dhcp6; +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) */ + u16_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if LWIP_SNMP + /** link type (from "snmp_ifType" enum from snmp.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + u32_t ifinoctets; + u32_t ifinucastpkts; + u32_t ifinnucastpkts; + u32_t ifindiscards; + u32_t ifoutoctets; + u32_t ifoutucastpkts; + u32_t ifoutnucastpkts; + u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP + /** This function could be called to add or delete an entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /** This function could be called to add or delete an entry in the IPv6 multicast + filter table of the ethernet MAC. */ + netif_mld_mac_filter_fn mld_mac_filter; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ + /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + (netif)->link_type = (type); \ + /* your link speed here (units: bits per second) */ \ + (netif)->link_speed = (speed); \ + (netif)->ts = 0; \ + (netif)->ifinoctets = 0; \ + (netif)->ifinucastpkts = 0; \ + (netif)->ifinnucastpkts = 0; \ + (netif)->ifindiscards = 0; \ + (netif)->ifoutoctets = 0; \ + (netif)->ifoutucastpkts = 0; \ + (netif)->ifoutnucastpkts = 0; \ + (netif)->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input); + +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw); +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(char *name); + +int netif_is_named (struct netif *netif, const char name[3]); + +void netif_set_default(struct netif *netif); + +void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, ip_addr_t *netmask); +void netif_set_gw(struct netif *netif, ip_addr_t *gw); +void netif_set_pretend_tcp(struct netif *netif, u8_t pretend); + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** Ask if an interface is up */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_IPV6 +#define netif_ip6_addr(netif, i) (&((netif)->ip6_addr[(i)])) +#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[(i)]) +#define netif_ip6_addr_set_state(netif, i, state) ((netif)->ip6_addr_state[(i)] = (state)) +s8_t netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr); +void netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit); +#endif /* LWIP_IPV6 */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETIF_H__ */ diff --git a/Shared/lwip/src/include/lwip/netifapi.h b/Shared/lwip/src/include/lwip/netifapi.h new file mode 100644 index 0000000..33318ef --- /dev/null +++ b/Shared/lwip/src/include/lwip/netifapi.h @@ -0,0 +1,108 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_NETIFAPI_H__ +#define __LWIP_NETIFAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + struct netif *netif; + union { + struct { + ip_addr_t *ipaddr; + ip_addr_t *netmask; + ip_addr_t *gw; + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + +struct netifapi_msg { + void (* function)(struct netifapi_msg_msg *msg); + struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input); + +err_t netifapi_netif_set_addr ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw ); + +err_t netifapi_netif_common ( struct netif *netif, + netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* __LWIP_NETIFAPI_H__ */ diff --git a/Shared/lwip/src/include/lwip/opt.h b/Shared/lwip/src/include/lwip/opt.h new file mode 100644 index 0000000..e51f8e5 --- /dev/null +++ b/Shared/lwip/src/include/lwip/opt.h @@ -0,0 +1,2417 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_OPT_H__ +#define __LWIP_OPT_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/** + * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of + * pending data in the network buffer. This is the way windows does it. It's + * the default for lwIP since it is smaller. + * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next + * pending datagram in bytes. This is the way linux does it. This code is only + * here for compatibility. + */ +#ifndef LWIP_FIONREAD_LINUXMODE +#define LWIP_FIONREAD_LINUXMODE 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +/** + * IP6_STATS==1: Enable IPv6 stats. + */ +#ifndef IP6_STATS +#define IP6_STATS (LWIP_IPV6) +#endif + +/** + * ICMP6_STATS==1: Enable ICMP for IPv6 stats. + */ +#ifndef ICMP6_STATS +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#endif + +/** + * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. + */ +#ifndef IP6_FRAG_STATS +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#endif + +/** + * MLD6_STATS==1: Enable MLD for IPv6 stats. + */ +#ifndef MLD6_STATS +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#endif + +/** + * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. + */ +#ifndef ND6_STATS +#define ND6_STATS (LWIP_IPV6) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define IP6_STATS 0 +#define ICMP6_STATS 0 +#define IP6_FRAG_STATS 0 +#define MLD6_STATS 0 +#define ND6_STATS 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#ifndef LWIP_IPV6 +#define LWIP_IPV6 0 +#endif + +/** + * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. + */ +#ifndef LWIP_IPV6_NUM_ADDRESSES +#define LWIP_IPV6_NUM_ADDRESSES 3 +#endif + +/** + * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs + */ +#ifndef LWIP_IPV6_FORWARD +#define LWIP_IPV6_FORWARD 0 +#endif + +/** + * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) + */ +#ifndef LWIP_ICMP6 +#define LWIP_ICMP6 (LWIP_IPV6) +#endif + +/** + * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in + * ICMPv6 error messages. + */ +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/** + * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages + */ +#ifndef LWIP_ICMP6_HL +#define LWIP_ICMP6_HL 255 +#endif + +/** + * LWIP_ICMP6_CHECKSUM_CHECK==1: verify checksum on ICMPv6 packets + */ +#ifndef LWIP_ICMP6_CHECKSUM_CHECK +#define LWIP_ICMP6_CHECKSUM_CHECK 1 +#endif + +/** + * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. + */ +#ifndef LWIP_IPV6_MLD +#define LWIP_IPV6_MLD (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined. + */ +#ifndef MEMP_NUM_MLD6_GROUP +#define MEMP_NUM_MLD6_GROUP 4 +#endif + +/** + * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. + */ +#ifndef LWIP_IPV6_FRAG +#define LWIP_IPV6_FRAG 0 +#endif + +/** + * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented + */ +#ifndef LWIP_IPV6_REASS +#define LWIP_IPV6_REASS (LWIP_IPV6) +#endif + +/** + * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address + * is being resolved. + */ +#ifndef LWIP_ND6_QUEUEING +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. + */ +#ifndef MEMP_NUM_ND6_QUEUE +#define MEMP_NUM_ND6_QUEUE 20 +#endif + +/** + * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache + */ +#ifndef LWIP_ND6_NUM_NEIGHBORS +#define LWIP_ND6_NUM_NEIGHBORS 10 +#endif + +/** + * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache + */ +#ifndef LWIP_ND6_NUM_DESTINATIONS +#define LWIP_ND6_NUM_DESTINATIONS 10 +#endif + +/** + * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache + */ +#ifndef LWIP_ND6_NUM_PREFIXES +#define LWIP_ND6_NUM_PREFIXES 5 +#endif + +/** + * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache + */ +#ifndef LWIP_ND6_NUM_ROUTERS +#define LWIP_ND6_NUM_ROUTERS 3 +#endif + +/** + * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send + * (neighbor solicit and router solicit) + */ +#ifndef LWIP_ND6_MAX_MULTICAST_SOLICIT +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#endif + +/** + * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages + * to send during neighbor reachability detection. + */ +#ifndef LWIP_ND6_MAX_UNICAST_SOLICIT +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#endif + +/** + * Unused: See ND RFC (time in milliseconds). + */ +#ifndef LWIP_ND6_MAX_ANYCAST_DELAY_TIME +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#endif + +/** + * Unused: See ND RFC + */ +#ifndef LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#endif + +/** + * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). + * May be updated by router advertisement messages. + */ +#ifndef LWIP_ND6_REACHABLE_TIME +#define LWIP_ND6_REACHABLE_TIME 30000 +#endif + +/** + * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages + */ +#ifndef LWIP_ND6_RETRANS_TIMER +#define LWIP_ND6_RETRANS_TIMER 1000 +#endif + +/** + * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation + * message is sent, during neighbor reachability detection. + */ +#ifndef LWIP_ND6_DELAY_FIRST_PROBE_TIME +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#endif + +/** + * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update + * Reachable time and retransmission timers, and netif MTU. + */ +#ifndef LWIP_ND6_ALLOW_RA_UPDATES +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#endif + +/** + * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during + * network startup. + */ +#ifndef LWIP_IPV6_SEND_ROUTER_SOLICIT +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#endif + +/** + * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery + * with reachability hints for connected destinations. This helps avoid sending + * unicast neighbor solicitation messages. + */ +#ifndef LWIP_ND6_TCP_REACHABILITY_HINTS +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#endif + +/** + * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. + */ +#ifndef LWIP_IPV6_AUTOCONFIG +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_DUP_DETECT_ATTEMPTS: Number of duplicate address detection attempts. + */ +#ifndef LWIP_IPV6_DUP_DETECT_ATTEMPTS +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#endif + +/** + * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. + */ +#ifndef LWIP_IPV6_DHCP6 +#define LWIP_IPV6_DHCP6 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#ifndef IP6_DEBUG +#define IP6_DEBUG LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/Shared/lwip/src/include/lwip/pbuf.h b/Shared/lwip/src/include/lwip/pbuf.h new file mode 100644 index 0000000..4f8dca8 --- /dev/null +++ b/Shared/lwip/src/include/lwip/pbuf.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG */ +#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) + +/* @todo: We need a mechanism to prevent wasting memory in every pbuf + (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ + +#define PBUF_TRANSPORT_HLEN 20 +#if LWIP_IPV6 +#define PBUF_IP_HLEN 40 +#else +#define PBUF_IP_HLEN 20 +#endif + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a + a pbuf differently */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +#if LWIP_TCP && TCP_QUEUE_OOSEQ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(void); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/ +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/Shared/lwip/src/include/lwip/raw.h b/Shared/lwip/src/include/lwip/raw.h new file mode 100644 index 0000000..f0c8ed4 --- /dev/null +++ b/Shared/lwip/src/include/lwip/raw.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_RAW_H__ +#define __LWIP_RAW_H__ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr); + +#if LWIP_IPV6 +/** Function prototype for raw pcb IPv6 receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IPv6 address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_ip6_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip6_addr_t *addr); +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV6 +#define RAW_PCB_RECV_IP6 raw_recv_ip6_fn ip6; +#else +#define RAW_PCB_RECV_IP6 +#endif /* LWIP_IPV6 */ + +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + union { + raw_recv_fn ip4; + RAW_PCB_RECV_IP6 + } recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +#if LWIP_IPV6 +struct raw_pcb * raw_new_ip6 (u8_t proto); +#define raw_bind_ip6(pcb, ip6addr) raw_bind(pcb, ip6_2_ip(ip6addr)) +#define raw_connect_ip6(pcb, ip6addr) raw_connect(pcb, ip6_2_ip(ip6addr)) +#define raw_recv_ip6(pcb, recv_ip6_fn, recv_arg) raw_recv(pcb, (raw_recv_fn)recv_ip6_fn, recv_arg) +#define raw_sendto_ip6(pcb, pbuf, ip6addr) raw_sendto(pcb, pbuf, ip6_2_ip(ip6addr)) +#endif /* LWIP_IPV6 */ + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, not init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* __LWIP_RAW_H__ */ diff --git a/Shared/lwip/src/include/lwip/sio.h b/Shared/lwip/src/include/lwip/sio.h new file mode 100644 index 0000000..28ae2f2 --- /dev/null +++ b/Shared/lwip/src/include/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef __SIO_H__ +#define __SIO_H__ + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SIO_H__ */ diff --git a/Shared/lwip/src/include/lwip/snmp.h b/Shared/lwip/src/include/lwip/snmp.h new file mode 100644 index 0000000..2ed043d --- /dev/null +++ b/Shared/lwip/src/include/lwip/snmp.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef __LWIP_SNMP_H__ +#define __LWIP_SNMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/ip_addr.h" + +struct udp_pcb; +struct netif; + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysobjid(struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value); +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip); +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void); +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdesr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value) +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors() +#define snmp_inc_icmpindestunreachs() +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs() +#define snmp_inc_icmpinsrcquenchs() +#define snmp_inc_icmpinredirects() +#define snmp_inc_icmpinechos() +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps() +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs() +#define snmp_inc_icmpouttimeexcds() +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects() +#define snmp_inc_icmpoutechos() +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SNMP_H__ */ diff --git a/Shared/lwip/src/include/lwip/snmp_asn1.h b/Shared/lwip/src/include/lwip/snmp_asn1.h new file mode 100644 index 0000000..605fa3f --- /dev/null +++ b/Shared/lwip/src/include/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_ASN1_H__ +#define __LWIP_SNMP_ASN1_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */ +#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */ +#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */ + +#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */ +#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */ + +/* universal tags */ +#define SNMP_ASN1_INTEG 2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL 5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ 16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1 /* u32_t */ +#define SNMP_ASN1_GAUGE 2 /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_ASN1_H__ */ diff --git a/Shared/lwip/src/include/lwip/snmp_msg.h b/Shared/lwip/src/include/lwip/snmp_msg.h new file mode 100644 index 0000000..1183e3a --- /dev/null +++ b/Shared/lwip/src/include/lwip/snmp_msg.h @@ -0,0 +1,315 @@ +/** + * @file + * SNMP Agent message handling structures. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_MSG_H__ +#define __LWIP_SNMP_MSG_H__ + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ + /* next pointer, NULL for last in list */ + struct snmp_varbind *next; + /* previous pointer, NULL for first in list */ + struct snmp_varbind *prev; + + /* object identifier length (in s32_t) */ + u8_t ident_len; + /* object identifier array */ + s32_t *ident; + + /* object value ASN1 type */ + u8_t value_type; + /* object value length (in u8_t) */ + u8_t value_len; + /* object value */ + void *value; + + /* encoding varbind seq length length */ + u8_t seqlenlen; + /* encoding object identifier length length */ + u8_t olenlen; + /* encoding object value length length */ + u8_t vlenlen; + /* encoding varbind seq length */ + u16_t seqlen; + /* encoding object identifier length */ + u16_t olen; + /* encoding object value length */ + u16_t vlen; +}; + +struct snmp_varbind_root +{ + struct snmp_varbind *head; + struct snmp_varbind *tail; + /* number of variable bindings in list */ + u8_t count; + /* encoding varbind-list seq length length */ + u8_t seqlenlen; + /* encoding varbind-list seq length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ + /* encoding error-index length length */ + u8_t erridxlenlen; + /* encoding error-status length length */ + u8_t errstatlenlen; + /* encoding request id length length */ + u8_t ridlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding error-index length */ + u16_t erridxlen; + /* encoding error-status length */ + u16_t errstatlen; + /* encoding request id length */ + u16_t ridlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ + /* encoding timestamp length length */ + u8_t tslenlen; + /* encoding specific-trap length length */ + u8_t strplenlen; + /* encoding generic-trap length length */ + u8_t gtrplenlen; + /* encoding agent-addr length length */ + u8_t aaddrlenlen; + /* encoding enterprise-id length length */ + u8_t eidlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding timestamp length */ + u16_t tslen; + /* encoding specific-trap length */ + u16_t strplen; + /* encoding generic-trap length */ + u16_t gtrplen; + /* encoding agent-addr length */ + u16_t aaddrlen; + /* encoding enterprise-id length */ + u16_t eidlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ 1 +/* Perform SNMP operation on in-memory object. + Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF 2 +#define SNMP_MSG_INTERNAL_GET_VALUE 3 +#define SNMP_MSG_INTERNAL_SET_TEST 4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE 6 +/* Perform SNMP operation on object located externally. + In theory this could be used for building a proxy agent. + Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7 +#define SNMP_MSG_EXTERNAL_GET_VALUE 8 +#define SNMP_MSG_EXTERNAL_SET_TEST 9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE 11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* source IP address */ + ip_addr_t sip; + /* source UDP port */ + u16_t sp; + /* request type */ + u8_t rt; + /* request ID */ + s32_t rid; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* community name (zero terminated) */ + u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u8_t com_strlen; + /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ + u8_t state; + /* saved arguments for MSG_EXTERNAL_x */ + struct mib_external_node *ext_mib_node; + struct snmp_name_ptr ext_name_ptr; + struct obj_def ext_object_def; + struct snmp_obj_id ext_oid; + /* index into input variable binding list */ + u8_t vb_idx; + /* ptr into input variable binding list */ + struct snmp_varbind *vb_ptr; + /* list of variable bindings from input */ + struct snmp_varbind_root invb; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output response lengths used in ASN encoding */ + struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* destination IP address in network order */ + ip_addr_t dip; + + /* source enterprise ID (sysObjectID) */ + struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + u8_t sip_raw[4]; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output trap lengths used in ASN encoding */ + struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_MSG_H__ */ diff --git a/Shared/lwip/src/include/lwip/snmp_structs.h b/Shared/lwip/src/include/lwip/snmp_structs.h new file mode 100644 index 0000000..0d3b46a --- /dev/null +++ b/Shared/lwip/src/include/lwip/snmp_structs.h @@ -0,0 +1,268 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB access types */ +#define MIB_ACCESS_READ 1 +#define MIB_ACCESS_WRITE 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ +#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE) +#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE +#define MIB_OBJECT_NOT_ACCESSIBLE 0 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(struct obj_def *od, u16_t len, void *value); + /** tests length and/or range BEFORE setting */ + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + /** sets object value, only to be called when set_test() */ + void (*set_value)(struct obj_def *od, u16_t len, void *value); + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + u8_t node_type; + /* array or max list length */ + u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + /** points to an external (in memory) record of some sort of addressing + information, passed to and interpreted by the funtions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external id + return zero when equal, nonzero when unequal */ + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async Questions */ + void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_q)(u8_t rid, struct obj_def *od); + void (*set_test_q)(u8_t rid, struct obj_def *od); + void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Answers */ + void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Panic Close (agent returns error reply, + e.g. used for external transaction cleanup) */ + void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_pc)(u8_t rid, struct obj_def *od); + void (*set_test_pc)(u8_t rid, struct obj_def *od); + void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, ip_addr_t *ip); +void snmp_iptooid(ip_addr_t *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_STRUCTS_H__ */ diff --git a/Shared/lwip/src/include/lwip/sockets.h b/Shared/lwip/src/include/lwip/sockets.h new file mode 100644 index 0000000..7346137 --- /dev/null +++ b/Shared/lwip/src/include/lwip/sockets.h @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef __LWIP_SOCKETS_H__ +#define __LWIP_SOCKETS_H__ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/inet.h" +#include "lwip/inet6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + u8_t sin_family; + u16_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; + +#if LWIP_IPV6 +struct sockaddr_in6 { + u8_t sin6_len; /* length of this structure */ + u8_t sin6_family; /* AF_INET6 */ + u16_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ +}; +#endif /* LWIP_IPV6 */ + +struct sockaddr { + u8_t sa_len; + u8_t sa_family; +#if LWIP_IPV6 + u8_t sa_data[22]; +#else /* LWIP_IPV6 */ + u8_t sa_data[14]; +#endif /* LWIP_IPV6 */ +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#if LWIP_IPV6 +#define AF_INET6 10 +#else /* LWIP_IPV6 */ +#define AF_INET6 AF_UNSPEC +#endif /* LWIP_IPV6 */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#if LWIP_IPV6 +#define IPPROTO_IPV6 41 +#endif /* LWIP_IPV6 */ +#define IPPROTO_UDPLITE 136 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* + * Options for level IPPROTO_IPV6 + */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET + #undef FD_SETSIZE + /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ + #define FD_SETSIZE MEMP_NUM_NETCONN + #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7))) + #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) + #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7))) + #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + + typedef struct fd_set { + unsigned char fd_bits [(FD_SETSIZE+7)/8]; + } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +void lwip_socket_init(void); + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c) lwip_accept(a,b,c) +#define bind(a,b,c) lwip_bind(a,b,c) +#define shutdown(a,b) lwip_shutdown(a,b) +#define closesocket(s) lwip_close(s) +#define connect(a,b,c) lwip_connect(a,b,c) +#define getsockname(a,b,c) lwip_getsockname(a,b,c) +#define getpeername(a,b,c) lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b) lwip_listen(a,b) +#define recv(a,b,c,d) lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d) lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c) lwip_socket(a,b,c) +#define select(a,b,c,d,e) lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c) lwip_read(a,b,c) +#define write(a,b,c) lwip_write(a,b,c) +#define close(s) lwip_close(s) +#define fcntl(a,b,c) lwip_fcntl(a,b,c) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* __LWIP_SOCKETS_H__ */ diff --git a/Shared/lwip/src/include/lwip/stats.h b/Shared/lwip/src/include/lwip/stats.h new file mode 100644 index 0000000..d911216 --- /dev/null +++ b/Shared/lwip/src/include/lwip/stats.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_STATS_H__ +#define __LWIP_STATS_H__ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +struct stats_mem { +#ifdef LWIP_DEBUG + const char *name; +#endif /* LWIP_DEBUG */ + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER err; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +#if IP6_STATS + struct stats_proto ip6; +#endif +#if ICMP6_STATS + struct stats_proto icmp6; +#endif +#if IP6_FRAG_STATS + struct stats_proto ip6_frag; +#endif +#if MLD6_STATS + struct stats_igmp mld6; +#endif +#if ND6_STATS + struct stats_proto nd6; +#endif +}; + +extern struct stats_ lwip_stats; + +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +#if IP6_STATS +#define IP6_STATS_INC(x) STATS_INC(x) +#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") +#else +#define IP6_STATS_INC(x) +#define IP6_STATS_DISPLAY() +#endif + +#if ICMP6_STATS +#define ICMP6_STATS_INC(x) STATS_INC(x) +#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") +#else +#define ICMP6_STATS_INC(x) +#define ICMP6_STATS_DISPLAY() +#endif + +#if IP6_FRAG_STATS +#define IP6_FRAG_STATS_INC(x) STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") +#else +#define IP6_FRAG_STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() +#endif + +#if MLD6_STATS +#define MLD6_STATS_INC(x) STATS_INC(x) +#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") +#else +#define MLD6_STATS_INC(x) +#define MLD6_STATS_DISPLAY() +#endif + +#if ND6_STATS +#define ND6_STATS_INC(x) STATS_INC(x) +#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") +#else +#define ND6_STATS_INC(x) +#define ND6_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp, const char *name); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp, name) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_STATS_H__ */ diff --git a/Shared/lwip/src/include/lwip/sys.h b/Shared/lwip/src/include/lwip/sys.h new file mode 100644 index 0000000..fd45ee8 --- /dev/null +++ b/Shared/lwip/src/include/lwip/sys.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_SYS_H__ +#define __LWIP_SYS_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_set_invalid(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_set_invalid(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** Signals a semaphore + * @param sem the semaphore to signal */ +void sys_sem_signal(sys_sem_t *sem); +/** Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** Delete a semaphore + * @param sem semaphore to delete */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif + +/* Mailbox functions. */ + +/** Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (miminum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** Delete an mbox + * @param mbox mbox to delete */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anthing else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** Ticks/jiffies since power up. */ +u32_t sys_jiffies(void); +#endif + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SYS_H__ */ diff --git a/Shared/lwip/src/include/lwip/tcp.h b/Shared/lwip/src/include/lwip/tcp.h new file mode 100644 index 0000000..535b6a3 --- /dev/null +++ b/Shared/lwip/src/include/lwip/tcp.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_H__ +#define __LWIP_TCP_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) TODO! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t abortsthe new connection + */ +#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept; +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + int bound_to_netif; \ + u16_t local_port; \ + char local_netif[3] + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + u8_t flags; +#define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ +#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + u16_t rcv_wnd; /* receiver window available */ + u16_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + u16_t cwnd; + u16_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + u16_t snd_wnd; /* sender window */ + u16_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + u16_t acked; + + u16_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +#if LWIP_IPV6 + u8_t accept_any_ip_version; +#endif /* LWIP_IPV6 */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); + +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ + (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ + (pcb)->state == LISTEN) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t tcp_bind_to_netif (struct tcp_pcb *pcb, const char ifname[3]); +err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + +#if LWIP_IPV6 +struct tcp_pcb * tcp_new_ip6 (void); +#define tcp_bind_ip6(pcb, ip6addr, port) \ + tcp_bind(pcb, ip6_2_ip(ip6addr), port) +#define tcp_connect_ip6(pcb, ip6addr, port, connected) \ + tcp_connect(pcb, ip6_2_ip(ip6addr), port, connected) +struct tcp_pcb * tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen_dual(pcb) tcp_listen_dual_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) +#else /* LWIP_IPV6 */ +#define tcp_listen_dual_with_backlog(pcb, backlog) tcp_listen_with_backlog(pcb, backlog) +#define tcp_listen_dual(pcb) tcp_listen(pcb) +#endif /* LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/Shared/lwip/src/include/lwip/tcp_impl.h b/Shared/lwip/src/include/lwip/tcp_impl.h new file mode 100644 index 0000000..2afc20d --- /dev/null +++ b/Shared/lwip/src/include/lwip/tcp_impl.h @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_IMPL_H__ +#define __LWIP_TCP_IMPL_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segements on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversized only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for(tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst_impl(u32_t seqno, u32_t ackno, + ipX_addr_t *local_ip, ipX_addr_t *remote_ip, + u16_t local_port, u16_t remote_port +#if LWIP_IPV6 + , u8_t isipv6 +#endif /* LWIP_IPV6 */ + ); +#if LWIP_IPV6 +#define tcp_rst(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) \ + tcp_rst_impl(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) +#else /* LWIP_IPV6 */ +#define tcp_rst(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) \ + tcp_rst_impl(seqno, ackno, local_ip, remote_ip, local_port, remote_port) +#endif /* LWIP_IPV6 */ + +u32_t tcp_next_iss(void); + +void tcp_keepalive(struct tcp_pcb *pcb); +void tcp_zero_window_probe(struct tcp_pcb *pcb); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest +#if LWIP_IPV6 + , ipX_addr_t *src, u8_t isipv6 +#endif /* LWIP_IPV6 */ + ); +#if LWIP_IPV6 +#define tcp_eff_send_mss(sendmss, src, dest, isipv6) tcp_eff_send_mss_impl(sendmss, dest, src, isipv6) +#else /* LWIP_IPV6 */ +#define tcp_eff_send_mss(sendmss, src, dest, isipv6) tcp_eff_send_mss_impl(sendmss, dest) +#endif /* LWIP_IPV6 */ +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/Shared/lwip/src/include/lwip/tcpip.h b/Shared/lwip/src/include/lwip/tcpip.h new file mode 100644 index 0000000..04567f2 --- /dev/null +++ b/Shared/lwip/src/include/lwip/tcpip.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCPIP_H__ +#define __LWIP_TCPIP_H__ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/timers.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. */ +#ifndef LWIP_TCPIP_THREAD_ALIVE +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#ifdef LWIP_DEBUG +#define TCIP_APIMSG_SET_ERR(m, e) (m)->msg.err = e /* catch functions that don't set err */ +#else +#define TCIP_APIMSG_SET_ERR(m, e) +#endif +#define TCPIP_APIMSG_NOERR(m,f) do { \ + TCIP_APIMSG_SET_ERR(m, ERR_VAL); \ + LOCK_TCPIP_CORE(); \ + f(&((m)->msg)); \ + UNLOCK_TCPIP_CORE(); \ +} while(0) +#define TCPIP_APIMSG(m,f,e) do { \ + TCPIP_APIMSG_NOERR(m,f); \ + (e) = (m)->msg.err; \ +} while(0) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG_NOERR(m,f) do { (m)->function = f; tcpip_apimsg(m); } while(0) +#define TCPIP_APIMSG(m,f,e) do { (m)->function = f; (e) = tcpip_apimsg(m); } while(0) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed) +#define TCPIP_NETIFAPI(m) tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +#if LWIP_NETCONN +err_t tcpip_apimsg(struct api_msg *apimsg); +#endif /* LWIP_NETCONN */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT */ + +enum tcpip_msg_type { +#if LWIP_NETCONN + TCPIP_MSG_API, +#endif /* LWIP_NETCONN */ + TCPIP_MSG_INPKT, +#if LWIP_NETIF_API + TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ +#if LWIP_TCPIP_TIMEOUT + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + sys_sem_t *sem; + union { +#if LWIP_NETCONN + struct api_msg *apimsg; +#endif /* LWIP_NETCONN */ +#if LWIP_NETIF_API + struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ + struct { + struct pbuf *p; + struct netif *netif; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* __LWIP_TCPIP_H__ */ diff --git a/Shared/lwip/src/include/lwip/timers.h b/Shared/lwip/src/include/lwip/timers.h new file mode 100644 index 0000000..04e78e0 --- /dev/null +++ b/Shared/lwip/src/include/lwip/timers.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef __LWIP_TIMERS_H__ +#define __LWIP_TIMERS_H__ + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +#if NO_SYS +void sys_check_timeouts(void); +void sys_restart_timeouts(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* __LWIP_TIMERS_H__ */ diff --git a/Shared/lwip/src/include/lwip/udp.h b/Shared/lwip/src/include/lwip/udp.h new file mode 100644 index 0000000..14d5c0a --- /dev/null +++ b/Shared/lwip/src/include/lwip/udp.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_UDP_H__ +#define __LWIP_UDP_H__ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf + * makes 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port); + +#if LWIP_IPV6 +/** Function prototype for udp pcb IPv6 receive callback functions + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IPv6 address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_ip6_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip6_addr_t *addr, u16_t port); +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV6 +#define UDP_PCB_RECV_IP6 udp_recv_ip6_fn ip6; +#else +#define UDP_PCB_RECV_IP6 +#endif /* LWIP_IPV6 */ + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_IGMP + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + union { + udp_recv_fn ip4; + UDP_PCB_RECV_IP6 + }recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for exernal reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +#if LWIP_IPV6 +struct udp_pcb * udp_new_ip6(void); +#define udp_bind_ip6(pcb, ip6addr, port) \ + udp_bind(pcb, ip6_2_ip(ip6addr), port) +#define udp_connect_ip6(pcb, ip6addr, port) \ + udp_connect(pcb, ip6_2_ip(ip6addr), port) +#define udp_recv_ip6(pcb, recv_ip6_fn, recv_arg) \ + udp_recv(pcb, (udp_recv_fn)recv_ip6_fn, recv_arg) +#define udp_sendto_ip6(pcb, pbuf, ip6addr, port) \ + udp_sendto(pcb, pbuf, ip6_2_ip(ip6addr), port) +#define udp_sendto_if_ip6(pcb, pbuf, ip6addr, port, netif) \ + udp_sendto_if(pcb, pbuf, ip6_2_ip(ip6addr), port, netif) +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +#define udp_sendto_chksum_ip6(pcb, pbuf, ip6addr, port, have_chk, chksum) \ + udp_sendto_chksum(pcb, pbuf, ip6_2_ip(ip6addr), port, have_chk, chksum) +#define udp_sendto_if_chksum_ip6(pcb, pbuf, ip6addr, port, netif, have_chk, chksum) \ + udp_sendto_if_chksum(pcb, pbuf, ip6_2_ip(ip6addr), port, netif, have_chk, chksum) +#endif /*LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +#endif /* LWIP_IPV6 */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* __LWIP_UDP_H__ */ diff --git a/Shared/lwip/src/include/netif/etharp.h b/Shared/lwip/src/include/netif/etharp.h new file mode 100644 index 0000000..8275a28 --- /dev/null +++ b/Shared/lwip/src/include/netif/etharp.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __NETIF_ETHARP_H__ +#define __NETIF_ETHARP_H__ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN 6 +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FIELD(struct eth_addr dest); + PACK_STRUCT_FIELD(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#if ETHARP_SUPPORT_VLAN + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) + +#endif /* ETHARP_SUPPORT_VLAN */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FIELD(u8_t hwlen); + PACK_STRUCT_FIELD(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FIELD(struct eth_addr shwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 sipaddr); + PACK_STRUCT_FIELD(struct eth_addr dhwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) + +/** 5 seconds period */ +#define ARP_TMR_INTERVAL 5000 + +#define ETHTYPE_ARP 0x0806U +#define ETHTYPE_IP 0x0800U +#define ETHTYPE_VLAN 0x8100U +#define ETHTYPE_IPV6 0x86DDU +#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN) +#endif + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** ARP message types (opcodes) */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, not init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr) +void etharp_cleanup_netif(struct netif *netif); + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(ip_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_AUTOIP +err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode); +#endif /* LWIP_AUTOIP */ + +#endif /* LWIP_ARP */ + +err_t ethernet_input(struct pbuf *p, struct netif *netif); + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#endif /* __NETIF_ARP_H__ */ diff --git a/Shared/lwip/src/include/netif/ppp_oe.h b/Shared/lwip/src/include/netif/ppp_oe.h new file mode 100644 index 0000000..e1cdfa5 --- /dev/null +++ b/Shared/lwip/src/include/netif/ppp_oe.h @@ -0,0 +1,190 @@ +/***************************************************************************** +* ppp_oe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PPP_OE_H +#define PPP_OE_H + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT > 0 + +#include "netif/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FIELD(u8_t vertype); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +#define PPPOE_STATE_CLOSING 4 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef ETHERMTU +#define ETHERMTU 1500 +#endif + +/* two byte PPP protocol discriminator, then IP data */ +#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2) + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + int sc_pd; /* ppp unit number */ + void (*sc_linkStatusCB)(int pd, int up); + + int sc_state; /* discovery phase or session connected */ + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + +#ifdef PPPOE_TODO + char *sc_service_name; /* if != NULL: requested name of service */ + char *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + size_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + size_t sc_hunique_len; /* length of host unique */ +#endif + int sc_padi_retried; /* number of PADI retries already done */ + int sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); +err_t pppoe_destroy(struct netif *ifp); + +int pppoe_connect(struct pppoe_softc *sc); +void pppoe_disconnect(struct pppoe_softc *sc); + +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); + +/** used in ppp.c */ +#define PPPOE_HDRLEN (sizeof(struct eth_hdr) + PPPOE_HEADERLEN) + +#endif /* PPPOE_SUPPORT */ + +#endif /* PPP_OE_H */ diff --git a/Shared/lwip/src/include/netif/slipif.h b/Shared/lwip/src/include/netif/slipif.h new file mode 100644 index 0000000..7b6ce5e --- /dev/null +++ b/Shared/lwip/src/include/netif/slipif.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __NETIF_SLIPIF_H__ +#define __NETIF_SLIPIF_H__ + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serila line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Shared/lwip/src/include/posix/netdb.h b/Shared/lwip/src/include/posix/netdb.h new file mode 100644 index 0000000..7134032 --- /dev/null +++ b/Shared/lwip/src/include/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/Shared/lwip/src/include/posix/sys/socket.h b/Shared/lwip/src/include/posix/sys/socket.h new file mode 100644 index 0000000..f7c7066 --- /dev/null +++ b/Shared/lwip/src/include/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/Shared/lwip/test/unit/core/test_mem.c b/Shared/lwip/test/unit/core/test_mem.c new file mode 100644 index 0000000..d3a5d54 --- /dev/null +++ b/Shared/lwip/test/unit/core/test_mem.c @@ -0,0 +1,73 @@ +#include "test_mem.h" + +#include "lwip/mem.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !MEM_STATS +#error "This tests needs MEM-statistics enabled" +#endif +#if LWIP_DNS +#error "This test needs DNS turned off (as it mallocs on init)" +#endif + +/* Setups/teardown functions */ + +static void +mem_setup(void) +{ +} + +static void +mem_teardown(void) +{ +} + + +/* Test functions */ + +/** Call mem_malloc, mem_free and mem_trim and check stats */ +START_TEST(test_mem_one) +{ +#define SIZE1 16 +#define SIZE1_2 12 +#define SIZE2 16 + void *p1, *p2; + mem_size_t s1, s2; + LWIP_UNUSED_ARG(_i); + +#if LWIP_DNS + fail("This test needs DNS turned off (as it mallocs on init)"); +#endif + + fail_unless(lwip_stats.mem.used == 0); + + p1 = mem_malloc(SIZE1); + fail_unless(p1 != NULL); + fail_unless(lwip_stats.mem.used >= SIZE1); + s1 = lwip_stats.mem.used; + + p2 = mem_malloc(SIZE2); + fail_unless(p2 != NULL); + fail_unless(lwip_stats.mem.used >= SIZE2 + s1); + s2 = lwip_stats.mem.used; + + mem_trim(p1, SIZE1_2); + + mem_free(p2); + fail_unless(lwip_stats.mem.used <= s2 - SIZE2); + + mem_free(p1); + fail_unless(lwip_stats.mem.used == 0); +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +mem_suite(void) +{ + TFun tests[] = { + test_mem_one + }; + return create_suite("MEM", tests, sizeof(tests)/sizeof(TFun), mem_setup, mem_teardown); +} diff --git a/Shared/lwip/test/unit/core/test_mem.h b/Shared/lwip/test/unit/core/test_mem.h new file mode 100644 index 0000000..13803ed --- /dev/null +++ b/Shared/lwip/test/unit/core/test_mem.h @@ -0,0 +1,8 @@ +#ifndef __TEST_MEM_H__ +#define __TEST_MEM_H__ + +#include "../lwip_check.h" + +Suite *mem_suite(void); + +#endif diff --git a/Shared/lwip/test/unit/core/test_pbuf.c b/Shared/lwip/test/unit/core/test_pbuf.c new file mode 100644 index 0000000..2911078 --- /dev/null +++ b/Shared/lwip/test/unit/core/test_pbuf.c @@ -0,0 +1,73 @@ +#include "test_pbuf.h" + +#include "lwip/pbuf.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !MEM_STATS ||!MEMP_STATS +#error "This tests needs MEM- and MEMP-statistics enabled" +#endif +#if LWIP_DNS +#error "This test needs DNS turned off (as it mallocs on init)" +#endif + +/* Setups/teardown functions */ + +static void +pbuf_setup(void) +{ +} + +static void +pbuf_teardown(void) +{ +} + + +/* Test functions */ + +/** Call pbuf_copy on a pbuf with zero length */ +START_TEST(test_pbuf_copy_zero_pbuf) +{ + struct pbuf *p1, *p2, *p3; + err_t err; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0); + + p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM); + fail_unless(p1 != NULL); + fail_unless(p1->ref == 1); + + p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL); + fail_unless(p2 != NULL); + fail_unless(p2->ref == 1); + p2->len = p2->tot_len = 0; + + pbuf_cat(p1, p2); + fail_unless(p1->ref == 1); + fail_unless(p2->ref == 1); + + p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL); + err = pbuf_copy(p3, p1); + fail_unless(err == ERR_VAL); + + pbuf_free(p1); + pbuf_free(p3); + fail_unless(lwip_stats.mem.used == 0); + + fail_unless(lwip_stats.mem.used == 0); + fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0); +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +pbuf_suite(void) +{ + TFun tests[] = { + test_pbuf_copy_zero_pbuf + }; + return create_suite("PBUF", tests, sizeof(tests)/sizeof(TFun), pbuf_setup, pbuf_teardown); +} diff --git a/Shared/lwip/test/unit/core/test_pbuf.h b/Shared/lwip/test/unit/core/test_pbuf.h new file mode 100644 index 0000000..b2715ad --- /dev/null +++ b/Shared/lwip/test/unit/core/test_pbuf.h @@ -0,0 +1,8 @@ +#ifndef __TEST_PBUF_H__ +#define __TEST_PBUF_H__ + +#include "../lwip_check.h" + +Suite *pbuf_suite(void); + +#endif diff --git a/Shared/lwip/test/unit/dhcp/test_dhcp.c b/Shared/lwip/test/unit/dhcp/test_dhcp.c new file mode 100644 index 0000000..4b40de8 --- /dev/null +++ b/Shared/lwip/test/unit/dhcp/test_dhcp.c @@ -0,0 +1,916 @@ +#include "test_dhcp.h" + +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "netif/etharp.h" + +struct netif net_test; + +static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + +static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 }; + +static u8_t dhcp_offer[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ + 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ + 0x08, 0x00, /* Protocol: IP */ + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ + 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ + + 0x02, /* Type == Boot reply */ + 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ + 0x00, /* 0 hops */ + 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ + 0x00, 0x00, /* 0 seconds elapsed */ + 0x00, 0x00, /* Flags (unicast) */ + 0x00, 0x00, 0x00, 0x00, /* Client ip */ + 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ + 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ + 0x00, 0x00, 0x00, 0x00, /* relay agent */ + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ + + /* Empty server name and boot file name */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ + 0x35, 0x01, 0x02, /* Message type: Offer */ + 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ + 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ + 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ + 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ + 0xff, /* End option */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ +}; + +static u8_t dhcp_ack[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ + 0x00, 0x0f, 0xEE, 0x30, 0xAB, 0x22, /* From remote host */ + 0x08, 0x00, /* Proto IP */ + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ + 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ + 0x02, /* Bootp reply */ + 0x01, 0x06, /* Hw type Eth, len 6 */ + 0x00, /* 0 hops */ + 0xAA, 0xAA, 0xAA, 0xAA, + 0x00, 0x00, /* 0 seconds elapsed */ + 0x00, 0x00, /* Flags (unicast) */ + 0x00, 0x00, 0x00, 0x00, /* Client IP */ + 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ + 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server IP */ + 0x00, 0x00, 0x00, 0x00, /* Relay agent */ + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Macaddr + padding */ + + /* Empty server name and boot file name */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ + 0x35, 0x01, 0x05, /* Dhcp message type ack */ + 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server identifier */ + 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ + 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ + 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Netmask */ + 0xff, /* End marker */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ +}; + +static const u8_t arpreply[] = { + 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* dst mac */ + 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* src mac */ + 0x08, 0x06, /* proto arp */ + 0x00, 0x01, /* hw eth */ + 0x08, 0x00, /* proto ip */ + 0x06, /* hw addr len 6 */ + 0x04, /* proto addr len 4 */ + 0x00, 0x02, /* arp reply */ + 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* sender mac */ + 0xc3, 0xaa, 0xbd, 0xc8, /* sender ip */ + 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* target mac */ + 0x00, 0x00, 0x00, 0x00, /* target ip */ +}; + +static int txpacket; +static enum tcase { + TEST_LWIP_DHCP, + TEST_LWIP_DHCP_NAK, + TEST_LWIP_DHCP_RELAY, + TEST_LWIP_DHCP_NAK_NO_ENDMARKER, +} tcase; + +static int debug = 0; +static void setdebug(int a) {debug = a;} + +static int tick = 0; +static void tick_lwip(void) +{ + tick++; + if (tick % 5 == 0) { + dhcp_fine_tmr(); + } + if (tick % 600 == 0) { + dhcp_coarse_tmr(); + } +} + +static void send_pkt(struct netif *netif, const u8_t *data, u32_t len) +{ + struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + struct pbuf *q; + + if (debug) { + /* Dump data */ + u32_t i; + printf("RX data (len %d)", p->tot_len); + for (i = 0; i < len; i++) { + printf(" %02X", data[i]); + } + printf("\n"); + } + + fail_unless(p != NULL); + for(q = p; q != NULL; q = q->next) { + memcpy(q->payload, data, q->len); + data += q->len; + } + netif->input(p, netif); +} + +static err_t lwip_tx_func(struct netif *netif, struct pbuf *p); + +static err_t testif_init(struct netif *netif) +{ + netif->name[0] = 'c'; + netif->name[1] = 'h'; + netif->output = etharp_output; + netif->linkoutput = lwip_tx_func; + netif->mtu = 1500; + netif->hwaddr_len = 6; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + netif->hwaddr[0] = 0x00; + netif->hwaddr[1] = 0x23; + netif->hwaddr[2] = 0xC1; + netif->hwaddr[3] = 0xDE; + netif->hwaddr[4] = 0xD0; + netif->hwaddr[5] = 0x0D; + + return ERR_OK; +} + +static void dhcp_setup(void) +{ + txpacket = 0; +} + +static void dhcp_teardown(void) +{ +} + +static void check_pkt(struct pbuf *p, u32_t pos, const u8_t *mem, u32_t len) +{ + u8_t *data; + + fail_if((pos + len) > p->tot_len); + while (pos > p->len && p->next) { + pos -= p->len; + p = p->next; + } + fail_if(p == NULL); + fail_unless(pos + len <= p->len); /* All data we seek within same pbuf */ + + data = p->payload; + fail_if(memcmp(&data[pos], mem, len), "data at pos %d, len %d in packet %d did not match", pos, len, txpacket); +} + +static void check_pkt_fuzzy(struct pbuf *p, u32_t startpos, const u8_t *mem, u32_t len) +{ + int found; + u32_t i; + u8_t *data; + + fail_if((startpos + len) > p->tot_len); + while (startpos > p->len && p->next) { + startpos -= p->len; + p = p->next; + } + fail_if(p == NULL); + fail_unless(startpos + len <= p->len); /* All data we seek within same pbuf */ + + found = 0; + data = p->payload; + for (i = startpos; i <= (p->len - len); i++) { + if (memcmp(&data[i], mem, len) == 0) { + found = 1; + break; + } + } + fail_unless(found); +} + +static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) +{ + fail_unless(netif == &net_test); + txpacket++; + + if (debug) { + struct pbuf *pp = p; + /* Dump data */ + printf("TX data (pkt %d, len %d, tick %d)", txpacket, p->tot_len, tick); + do { + int i; + for (i = 0; i < pp->len; i++) { + printf(" %02X", ((u8_t *) pp->payload)[i]); + } + if (pp->next) { + pp = pp->next; + } + } while (pp->next); + printf("\n"); + } + + switch (tcase) { + case TEST_LWIP_DHCP: + switch (txpacket) { + case 1: + case 2: + { + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + /* Check dchp message type, can be at different positions */ + if (txpacket == 1) { + u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; + check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); + } else if (txpacket == 2) { + u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; + u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* Ask for offered IP */ + + check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); + check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); + } + break; + } + case 3: + case 4: + case 5: + { + const u8_t arpproto[] = { 0x08, 0x06 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ + break; + } + } + break; + + case TEST_LWIP_DHCP_NAK: + { + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const u8_t dhcp_nak_opt[] = { 0x35, 0x01, 0x04 }; + const u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* offered IP */ + + fail_unless(txpacket == 4); + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + check_pkt_fuzzy(p, 282, dhcp_nak_opt, sizeof(dhcp_nak_opt)); /* NAK the ack */ + + check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); + break; + } + + case TEST_LWIP_DHCP_RELAY: + switch (txpacket) { + case 1: + case 2: + { + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + /* Check dchp message type, can be at different positions */ + if (txpacket == 1) { + u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; + check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); + } else if (txpacket == 2) { + u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; + u8_t requested_ipaddr[] = { 0x32, 0x04, 0x4f, 0x8a, 0x33, 0x05 }; /* Ask for offered IP */ + + check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); + check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); + } + break; + } + case 3: + case 4: + case 5: + case 6: + { + const u8_t arpproto[] = { 0x08, 0x06 }; + + check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ + break; + } + case 7: + { + const u8_t fake_arp[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab }; + const u8_t ipproto[] = { 0x08, 0x00 }; + const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ + const u8_t ipaddrs[] = { 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; + + check_pkt(p, 0, fake_arp, 6); /* eth level dest: broadcast */ + check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ + + check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ + + check_pkt(p, 42, bootp_start, sizeof(bootp_start)); + + check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); + + check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ + + check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); + + /* Check dchp message type, can be at different positions */ + check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); + break; + } + } + break; + + default: + break; + } + + return ERR_OK; +} + +/* + * Test basic happy flow DHCP session. + * Validate that xid is checked. + */ +START_TEST(test_dhcp) +{ + struct ip_addr addr; + struct ip_addr netmask; + struct ip_addr gw; + int i; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_offer[46], &xid, 4); + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + /* Interface down */ + fail_if(netif_is_up(&net_test)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(struct ip_addr))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(struct ip_addr))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(struct ip_addr))); + + fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */ + xid = htonl(net_test.dhcp->xid); + memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */ + xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_ack[46], &xid, 4); + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */ + xid = htonl(net_test.dhcp->xid); /* xid updated */ + memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + for (i = 0; i < 20; i++) { + tick_lwip(); + } + fail_unless(txpacket == 4, "TX %d packets, expected 4", txpacket); /* ARP requests sent */ + + /* Interface up */ + fail_unless(netif_is_up(&net_test)); + + /* Now it should have taken the IP */ + IP4_ADDR(&addr, 195, 170, 189, 200); + IP4_ADDR(&netmask, 255, 255, 255, 0); + IP4_ADDR(&gw, 195, 170, 189, 171); + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(struct ip_addr))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(struct ip_addr))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(struct ip_addr))); + + netif_remove(&net_test); +} +END_TEST + +/* + * Test that IP address is not taken and NAK is sent if someone + * replies to ARP requests for the offered address. + */ +START_TEST(test_dhcp_nak) +{ + struct ip_addr addr; + struct ip_addr netmask; + struct ip_addr gw; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_offer[46], &xid, 4); + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + /* Interface down */ + fail_if(netif_is_up(&net_test)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(struct ip_addr))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(struct ip_addr))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(struct ip_addr))); + + fail_unless(txpacket == 1); /* Nothing more sent */ + xid = htonl(net_test.dhcp->xid); + memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + fail_unless(txpacket == 2); /* DHCP request sent */ + xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_ack[46], &xid, 4); + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + fail_unless(txpacket == 2); /* No more sent */ + xid = htonl(net_test.dhcp->xid); /* xid updated */ + memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); + + fail_unless(txpacket == 3); /* ARP request sent */ + + tcase = TEST_LWIP_DHCP_NAK; /* Switch testcase */ + + /* Send arp reply, mark offered IP as taken */ + send_pkt(&net_test, arpreply, sizeof(arpreply)); + + fail_unless(txpacket == 4); /* DHCP nak sent */ + + netif_remove(&net_test); +} +END_TEST + +/* + * Test case based on captured data where + * replies are sent from a different IP than the + * one the client unicasted to. + */ +START_TEST(test_dhcp_relayed) +{ + const u8_t relay_offer[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, + 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, + 0x08, 0x00, 0x45, 0x00, + 0x01, 0x38, 0xfd, 0x53, 0x00, 0x00, 0x40, 0x11, + 0x78, 0x46, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, + 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, + 0xb6, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, + 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, + 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, + 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x02, 0x36, + 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff + }; + + const u8_t relay_ack1[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, + 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, + 0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11, + 0x78, 0x44, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, + 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, + 0xb6, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, + 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, + 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, + 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x05, 0x36, + 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff + }; + + const u8_t relay_ack2[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, + 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, + 0x08, 0x00, 0x45, 0x00, + 0x01, 0x38, 0xfa, 0x18, 0x00, 0x00, 0x40, 0x11, + 0x7b, 0x81, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, + 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x49, 0x8b, + 0x6e, 0xab, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8a, + 0x33, 0x05, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, + 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, + 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, + 0x00, 0x00, 0x54, 0x60, 0x35, 0x01, 0x05, 0x36, + 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff }; + + const u8_t arp_resp[] = { + 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* DEST */ + 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, /* SRC */ + 0x08, 0x06, /* Type: ARP */ + 0x00, 0x01, /* HW: Ethernet */ + 0x08, 0x00, /* PROTO: IP */ + 0x06, /* HW size */ + 0x04, /* PROTO size */ + 0x00, 0x02, /* OPCODE: Reply */ + + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, /* Target MAC */ + 0x4f, 0x8a, 0x32, 0x01, /* Target IP */ + + 0x00, 0x23, 0xc1, 0x00, 0x06, 0x50, /* src mac */ + 0x4f, 0x8a, 0x33, 0x05, /* src ip */ + + /* Padding follows.. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + struct ip_addr addr; + struct ip_addr netmask; + struct ip_addr gw; + int i; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP_RELAY; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + + /* Interface down */ + fail_if(netif_is_up(&net_test)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(struct ip_addr))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(struct ip_addr))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(struct ip_addr))); + + fail_unless(txpacket == 1); /* Nothing more sent */ + xid = htonl(net_test.dhcp->xid); + memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, relay_offer, sizeof(relay_offer)); + + /* request sent? */ + fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket); + xid = htonl(net_test.dhcp->xid); /* xid updated */ + memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, relay_ack1, sizeof(relay_ack1)); + + for (i = 0; i < 25; i++) { + tick_lwip(); + } + fail_unless(txpacket == 4, "txpkt should be 5, is %d", txpacket); /* ARP requests sent */ + + /* Interface up */ + fail_unless(netif_is_up(&net_test)); + + /* Now it should have taken the IP */ + IP4_ADDR(&addr, 79, 138, 51, 5); + IP4_ADDR(&netmask, 255, 255, 254, 0); + IP4_ADDR(&gw, 79, 138, 50, 1); + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(struct ip_addr))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(struct ip_addr))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(struct ip_addr))); + + fail_unless(txpacket == 4, "txpacket = %d", txpacket); + + for (i = 0; i < 108000 - 25; i++) { + tick_lwip(); + } + + fail_unless(netif_is_up(&net_test)); + fail_unless(txpacket == 6, "txpacket = %d", txpacket); + + /* We need to send arp response here.. */ + + send_pkt(&net_test, arp_resp, sizeof(arp_resp)); + + fail_unless(txpacket == 7, "txpacket = %d", txpacket); + fail_unless(netif_is_up(&net_test)); + + xid = htonl(net_test.dhcp->xid); /* xid updated */ + memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, relay_ack2, sizeof(relay_ack2)); + + for (i = 0; i < 100000; i++) { + tick_lwip(); + } + + fail_unless(txpacket == 7, "txpacket = %d", txpacket); + + netif_remove(&net_test); + +} +END_TEST + +START_TEST(test_dhcp_nak_no_endmarker) +{ + struct ip_addr addr; + struct ip_addr netmask; + struct ip_addr gw; + + u8_t dhcp_nack_no_endmarker[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x54, 0x75, + 0xd0, 0x26, 0xd0, 0x0d, 0x08, 0x00, 0x45, 0x00, + 0x01, 0x15, 0x38, 0x86, 0x00, 0x00, 0xff, 0x11, + 0xc0, 0xa8, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x01, + 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x7a, 0xcb, + 0xba, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, + 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, + 0x53, 0x63, 0x35, 0x01, 0x06, 0x36, 0x04, 0xc0, + 0xa8, 0x01, 0x01, 0x31, 0xef, 0xad, 0x72, 0x31, + 0x43, 0x4e, 0x44, 0x30, 0x32, 0x35, 0x30, 0x43, + 0x52, 0x47, 0x44, 0x38, 0x35, 0x36, 0x3c, 0x08, + 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, + 0x37, 0x0d, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, + 0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xfc, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x71, + 0xf3, 0x5b, 0xe2, 0x71, 0x2e, 0x01, 0x08, 0x03, + 0x04, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xeb, 0x1e, + 0x44, 0xec, 0xeb, 0x1e, 0x30, 0x37, 0x0c, 0x01, + 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, + 0x79, 0xf9, 0x2b, 0xff, 0x25, 0xc0, 0x09, 0xd6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u32_t xid; + LWIP_UNUSED_ARG(_i); + + tcase = TEST_LWIP_DHCP_NAK_NO_ENDMARKER; + setdebug(0); + + IP4_ADDR(&addr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + + netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); + + dhcp_start(&net_test); + + fail_unless(txpacket == 1); /* DHCP discover sent */ + xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */ + memcpy(&dhcp_offer[46], &xid, 4); + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + /* Interface down */ + fail_if(netif_is_up(&net_test)); + + /* IP addresses should be zero */ + fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(struct ip_addr))); + fail_if(memcmp(&netmask, &net_test.netmask, sizeof(struct ip_addr))); + fail_if(memcmp(&gw, &net_test.gw, sizeof(struct ip_addr))); + + fail_unless(txpacket == 1); /* Nothing more sent */ + xid = htonl(net_test.dhcp->xid); + memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ + send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); + + fail_unless(net_test.dhcp->state == DHCP_REQUESTING); + + fail_unless(txpacket == 2); /* No more sent */ + xid = htonl(net_test.dhcp->xid); /* xid updated */ + memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */ + send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker)); + + /* NAK should put us in another state for a while, no other way detecting it */ + fail_unless(net_test.dhcp->state != DHCP_REQUESTING); + + netif_remove(&net_test); +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +dhcp_suite(void) +{ + TFun tests[] = { + test_dhcp, + test_dhcp_nak, + test_dhcp_relayed, + test_dhcp_nak_no_endmarker + }; + return create_suite("DHCP", tests, sizeof(tests)/sizeof(TFun), dhcp_setup, dhcp_teardown); +} diff --git a/Shared/lwip/test/unit/dhcp/test_dhcp.h b/Shared/lwip/test/unit/dhcp/test_dhcp.h new file mode 100644 index 0000000..aff44b7 --- /dev/null +++ b/Shared/lwip/test/unit/dhcp/test_dhcp.h @@ -0,0 +1,8 @@ +#ifndef __TEST_DHCP_H__ +#define __TEST_DHCP_H__ + +#include "../lwip_check.h" + +Suite* dhcp_suite(void); + +#endif diff --git a/Shared/lwip/test/unit/etharp/test_etharp.c b/Shared/lwip/test/unit/etharp/test_etharp.c new file mode 100644 index 0000000..cbbc950 --- /dev/null +++ b/Shared/lwip/test/unit/etharp/test_etharp.c @@ -0,0 +1,262 @@ +#include "test_etharp.h" + +#include "lwip/udp.h" +#include "netif/etharp.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS +#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" +#endif +#if !ETHARP_SUPPORT_STATIC_ENTRIES +#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" +#endif + +static struct netif test_netif; +static ip_addr_t test_ipaddr, test_netmask, test_gw; +struct eth_addr test_ethaddr = {1,1,1,1,1,1}; +struct eth_addr test_ethaddr2 = {1,1,1,1,1,2}; +struct eth_addr test_ethaddr3 = {1,1,1,1,1,3}; +struct eth_addr test_ethaddr4 = {1,1,1,1,1,4}; +static int linkoutput_ctr; + +/* Helper functions */ +static void +etharp_remove_all(void) +{ + int i; + /* call etharp_tmr often enough to have all entries cleaned */ + for(i = 0; i < 0xff; i++) { + etharp_tmr(); + } +} + +static err_t +default_netif_linkoutput(struct netif *netif, struct pbuf *p) +{ + fail_unless(netif == &test_netif); + fail_unless(p != NULL); + linkoutput_ctr++; + return ERR_OK; +} + +static err_t +default_netif_init(struct netif *netif) +{ + fail_unless(netif != NULL); + netif->linkoutput = default_netif_linkoutput; + netif->output = etharp_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + netif->hwaddr_len = ETHARP_HWADDR_LEN; + return ERR_OK; +} + +static void +default_netif_add(void) +{ + IP4_ADDR(&test_gw, 192,168,0,1); + IP4_ADDR(&test_ipaddr, 192,168,0,1); + IP4_ADDR(&test_netmask, 255,255,0,0); + + fail_unless(netif_default == NULL); + netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, + &test_gw, NULL, default_netif_init, NULL)); + netif_set_up(&test_netif); +} + +static void +default_netif_remove(void) +{ + fail_unless(netif_default == &test_netif); + netif_remove(&test_netif); +} + +static void +create_arp_response(ip_addr_t *adr) +{ + int k; + struct eth_hdr *ethhdr; + struct etharp_hdr *etharphdr; + struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); + if(p == NULL) { + FAIL_RET(); + } + ethhdr = (struct eth_hdr*)p->payload; + etharphdr = (struct etharp_hdr*)(ethhdr + 1); + + ethhdr->dest = test_ethaddr; + ethhdr->src = test_ethaddr2; + ethhdr->type = htons(ETHTYPE_ARP); + + etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1); + etharphdr->proto = htons(ETHTYPE_IP); + etharphdr->hwlen = ETHARP_HWADDR_LEN; + etharphdr->protolen = sizeof(ip_addr_t); + etharphdr->opcode = htons(ARP_REPLY); + + SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip_addr_t)); + SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip_addr_t)); + + k = 6; + while(k > 0) { + k--; + /* Write the ARP MAC-Addresses */ + etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; + etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; + /* Write the Ethernet MAC-Addresses */ + ethhdr->dest.addr[k] = test_ethaddr.addr[k]; + ethhdr->src.addr[k] = test_ethaddr2.addr[k]; + } + + ethernet_input(p, &test_netif); +} + +/* Setups/teardown functions */ + +static void +etharp_setup(void) +{ + etharp_remove_all(); + default_netif_add(); +} + +static void +etharp_teardown(void) +{ + etharp_remove_all(); + default_netif_remove(); +} + + +/* Test functions */ + +START_TEST(test_etharp_table) +{ +#if ETHARP_SUPPORT_STATIC_ENTRIES + err_t err; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + s8_t idx; + ip_addr_t *unused_ipaddr; + struct eth_addr *unused_ethaddr; + struct udp_pcb* pcb; + LWIP_UNUSED_ARG(_i); + + if (netif_default != &test_netif) { + fail("This test needs a default netif"); + } + + linkoutput_ctr = 0; + + pcb = udp_new(); + fail_unless(pcb != NULL); + if (pcb != NULL) { + ip_addr_t adrs[ARP_TABLE_SIZE + 2]; + int i; + for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { + IP4_ADDR(&adrs[i], 192,168,0,i+2); + } + /* fill ARP-table with dynamic entries */ + for(i = 0; i < ARP_TABLE_SIZE; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); + fail_unless(p != NULL); + if (p != NULL) { + err_t err = udp_sendto(pcb, p, &adrs[i], 123); + fail_unless(err == ERR_OK); + /* etharp request sent? */ + fail_unless(linkoutput_ctr == (2*i) + 1); + pbuf_free(p); + + /* create an ARP response */ + create_arp_response(&adrs[i]); + /* queued UDP packet sent? */ + fail_unless(linkoutput_ctr == (2*i) + 2); + + idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == i); + etharp_tmr(); + } + } + linkoutput_ctr = 0; +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* create one static entry */ + err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + fail_unless(linkoutput_ctr == 0); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + + linkoutput_ctr = 0; + /* fill ARP-table with dynamic entries */ + for(i = 0; i < ARP_TABLE_SIZE; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); + fail_unless(p != NULL); + if (p != NULL) { + err_t err = udp_sendto(pcb, p, &adrs[i], 123); + fail_unless(err == ERR_OK); + /* etharp request sent? */ + fail_unless(linkoutput_ctr == (2*i) + 1); + pbuf_free(p); + + /* create an ARP response */ + create_arp_response(&adrs[i]); + /* queued UDP packet sent? */ + fail_unless(linkoutput_ctr == (2*i) + 2); + + idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); + if (i < ARP_TABLE_SIZE - 1) { + fail_unless(idx == i+1); + } else { + /* the last entry must not overwrite the static entry! */ + fail_unless(idx == 1); + } + etharp_tmr(); + } + } +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* create a second static entry */ + err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 2); + /* and remove it again */ + err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == -1); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + + /* check that static entries don't time out */ + etharp_remove_all(); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == 0); + +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* remove the first static entry */ + err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); + fail_unless(err == ERR_OK); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == -1); + idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); + fail_unless(idx == -1); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + + udp_remove(pcb); + } +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +etharp_suite(void) +{ + TFun tests[] = { + test_etharp_table + }; + return create_suite("ETHARP", tests, sizeof(tests)/sizeof(TFun), etharp_setup, etharp_teardown); +} diff --git a/Shared/lwip/test/unit/etharp/test_etharp.h b/Shared/lwip/test/unit/etharp/test_etharp.h new file mode 100644 index 0000000..96e00c3 --- /dev/null +++ b/Shared/lwip/test/unit/etharp/test_etharp.h @@ -0,0 +1,8 @@ +#ifndef __TEST_ETHARP_H__ +#define __TEST_ETHARP_H__ + +#include "../lwip_check.h" + +Suite* etharp_suite(void); + +#endif diff --git a/Shared/lwip/test/unit/lwip_check.h b/Shared/lwip/test/unit/lwip_check.h new file mode 100644 index 0000000..e27f55a --- /dev/null +++ b/Shared/lwip/test/unit/lwip_check.h @@ -0,0 +1,37 @@ +#ifndef __LWIP_CHECK_H__ +#define __LWIP_CHECK_H__ + +/* Common header file for lwIP unit tests using the check framework */ + +#include +#include +#include + +#define FAIL_RET() do { fail(); return; } while(0) +#define EXPECT(x) fail_unless(x) +#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0) +#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0) +#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL) + +/** typedef for a function returning a test suite */ +typedef Suite* (suite_getter_fn)(void); + +/** Create a test suite */ +static Suite* create_suite(const char* name, TFun *tests, size_t num_tests, SFun setup, SFun teardown) +{ + size_t i; + Suite *s = suite_create(name); + + for(i = 0; i < num_tests; i++) { + /* Core test case */ + TCase *tc_core = tcase_create("Core"); + if ((setup != NULL) || (teardown != NULL)) { + tcase_add_checked_fixture(tc_core, setup, teardown); + } + tcase_add_test(tc_core, tests[i]); + suite_add_tcase(s, tc_core); + } + return s; +} + +#endif /* __LWIP_CHECK_H__ */ diff --git a/Shared/lwip/test/unit/lwip_unittests.c b/Shared/lwip/test/unit/lwip_unittests.c new file mode 100644 index 0000000..41d1f36 --- /dev/null +++ b/Shared/lwip/test/unit/lwip_unittests.c @@ -0,0 +1,49 @@ +#include "lwip_check.h" + +#include "udp/test_udp.h" +#include "tcp/test_tcp.h" +#include "tcp/test_tcp_oos.h" +#include "core/test_mem.h" +#include "core/test_pbuf.h" +#include "etharp/test_etharp.h" +#include "dhcp/test_dhcp.h" + +#include "lwip/init.h" + + +int main() +{ + int number_failed; + SRunner *sr; + size_t i; + suite_getter_fn* suites[] = { + udp_suite, + tcp_suite, + tcp_oos_suite, + mem_suite, + pbuf_suite, + etharp_suite, + dhcp_suite + }; + size_t num = sizeof(suites)/sizeof(void*); + LWIP_ASSERT("No suites defined", num > 0); + + lwip_init(); + + sr = srunner_create((suites[0])()); + for(i = 1; i < num; i++) { + srunner_add_suite(sr, ((suite_getter_fn*)suites[i])()); + } + +#ifdef LWIP_UNITTESTS_NOFORK + srunner_set_fork_status(sr, CK_NOFORK); +#endif +#ifdef LWIP_UNITTESTS_FORK + srunner_set_fork_status(sr, CK_FORK); +#endif + + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/Shared/lwip/test/unit/lwipopts.h b/Shared/lwip/test/unit/lwipopts.h new file mode 100644 index 0000000..0059515 --- /dev/null +++ b/Shared/lwip/test/unit/lwipopts.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 1 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 + +/* Enable DHCP to test it, disable UDP checksum to easier inject packets */ +#define LWIP_DHCP 1 + +/* Minimal changes to opt.h required for tcp unit tests: */ +#define MEM_SIZE 16000 +#define TCP_SND_QUEUELEN 40 +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN +#define TCP_SND_BUF (12 * TCP_MSS) +#define TCP_WND (10 * TCP_MSS) + +/* Minimal changes to opt.h required for etharp unit tests: */ +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 + +#endif /* __LWIPOPTS_H__ */ diff --git a/Shared/lwip/test/unit/tcp/tcp_helper.c b/Shared/lwip/test/unit/tcp/tcp_helper.c new file mode 100644 index 0000000..ff503db --- /dev/null +++ b/Shared/lwip/test/unit/tcp/tcp_helper.c @@ -0,0 +1,303 @@ +#include "tcp_helper.h" + +#include "lwip/tcp_impl.h" +#include "lwip/stats.h" +#include "lwip/pbuf.h" +#include "lwip/inet_chksum.h" + +#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS +#error "This tests needs TCP- and MEMP-statistics enabled" +#endif + +/** Remove all pcbs on the given list. */ +static void +tcp_remove(struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb = pcb_list; + struct tcp_pcb *pcb2; + + while(pcb != NULL) { + pcb2 = pcb; + pcb = pcb->next; + tcp_abort(pcb2); + } +} + +/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */ +void +tcp_remove_all(void) +{ + tcp_remove(tcp_listen_pcbs.pcbs); + tcp_remove(tcp_active_pcbs); + tcp_remove(tcp_tw_pcbs); + fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0); + fail_unless(lwip_stats.memp[MEMP_TCP_PCB_LISTEN].used == 0); + fail_unless(lwip_stats.memp[MEMP_TCP_SEG].used == 0); + fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0); +} + +/** Create a TCP segment usable for passing to tcp_input */ +static struct pbuf* +tcp_create_segment_wnd(ip_addr_t* src_ip, ip_addr_t* dst_ip, + u16_t src_port, u16_t dst_port, void* data, size_t data_len, + u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd) +{ + struct pbuf *p, *q; + struct ip_hdr* iphdr; + struct tcp_hdr* tcphdr; + u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len); + + p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL); + EXPECT_RETNULL(p != NULL); + /* first pbuf must be big enough to hold the headers */ + EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); + if (data_len > 0) { + /* first pbuf must be big enough to hold at least 1 data byte, too */ + EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); + } + + for(q = p; q != NULL; q = q->next) { + memset(q->payload, 0, q->len); + } + + iphdr = p->payload; + /* fill IP header */ + iphdr->dest.addr = dst_ip->addr; + iphdr->src.addr = src_ip->addr; + IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); + IPH_TOS_SET(iphdr, 0); + IPH_LEN_SET(iphdr, htons(p->tot_len)); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + + /* let p point to TCP header */ + pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); + + tcphdr = p->payload; + tcphdr->src = htons(src_port); + tcphdr->dest = htons(dst_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4); + TCPH_FLAGS_SET(tcphdr, headerflags); + tcphdr->wnd = htons(wnd); + + if (data_len > 0) { + /* let p point to TCP data */ + pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr)); + /* copy data */ + pbuf_take(p, data, data_len); + /* let p point to TCP header again */ + pbuf_header(p, sizeof(struct tcp_hdr)); + } + + /* calculate checksum */ + + tcphdr->chksum = inet_chksum_pseudo(p, + IP_PROTO_TCP, p->tot_len, src_ip, dst_ip); + + pbuf_header(p, sizeof(struct ip_hdr)); + + return p; +} + +/** Create a TCP segment usable for passing to tcp_input */ +struct pbuf* +tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, + u16_t src_port, u16_t dst_port, void* data, size_t data_len, + u32_t seqno, u32_t ackno, u8_t headerflags) +{ + return tcp_create_segment_wnd(src_ip, dst_ip, src_port, dst_port, data, + data_len, seqno, ackno, headerflags, TCP_WND); +} + +/** Create a TCP segment usable for passing to tcp_input + * - IP-addresses, ports, seqno and ackno are taken from pcb + * - seqno and ackno can be altered with an offset + */ +struct pbuf* +tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset, + u32_t ackno_offset, u8_t headerflags) +{ + return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, + data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags); +} + +/** Create a TCP segment usable for passing to tcp_input + * - IP-addresses, ports, seqno and ackno are taken from pcb + * - seqno and ackno can be altered with an offset + * - TCP window can be adjusted + */ +struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, + u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd) +{ + return tcp_create_segment_wnd(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, + data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags, wnd); +} + +/** Safely bring a tcp_pcb into the requested state */ +void +tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, + ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port) +{ + /* @todo: are these all states? */ + /* @todo: remove from previous list */ + pcb->state = state; + if (state == ESTABLISHED) { + TCP_REG(&tcp_active_pcbs, pcb); + pcb->local_ip.addr = local_ip->addr; + pcb->local_port = local_port; + pcb->remote_ip.addr = remote_ip->addr; + pcb->remote_port = remote_port; + } else if(state == LISTEN) { + TCP_REG(&tcp_listen_pcbs.pcbs, pcb); + pcb->local_ip.addr = local_ip->addr; + pcb->local_port = local_port; + } else if(state == TIME_WAIT) { + TCP_REG(&tcp_tw_pcbs, pcb); + pcb->local_ip.addr = local_ip->addr; + pcb->local_port = local_port; + pcb->remote_ip.addr = remote_ip->addr; + pcb->remote_port = remote_port; + } else { + fail(); + } +} + +void +test_tcp_counters_err(void* arg, err_t err) +{ + struct test_tcp_counters* counters = arg; + EXPECT_RET(arg != NULL); + counters->err_calls++; + counters->last_err = err; +} + +static void +test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p) +{ + struct pbuf* q; + u32_t i, received; + if(counters->expected_data == NULL) { + /* no data to compare */ + return; + } + EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len); + received = counters->recved_bytes; + for(q = p; q != NULL; q = q->next) { + char *data = q->payload; + for(i = 0; i < q->len; i++) { + EXPECT_RET(data[i] == counters->expected_data[received]); + received++; + } + } + EXPECT(received == counters->recved_bytes + p->tot_len); +} + +err_t +test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) +{ + struct test_tcp_counters* counters = arg; + EXPECT_RETX(arg != NULL, ERR_OK); + EXPECT_RETX(pcb != NULL, ERR_OK); + EXPECT_RETX(err == ERR_OK, ERR_OK); + + if (p != NULL) { + if (counters->close_calls == 0) { + counters->recv_calls++; + test_tcp_counters_check_rxdata(counters, p); + counters->recved_bytes += p->tot_len; + } else { + counters->recv_calls_after_close++; + counters->recved_bytes_after_close += p->tot_len; + } + pbuf_free(p); + } else { + counters->close_calls++; + } + EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0); + return ERR_OK; +} + +/** Allocate a pcb and set up the test_tcp_counters_* callbacks */ +struct tcp_pcb* +test_tcp_new_counters_pcb(struct test_tcp_counters* counters) +{ + struct tcp_pcb* pcb = tcp_new(); + if (pcb != NULL) { + /* set up args and callbacks */ + tcp_arg(pcb, counters); + tcp_recv(pcb, test_tcp_counters_recv); + tcp_err(pcb, test_tcp_counters_err); + pcb->snd_wnd = TCP_WND; + pcb->snd_wnd_max = TCP_WND; + } + return pcb; +} + +/** Calls tcp_input() after adjusting current_iphdr_dest */ +void test_tcp_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; + /* these lines are a hack, don't use them as an example :-) */ + ip_addr_copy(*ipX_current_dest_addr(), iphdr->dest); + ip_addr_copy(*ipX_current_src_addr(), iphdr->src); + ip_current_netif() = inp; + ip_current_header() = iphdr; + + /* since adding IPv6, p->payload must point to tcp header, not ip header */ + pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); + + tcp_input(p, inp); + + ipX_current_dest_addr()->addr = 0; + ipX_current_src_addr()->addr = 0; + ip_current_netif() = NULL; + ip_current_header() = NULL; +} + +static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr) +{ + struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state; + LWIP_UNUSED_ARG(ipaddr); + if (txcounters != NULL) + { + txcounters->num_tx_calls++; + txcounters->num_tx_bytes += p->tot_len; + if (txcounters->copy_tx_packets) { + struct pbuf *p_copy = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + err_t err; + EXPECT(p_copy != NULL); + err = pbuf_copy(p_copy, p); + EXPECT(err == ERR_OK); + if (txcounters->tx_packets == NULL) { + txcounters->tx_packets = p_copy; + } else { + pbuf_cat(txcounters->tx_packets, p_copy); + } + } + } + return ERR_OK; +} + +void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, + ip_addr_t *ip_addr, ip_addr_t *netmask) +{ + struct netif *n; + memset(netif, 0, sizeof(struct netif)); + if (txcounters != NULL) { + memset(txcounters, 0, sizeof(struct test_tcp_txcounters)); + netif->state = txcounters; + } + netif->output = test_tcp_netif_output; + netif->flags |= NETIF_FLAG_UP; + ip_addr_copy(netif->netmask, *netmask); + ip_addr_copy(netif->ip_addr, *ip_addr); + for (n = netif_list; n != NULL; n = n->next) { + if (n == netif) { + return; + } + } + netif->next = NULL; + netif_list = netif; +} diff --git a/Shared/lwip/test/unit/tcp/tcp_helper.h b/Shared/lwip/test/unit/tcp/tcp_helper.h new file mode 100644 index 0000000..4a72c93 --- /dev/null +++ b/Shared/lwip/test/unit/tcp/tcp_helper.h @@ -0,0 +1,52 @@ +#ifndef __TCP_HELPER_H__ +#define __TCP_HELPER_H__ + +#include "../lwip_check.h" +#include "lwip/arch.h" +#include "lwip/tcp.h" +#include "lwip/netif.h" + +/* counters used for test_tcp_counters_* callback functions */ +struct test_tcp_counters { + u32_t recv_calls; + u32_t recved_bytes; + u32_t recv_calls_after_close; + u32_t recved_bytes_after_close; + u32_t close_calls; + u32_t err_calls; + err_t last_err; + char* expected_data; + u32_t expected_data_len; +}; + +struct test_tcp_txcounters { + u32_t num_tx_calls; + u32_t num_tx_bytes; + u8_t copy_tx_packets; + struct pbuf *tx_packets; +}; + +/* Helper functions */ +void tcp_remove_all(void); + +struct pbuf* tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, + u16_t src_port, u16_t dst_port, void* data, size_t data_len, + u32_t seqno, u32_t ackno, u8_t headerflags); +struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, + u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags); +struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, + u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd); +void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, + ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port); +void test_tcp_counters_err(void* arg, err_t err); +err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err); + +struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters); + +void test_tcp_input(struct pbuf *p, struct netif *inp); + +void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, + ip_addr_t *ip_addr, ip_addr_t *netmask); + + +#endif diff --git a/Shared/lwip/test/unit/tcp/test_tcp.c b/Shared/lwip/test/unit/tcp/test_tcp.c new file mode 100644 index 0000000..8172098 --- /dev/null +++ b/Shared/lwip/test/unit/tcp/test_tcp.c @@ -0,0 +1,671 @@ +#include "test_tcp.h" + +#include "lwip/tcp_impl.h" +#include "lwip/stats.h" +#include "tcp_helper.h" + +#ifdef _MSC_VER +#pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */ +#endif + +#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS +#error "This tests needs TCP- and MEMP-statistics enabled" +#endif +#if TCP_SND_BUF <= TCP_WND +#error "This tests needs TCP_SND_BUF to be > TCP_WND" +#endif + +static u8_t test_tcp_timer; + +/* our own version of tcp_tmr so we can reset fast/slow timer state */ +static void +test_tcp_tmr(void) +{ + tcp_fasttmr(); + if (++test_tcp_timer & 1) { + tcp_slowtmr(); + } +} + +/* Setups/teardown functions */ + +static void +tcp_setup(void) +{ + /* reset iss to default (6510) */ + tcp_ticks = 0; + tcp_ticks = 0 - (tcp_next_iss() - 6510); + tcp_next_iss(); + tcp_ticks = 0; + + test_tcp_timer = 0; + tcp_remove_all(); +} + +static void +tcp_teardown(void) +{ + tcp_remove_all(); + netif_list = NULL; + netif_default = NULL; +} + + +/* Test functions */ + +/** Call tcp_new() and tcp_abort() and test memp stats */ +START_TEST(test_tcp_new_abort) +{ + struct tcp_pcb* pcb; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0); + + pcb = tcp_new(); + fail_unless(pcb != NULL); + if (pcb != NULL) { + fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0); + } +} +END_TEST + +/** Create an ESTABLISHED pcb and check if receive callback is called */ +START_TEST(test_tcp_recv_inseq) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + char data[] = {1, 2, 3, 4}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + struct test_tcp_txcounters txcounters; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create a segment */ + p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); + EXPECT(p != NULL); + if (p != NULL) { + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == data_len); + EXPECT(counters.err_calls == 0); + } + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} +END_TEST + +/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. + * At the end, send more data. */ +START_TEST(test_tcp_fast_retx_recover) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + char data1[] = { 1, 2, 3, 4}; + char data2[] = { 5, 6, 7, 8}; + char data3[] = { 9, 10, 11, 12}; + char data4[] = {13, 14, 15, 16}; + char data5[] = {17, 18, 19, 20}; + char data6[] = {21, 22, 23, 24}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = pcb->snd_wnd; + + /* send data1 */ + err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT_RET(txcounters.num_tx_calls == 1); + EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); + memset(&txcounters, 0, sizeof(txcounters)); + /* "recv" ACK for data1 */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(pcb->unacked == NULL); + /* send data2 */ + err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT_RET(txcounters.num_tx_calls == 1); + EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); + memset(&txcounters, 0, sizeof(txcounters)); + /* duplicate ACK for data1 (data2 is lost) */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(pcb->dupacks == 1); + /* send data3 */ + err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* nagle enabled, no tx calls */ + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(txcounters.num_tx_bytes == 0); + memset(&txcounters, 0, sizeof(txcounters)); + /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(pcb->dupacks == 2); + /* queue data4, don't send it (unsent-oversize is != 0) */ + err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + /*EXPECT_RET(txcounters.num_tx_calls == 1);*/ + EXPECT_RET(pcb->dupacks == 3); + memset(&txcounters, 0, sizeof(txcounters)); + /* TODO: check expected data?*/ + + /* send data5, not output yet */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + /*err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK);*/ + EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(txcounters.num_tx_bytes == 0); + memset(&txcounters, 0, sizeof(txcounters)); + { + int i = 0; + do + { + err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY); + i++; + }while(err == ERR_OK); + EXPECT_RET(err != ERR_OK); + } + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /*EXPECT_RET(txcounters.num_tx_calls == 0); + EXPECT_RET(txcounters.num_tx_bytes == 0);*/ + memset(&txcounters, 0, sizeof(txcounters)); + + /* send even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + + /* send ACKs for data2 and data3 */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK); + EXPECT_RET(p != NULL); + test_tcp_input(p, &netif); + /*EXPECT_RET(txcounters.num_tx_calls == 0);*/ + + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + /* ...and even more data */ + err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + +#if 0 + /* create expected segment */ + p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); + EXPECT_RET(p != NULL); + if (p != NULL) { + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT_RET(counters.close_calls == 0); + EXPECT_RET(counters.recv_calls == 1); + EXPECT_RET(counters.recved_bytes == data_len); + EXPECT_RET(counters.err_calls == 0); + } +#endif + /* make sure the pcb is freed */ + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} +END_TEST + +static u8_t tx_data[TCP_WND*2]; + +static void +check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected) +{ + struct tcp_seg *s = segs; + int i; + for (i = 0; i < num_expected; i++, s = s->next) { + EXPECT_RET(s != NULL); + EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i])); + } + EXPECT(s == NULL); +} + +/** Send data with sequence numbers that wrap around the u32_t range. + * Then, provoke fast retransmission by duplicate ACKs and check that all + * segment lists are still properly sorted. */ +START_TEST(test_tcp_fast_rexmit_wraparound) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf* p; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; +#define SEQNO1 (0xFFFFFF00 - TCP_MSS) +#define ISS 6510 + u16_t i, sent_total = 0; + u32_t seqnos[] = { + SEQNO1, + SEQNO1 + (1 * TCP_MSS), + SEQNO1 + (2 * TCP_MSS), + SEQNO1 + (3 * TCP_MSS), + SEQNO1 + (4 * TCP_MSS), + SEQNO1 + (5 * TCP_MSS)}; + LWIP_UNUSED_ARG(_i); + + for (i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (u8_t)i; + } + + /* initialize local vars */ + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + + /* create and initialize the pcb */ + tcp_ticks = SEQNO1 - ISS; + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + EXPECT(pcb->lastack == SEQNO1); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = 2*TCP_MSS; + + /* send 6 mss-sized segments */ + for (i = 0; i < 6; i++) { + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + sent_total += TCP_MSS; + } + check_seqnos(pcb->unsent, 6, seqnos); + EXPECT(pcb->unacked == NULL); + err = tcp_output(pcb); + EXPECT(txcounters.num_tx_calls == 2); + EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); + memset(&txcounters, 0, sizeof(txcounters)); + + check_seqnos(pcb->unacked, 2, seqnos); + check_seqnos(pcb->unsent, 4, &seqnos[2]); + + /* ACK the first segment */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK); + test_tcp_input(p, &netif); + /* ensure this didn't trigger a retransmission */ + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + check_seqnos(pcb->unacked, 2, &seqnos[1]); + check_seqnos(pcb->unsent, 3, &seqnos[3]); + + /* 3 dupacks */ + EXPECT(pcb->dupacks == 0); + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(pcb->dupacks == 1); + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(pcb->dupacks == 2); + /* 3rd dupack -> fast rexmit */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + EXPECT(pcb->dupacks == 3); + EXPECT(txcounters.num_tx_calls == 4); + memset(&txcounters, 0, sizeof(txcounters)); + EXPECT(pcb->unsent == NULL); + check_seqnos(pcb->unacked, 5, &seqnos[1]); + + /* make sure the pcb is freed */ + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} +END_TEST + +/** Send data with sequence numbers that wrap around the u32_t range. + * Then, provoke RTO retransmission and check that all + * segment lists are still properly sorted. */ +START_TEST(test_tcp_rto_rexmit_wraparound) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; +#define SEQNO1 (0xFFFFFF00 - TCP_MSS) +#define ISS 6510 + u16_t i, sent_total = 0; + u32_t seqnos[] = { + SEQNO1, + SEQNO1 + (1 * TCP_MSS), + SEQNO1 + (2 * TCP_MSS), + SEQNO1 + (3 * TCP_MSS), + SEQNO1 + (4 * TCP_MSS), + SEQNO1 + (5 * TCP_MSS)}; + LWIP_UNUSED_ARG(_i); + + for (i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (u8_t)i; + } + + /* initialize local vars */ + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + + /* create and initialize the pcb */ + tcp_ticks = 0; + tcp_ticks = 0 - tcp_next_iss(); + tcp_ticks = SEQNO1 - tcp_next_iss(); + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + EXPECT(pcb->lastack == SEQNO1); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = 2*TCP_MSS; + + /* send 6 mss-sized segments */ + for (i = 0; i < 6; i++) { + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + sent_total += TCP_MSS; + } + check_seqnos(pcb->unsent, 6, seqnos); + EXPECT(pcb->unacked == NULL); + err = tcp_output(pcb); + EXPECT(txcounters.num_tx_calls == 2); + EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); + memset(&txcounters, 0, sizeof(txcounters)); + + check_seqnos(pcb->unacked, 2, seqnos); + check_seqnos(pcb->unsent, 4, &seqnos[2]); + + /* call the tcp timer some times */ + for (i = 0; i < 10; i++) { + test_tcp_tmr(); + EXPECT(txcounters.num_tx_calls == 0); + } + /* 11th call to tcp_tmr: RTO rexmit fires */ + test_tcp_tmr(); + EXPECT(txcounters.num_tx_calls == 1); + check_seqnos(pcb->unacked, 1, seqnos); + check_seqnos(pcb->unsent, 5, &seqnos[1]); + + /* fake greater cwnd */ + pcb->cwnd = pcb->snd_wnd; + /* send more data */ + err = tcp_output(pcb); + EXPECT(err == ERR_OK); + /* check queues are sorted */ + EXPECT(pcb->unsent == NULL); + check_seqnos(pcb->unacked, 6, seqnos); + + /* make sure the pcb is freed */ + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} +END_TEST + +/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. + * At the end, send more data. */ +static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent) +{ + struct netif netif; + struct test_tcp_txcounters txcounters; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + err_t err; + u16_t sent_total, i; + u8_t expected = 0xFE; + + for (i = 0; i < sizeof(tx_data); i++) { + u8_t d = (u8_t)i; + if (d == 0xFE) { + d = 0xF0; + } + tx_data[i] = d; + } + if (zero_window_probe_from_unsent) { + tx_data[TCP_WND] = expected; + } else { + tx_data[0] = expected; + } + + /* initialize local vars */ + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); + memset(&counters, 0, sizeof(counters)); + memset(&txcounters, 0, sizeof(txcounters)); + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->mss = TCP_MSS; + /* disable initial congestion window (we don't send a SYN here...) */ + pcb->cwnd = pcb->snd_wnd; + + /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */ + sent_total = 0; + if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) { + u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS; + err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + sent_total += initial_data_len; + } + for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) { + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + } + EXPECT(sent_total == (TCP_WND - TCP_MSS)); + + /* now ACK the packet before the first */ + p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); + test_tcp_input(p, &netif); + /* ensure this didn't trigger a retransmission */ + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + + EXPECT(pcb->persist_backoff == 0); + /* send the last packet, now a complete window has been sent */ + err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); + sent_total += TCP_MSS; + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); + memset(&txcounters, 0, sizeof(txcounters)); + EXPECT(pcb->persist_backoff == 0); + + if (zero_window_probe_from_unsent) { + /* ACK all data but close the TX window */ + p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0); + test_tcp_input(p, &netif); + /* ensure this didn't trigger any transmission */ + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + EXPECT(pcb->persist_backoff == 1); + } + + /* send one byte more (out of window) -> persist timer starts */ + err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY); + EXPECT_RET(err == ERR_OK); + err = tcp_output(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + memset(&txcounters, 0, sizeof(txcounters)); + if (!zero_window_probe_from_unsent) { + /* no persist timer unless a zero window announcement has been received */ + EXPECT(pcb->persist_backoff == 0); + } else { + EXPECT(pcb->persist_backoff == 1); + + /* call tcp_timer some more times to let persist timer count up */ + for (i = 0; i < 4; i++) { + test_tcp_tmr(); + EXPECT(txcounters.num_tx_calls == 0); + EXPECT(txcounters.num_tx_bytes == 0); + } + + /* this should trigger the zero-window-probe */ + txcounters.copy_tx_packets = 1; + test_tcp_tmr(); + txcounters.copy_tx_packets = 0; + EXPECT(txcounters.num_tx_calls == 1); + EXPECT(txcounters.num_tx_bytes == 1 + 40U); + EXPECT(txcounters.tx_packets != NULL); + if (txcounters.tx_packets != NULL) { + u8_t sent; + u16_t ret; + ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U); + EXPECT(ret == 1); + EXPECT(sent == expected); + } + if (txcounters.tx_packets != NULL) { + pbuf_free(txcounters.tx_packets); + txcounters.tx_packets = NULL; + } + } + + /* make sure the pcb is freed */ + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} + +START_TEST(test_tcp_tx_full_window_lost_from_unsent) +{ + LWIP_UNUSED_ARG(_i); + test_tcp_tx_full_window_lost(1); +} +END_TEST + +START_TEST(test_tcp_tx_full_window_lost_from_unacked) +{ + LWIP_UNUSED_ARG(_i); + test_tcp_tx_full_window_lost(0); +} +END_TEST + +/** Create the suite including all tests for this module */ +Suite * +tcp_suite(void) +{ + TFun tests[] = { + test_tcp_new_abort, + test_tcp_recv_inseq, + test_tcp_fast_retx_recover, + test_tcp_fast_rexmit_wraparound, + test_tcp_rto_rexmit_wraparound, + test_tcp_tx_full_window_lost_from_unacked, + test_tcp_tx_full_window_lost_from_unsent + }; + return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown); +} diff --git a/Shared/lwip/test/unit/tcp/test_tcp.h b/Shared/lwip/test/unit/tcp/test_tcp.h new file mode 100644 index 0000000..f1c4a46 --- /dev/null +++ b/Shared/lwip/test/unit/tcp/test_tcp.h @@ -0,0 +1,8 @@ +#ifndef __TEST_TCP_H__ +#define __TEST_TCP_H__ + +#include "../lwip_check.h" + +Suite *tcp_suite(void); + +#endif diff --git a/Shared/lwip/test/unit/tcp/test_tcp_oos.c b/Shared/lwip/test/unit/tcp/test_tcp_oos.c new file mode 100644 index 0000000..612c468 --- /dev/null +++ b/Shared/lwip/test/unit/tcp/test_tcp_oos.c @@ -0,0 +1,958 @@ +#include "test_tcp_oos.h" + +#include "lwip/tcp_impl.h" +#include "lwip/stats.h" +#include "tcp_helper.h" + +#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS +#error "This tests needs TCP- and MEMP-statistics enabled" +#endif +#if !TCP_QUEUE_OOSEQ +#error "This tests needs TCP_QUEUE_OOSEQ enabled" +#endif + +/** CHECK_SEGMENTS_ON_OOSEQ: + * 1: check count, seqno and len of segments on pcb->ooseq (strict) + * 0: only check that bytes are received in correct order (less strict) */ +#define CHECK_SEGMENTS_ON_OOSEQ 1 + +#if CHECK_SEGMENTS_ON_OOSEQ +#define EXPECT_OOSEQ(x) EXPECT(x) +#else +#define EXPECT_OOSEQ(x) +#endif + +/* helper functions */ + +/** Get the numbers of segments on the ooseq list */ +static int tcp_oos_count(struct tcp_pcb* pcb) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + while(seg != NULL) { + num++; + seg = seg->next; + } + return num; +} + +/** Get the numbers of pbufs on the ooseq list */ +static int tcp_oos_pbuf_count(struct tcp_pcb* pcb) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + while(seg != NULL) { + num += pbuf_clen(seg->p); + seg = seg->next; + } + return num; +} + +/** Get the seqno of a segment (by index) on the ooseq list + * + * @param pcb the pcb to check for ooseq segments + * @param seg_index index of the segment on the ooseq list + * @return seqno of the segment + */ +static u32_t +tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + + /* then check the actual segment */ + while(seg != NULL) { + if(num == seg_index) { + return seg->tcphdr->seqno; + } + num++; + seg = seg->next; + } + fail(); + return 0; +} + +/** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list + * + * @param pcb the pcb to check for ooseq segments + * @param seg_index index of the segment on the ooseq list + * @return tcplen of the segment + */ +static int +tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index) +{ + int num = 0; + struct tcp_seg* seg = pcb->ooseq; + + /* then check the actual segment */ + while(seg != NULL) { + if(num == seg_index) { + return TCP_TCPLEN(seg); + } + num++; + seg = seg->next; + } + fail(); + return -1; +} + +/** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list + * + * @param pcb the pcb to check for ooseq segments + * @return tcplen of all segment + */ +static int +tcp_oos_tcplen(struct tcp_pcb* pcb) +{ + int len = 0; + struct tcp_seg* seg = pcb->ooseq; + + /* then check the actual segment */ + while(seg != NULL) { + len += TCP_TCPLEN(seg); + seg = seg->next; + } + return len; +} + +/* Setup/teardown functions */ + +static void +tcp_oos_setup(void) +{ + tcp_remove_all(); +} + +static void +tcp_oos_teardown(void) +{ + tcp_remove_all(); + netif_list = NULL; + netif_default = NULL; +} + + + +/* Test functions */ + +/** create multiple segments and pass them to tcp_input in a wrong + * order to see if ooseq-caching works correctly + * FIN is received in out-of-sequence segments only */ +START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq; + char data[] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create segments */ + /* pinseq is sent as last segment! */ + pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); + /* p1: 8 bytes before FIN */ + /* seqno: 8..16 */ + p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN); + /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ + /* seqno: 4..11 */ + p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); + /* p3: same as p2 but 2 bytes longer */ + /* seqno: 4..13 */ + p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK); + /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */ + /* seqno: 2..15 */ + p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK); + /* FIN, seqno 16 */ + p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN); + EXPECT(pinseq != NULL); + EXPECT(p_8_9 != NULL); + EXPECT(p_4_8 != NULL); + EXPECT(p_4_10 != NULL); + EXPECT(p_2_14 != NULL); + EXPECT(p_fin != NULL); + if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) { + /* pass the segment to tcp_input */ + test_tcp_input(p_8_9, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_4_8, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_4_10, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* ooseq queue: unchanged */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_2_14, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(p_fin, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* ooseq queue: unchanged */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ + + /* pass the segment to tcp_input */ + test_tcp_input(pinseq, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 1); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == data_len); + EXPECT(counters.err_calls == 0); + EXPECT(pcb->ooseq == NULL); + } + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} +END_TEST + + +/** create multiple segments and pass them to tcp_input in a wrong + * order to see if ooseq-caching works correctly + * FIN is received IN-SEQUENCE at the end */ +START_TEST(test_tcp_recv_ooseq_FIN_INSEQ) +{ + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN; + char data[] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + ip_addr_t remote_ip, local_ip, netmask; + u16_t data_len; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + LWIP_UNUSED_ARG(_i); + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + data_len = sizeof(data); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = data_len; + counters.expected_data = data; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + + /* create segments */ + /* p1: 7 bytes - 2 before FIN */ + /* seqno: 1..2 */ + p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK); + /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ + /* seqno: 4..11 */ + p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); + /* p3: same as p2 but 2 bytes longer and one byte more at the front */ + /* seqno: 3..13 */ + p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK); + /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */ + /* seqno: 2..13 */ + p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK); + /* pinseq is the first segment that is held back to create ooseq! */ + /* seqno: 0..3 */ + pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); + /* p5: last byte before FIN */ + /* seqno: 15 */ + p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); + /* p6: same as p5, should be ignored */ + p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); + /* pinseqFIN: last 2 bytes plus FIN */ + /* only segment containing seqno 14 and FIN */ + pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN); + EXPECT(pinseq != NULL); + EXPECT(p_1_2 != NULL); + EXPECT(p_4_8 != NULL); + EXPECT(p_3_11 != NULL); + EXPECT(p_2_12 != NULL); + EXPECT(p_15_1 != NULL); + EXPECT(p_15_1a != NULL); + EXPECT(pinseqFIN != NULL); + if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL) + && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) { + /* pass the segment to tcp_input */ + test_tcp_input(p_1_2, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); + + /* pass the segment to tcp_input */ + test_tcp_input(p_4_8, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8); + + /* pass the segment to tcp_input */ + test_tcp_input(p_3_11, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); + /* p_3_11 has removed p_4_8 from ooseq */ + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11); + + /* pass the segment to tcp_input */ + test_tcp_input(p_2_12, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12); + + /* pass the segment to tcp_input */ + test_tcp_input(pinseq, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == 14); + EXPECT(counters.err_calls == 0); + EXPECT(pcb->ooseq == NULL); + + /* pass the segment to tcp_input */ + test_tcp_input(p_15_1, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == 14); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); + + /* pass the segment to tcp_input */ + test_tcp_input(p_15_1a, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 1); + EXPECT(counters.recved_bytes == 14); + EXPECT(counters.err_calls == 0); + /* check ooseq queue: unchanged */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); + EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); + EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); + + /* pass the segment to tcp_input */ + test_tcp_input(pinseqFIN, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 1); + EXPECT(counters.recv_calls == 2); + EXPECT(counters.recved_bytes == data_len); + EXPECT(counters.err_calls == 0); + EXPECT(pcb->ooseq == NULL); + } + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} +END_TEST + +static char data_full_wnd[TCP_WND]; + +/** create multiple segments and pass them to tcp_input with the first segment missing + * to simulate overruning the rxwin with ooseq queueing enabled */ +START_TEST(test_tcp_recv_ooseq_overrun_rxwin) +{ +#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *pinseq, *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* create segments */ + /* pinseq is sent as last segment! */ + pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); + + for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { + int count, expected_datalen; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], + TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); + EXPECT_RET(p != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_count(pcb); + EXPECT_OOSEQ(count == k+1); + datalen = tcp_oos_tcplen(pcb); + if (i + TCP_MSS < TCP_WND) { + expected_datalen = (k+1)*TCP_MSS; + } else { + expected_datalen = TCP_WND - TCP_MSS; + } + if (datalen != expected_datalen) { + EXPECT_OOSEQ(datalen == expected_datalen); + } + } + + /* pass in one more segment, cleary overrunning the rxwin */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == k); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == datalen2); + + /* now pass inseq */ + test_tcp_input(pinseq, &netif); + EXPECT(pcb->ooseq == NULL); + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +START_TEST(test_tcp_recv_ooseq_max_bytes) +{ +#if TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ + + /* create segments and 'recv' them */ + for(k = 1, i = 1; k < TCP_OOSEQ_MAX_BYTES; k += TCP_MSS, i++) { + int count; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[k], + TCP_MSS, k, 0, TCP_ACK); + EXPECT_RET(p != NULL); + EXPECT_RET(p->next == NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_pbuf_count(pcb); + EXPECT_OOSEQ(count == i); + datalen = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == (i * TCP_MSS)); + } + + /* pass in one more segment, overrunning the limit */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[k+1], 1, k+1, 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue (ensure the new segment was not accepted) */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen2 == ((i-1) * TCP_MSS)); + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +#endif /* TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +START_TEST(test_tcp_recv_ooseq_max_pbufs) +{ +#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + int i; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_ovr; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + int datalen = 0; + int datalen2; + + for(i = 0; i < sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ + + /* create segments and 'recv' them */ + for(i = 1; i <= TCP_OOSEQ_MAX_PBUFS; i++) { + int count; + struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[i], + 1, i, 0, TCP_ACK); + EXPECT_RET(p != NULL); + EXPECT_RET(p->next == NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue */ + count = tcp_oos_pbuf_count(pcb); + EXPECT_OOSEQ(count == i); + datalen = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen == i); + } + + /* pass in one more segment, overrunning the limit */ + p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[i+1], 1, i+1, 0, TCP_ACK); + EXPECT_RET(p_ovr != NULL); + /* pass the segment to tcp_input */ + test_tcp_input(p_ovr, &netif); + /* check if counters are as expected */ + EXPECT(counters.close_calls == 0); + EXPECT(counters.recv_calls == 0); + EXPECT(counters.recved_bytes == 0); + EXPECT(counters.err_calls == 0); + /* check ooseq queue (ensure the new segment was not accepted) */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); + datalen2 = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(datalen2 == (i-1)); + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +#endif /* TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ + LWIP_UNUSED_ARG(_i); +} +END_TEST + +static void +check_rx_counters(struct tcp_pcb *pcb, struct test_tcp_counters *counters, u32_t exp_close_calls, u32_t exp_rx_calls, + u32_t exp_rx_bytes, u32_t exp_err_calls, int exp_oos_count, int exp_oos_len) +{ + int oos_len; + EXPECT(counters->close_calls == exp_close_calls); + EXPECT(counters->recv_calls == exp_rx_calls); + EXPECT(counters->recved_bytes == exp_rx_bytes); + EXPECT(counters->err_calls == exp_err_calls); + /* check that pbuf is queued in ooseq */ + EXPECT_OOSEQ(tcp_oos_count(pcb) == exp_oos_count); + oos_len = tcp_oos_tcplen(pcb); + EXPECT_OOSEQ(exp_oos_len == oos_len); +} + +/* this test uses 4 packets: + * - data (len=TCP_MSS) + * - FIN + * - data after FIN (len=1) (invalid) + * - 2nd FIN (invalid) + * + * the parameter 'delay_packet' is a bitmask that choses which on these packets is ooseq + */ +static void test_tcp_recv_ooseq_double_FINs(int delay_packet) +{ + int i, k; + struct test_tcp_counters counters; + struct tcp_pcb* pcb; + struct pbuf *p_normal_fin, *p_data_after_fin, *p, *p_2nd_fin_ooseq; + ip_addr_t remote_ip, local_ip, netmask; + u16_t remote_port = 0x100, local_port = 0x101; + struct netif netif; + u32_t exp_rx_calls = 0, exp_rx_bytes = 0, exp_close_calls = 0, exp_oos_pbufs = 0, exp_oos_tcplen = 0; + int first_dropped = 0xff; + int last_dropped = 0; + + for(i = 0; i < sizeof(data_full_wnd); i++) { + data_full_wnd[i] = (char)i; + } + + /* initialize local vars */ + memset(&netif, 0, sizeof(netif)); + IP4_ADDR(&local_ip, 192, 168, 1, 1); + IP4_ADDR(&remote_ip, 192, 168, 1, 2); + IP4_ADDR(&netmask, 255, 255, 255, 0); + test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); + /* initialize counter struct */ + memset(&counters, 0, sizeof(counters)); + counters.expected_data_len = TCP_WND; + counters.expected_data = data_full_wnd; + + /* create and initialize the pcb */ + pcb = test_tcp_new_counters_pcb(&counters); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); + pcb->rcv_nxt = 0x8000; + + /* create segments */ + p = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); + p_normal_fin = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS, 0, TCP_ACK|TCP_FIN); + k = 1; + p_data_after_fin = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS+1], k, TCP_MSS+1, 0, TCP_ACK); + p_2nd_fin_ooseq = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS+1+k, 0, TCP_ACK|TCP_FIN); + + if(delay_packet & 1) { + /* drop normal data */ + first_dropped = 1; + last_dropped = 1; + } else { + /* send normal data */ + test_tcp_input(p, &netif); + exp_rx_calls++; + exp_rx_bytes += TCP_MSS; + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 2) { + /* drop FIN */ + if(first_dropped > 2) { + first_dropped = 2; + } + last_dropped = 2; + } else { + /* send FIN */ + test_tcp_input(p_normal_fin, &netif); + if (first_dropped < 2) { + /* already dropped packets, this one is ooseq */ + exp_oos_pbufs++; + exp_oos_tcplen++; + } else { + /* inseq */ + exp_close_calls++; + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 4) { + /* drop data-after-FIN */ + if(first_dropped > 3) { + first_dropped = 3; + } + last_dropped = 3; + } else { + /* send data-after-FIN */ + test_tcp_input(p_data_after_fin, &netif); + if (first_dropped < 3) { + /* already dropped packets, this one is ooseq */ + if (delay_packet & 2) { + /* correct FIN was ooseq */ + exp_oos_pbufs++; + exp_oos_tcplen += k; + } + } else { + /* inseq: no change */ + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 8) { + /* drop 2nd-FIN */ + if(first_dropped > 4) { + first_dropped = 4; + } + last_dropped = 4; + } else { + /* send 2nd-FIN */ + test_tcp_input(p_2nd_fin_ooseq, &netif); + if (first_dropped < 3) { + /* already dropped packets, this one is ooseq */ + if (delay_packet & 2) { + /* correct FIN was ooseq */ + exp_oos_pbufs++; + exp_oos_tcplen++; + } + } else { + /* inseq: no change */ + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 1) { + /* dropped normal data before */ + test_tcp_input(p, &netif); + exp_rx_calls++; + exp_rx_bytes += TCP_MSS; + if((delay_packet & 2) == 0) { + /* normal FIN was NOT delayed */ + exp_close_calls++; + exp_oos_pbufs = exp_oos_tcplen = 0; + } + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 2) { + /* dropped normal FIN before */ + test_tcp_input(p_normal_fin, &netif); + exp_close_calls++; + exp_oos_pbufs = exp_oos_tcplen = 0; + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 4) { + /* dropped data-after-FIN before */ + test_tcp_input(p_data_after_fin, &netif); + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + if(delay_packet & 8) { + /* dropped 2nd-FIN before */ + test_tcp_input(p_2nd_fin_ooseq, &netif); + } + /* check if counters are as expected */ + check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); + + /* check that ooseq data has been dumped */ + EXPECT(pcb->ooseq == NULL); + + /* make sure the pcb is freed */ + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1); + tcp_abort(pcb); + EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0); +} + +/** create multiple segments and pass them to tcp_input with the first segment missing + * to simulate overruning the rxwin with ooseq queueing enabled */ +#define FIN_TEST(name, num) \ + START_TEST(name) \ + { \ + LWIP_UNUSED_ARG(_i); \ + test_tcp_recv_ooseq_double_FINs(num); \ + } \ + END_TEST +FIN_TEST(test_tcp_recv_ooseq_double_FIN_0, 0) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_1, 1) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_2, 2) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_3, 3) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_4, 4) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_5, 5) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_6, 6) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_7, 7) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_8, 8) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_9, 9) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_10, 10) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_11, 11) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_12, 12) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_13, 13) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_14, 14) +FIN_TEST(test_tcp_recv_ooseq_double_FIN_15, 15) + + +/** Create the suite including all tests for this module */ +Suite * +tcp_oos_suite(void) +{ + TFun tests[] = { + test_tcp_recv_ooseq_FIN_OOSEQ, + test_tcp_recv_ooseq_FIN_INSEQ, + test_tcp_recv_ooseq_overrun_rxwin, + test_tcp_recv_ooseq_max_bytes, + test_tcp_recv_ooseq_max_pbufs, + test_tcp_recv_ooseq_double_FIN_0, + test_tcp_recv_ooseq_double_FIN_1, + test_tcp_recv_ooseq_double_FIN_2, + test_tcp_recv_ooseq_double_FIN_3, + test_tcp_recv_ooseq_double_FIN_4, + test_tcp_recv_ooseq_double_FIN_5, + test_tcp_recv_ooseq_double_FIN_6, + test_tcp_recv_ooseq_double_FIN_7, + test_tcp_recv_ooseq_double_FIN_8, + test_tcp_recv_ooseq_double_FIN_9, + test_tcp_recv_ooseq_double_FIN_10, + test_tcp_recv_ooseq_double_FIN_11, + test_tcp_recv_ooseq_double_FIN_12, + test_tcp_recv_ooseq_double_FIN_13, + test_tcp_recv_ooseq_double_FIN_14, + test_tcp_recv_ooseq_double_FIN_15 + }; + return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown); +} diff --git a/Shared/lwip/test/unit/tcp/test_tcp_oos.h b/Shared/lwip/test/unit/tcp/test_tcp_oos.h new file mode 100644 index 0000000..5e411f0 --- /dev/null +++ b/Shared/lwip/test/unit/tcp/test_tcp_oos.h @@ -0,0 +1,8 @@ +#ifndef __TEST_TCP_OOS_H__ +#define __TEST_TCP_OOS_H__ + +#include "../lwip_check.h" + +Suite *tcp_oos_suite(void); + +#endif diff --git a/Shared/lwip/test/unit/udp/test_udp.c b/Shared/lwip/test/unit/udp/test_udp.c new file mode 100644 index 0000000..a2f02af --- /dev/null +++ b/Shared/lwip/test/unit/udp/test_udp.c @@ -0,0 +1,68 @@ +#include "test_udp.h" + +#include "lwip/udp.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS +#error "This tests needs UDP- and MEMP-statistics enabled" +#endif + +/* Helper functions */ +static void +udp_remove_all(void) +{ + struct udp_pcb *pcb = udp_pcbs; + struct udp_pcb *pcb2; + + while(pcb != NULL) { + pcb2 = pcb; + pcb = pcb->next; + udp_remove(pcb2); + } + fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0); +} + +/* Setups/teardown functions */ + +static void +udp_setup(void) +{ + udp_remove_all(); +} + +static void +udp_teardown(void) +{ + udp_remove_all(); +} + + +/* Test functions */ + +START_TEST(test_udp_new_remove) +{ + struct udp_pcb* pcb; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0); + + pcb = udp_new(); + fail_unless(pcb != NULL); + if (pcb != NULL) { + fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 1); + udp_remove(pcb); + fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0); + } +} +END_TEST + + +/** Create the suite including all tests for this module */ +Suite * +udp_suite(void) +{ + TFun tests[] = { + test_udp_new_remove, + }; + return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown); +} diff --git a/Shared/lwip/test/unit/udp/test_udp.h b/Shared/lwip/test/unit/udp/test_udp.h new file mode 100644 index 0000000..9335368 --- /dev/null +++ b/Shared/lwip/test/unit/udp/test_udp.h @@ -0,0 +1,8 @@ +#ifndef __TEST_UDP_H__ +#define __TEST_UDP_H__ + +#include "../lwip_check.h" + +Suite* udp_suite(void); + +#endif diff --git a/Shared/proxy/tun/HTTPProxyServer.h b/Shared/proxy/tun/HTTPProxyServer.h new file mode 100644 index 0000000..0457ddd --- /dev/null +++ b/Shared/proxy/tun/HTTPProxyServer.h @@ -0,0 +1,17 @@ +// +// HTTPProxyServer.h +// Surf +// +// Created by 孔祥波 on 16/5/20. +// Copyright © 2016年 yarshure. All rights reserved. +// + +#ifndef HTTPProxyServer_h +#define HTTPProxyServer_h + +#include +int startserver(int any); +void stopserver(void); +typedef struct ecb *ECBRef; + +#endif /* HTTPProxyServer_h */ diff --git a/Shared/proxy/tun/HTTPProxyServer.m b/Shared/proxy/tun/HTTPProxyServer.m new file mode 100644 index 0000000..3888e6e --- /dev/null +++ b/Shared/proxy/tun/HTTPProxyServer.m @@ -0,0 +1,367 @@ +// +// HTTPProxyServer.c +// Surf +// +// Created by 孔祥波 on 16/5/20. +// Copyright © 2016年 yarshure. All rights reserved. +// + +#include "HTTPProxyServer.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#import +//#import "PacketTunnel-Swift.h" +typedef struct in_addr in_addr; +typedef struct sockaddr_in sockaddr_in; +typedef struct servent servent; +typedef struct timespec timespec; + +typedef void (action) (register struct kevent const *const kep); + +/* Event Control Block (ecb) */ +typedef struct { + action *do_read; + action *do_write; + void *client; + char *buf; + unsigned bufsiz; +} ecb; + +static char const *pname; +static struct kevent *ke_vec = NULL; +static unsigned ke_vec_alloc = 0; +static unsigned ke_vec_used = 0; +static char const protoname[] = "tcp"; +static char const servname[] = "ndl-aas"; + +static void +vlog (char const *const fmt, va_list ap) +{ + vfprintf (stderr, fmt, ap); + fputc ('\n', stderr); +} + +static void fatal (char const *const fmt, ...) +__attribute__ ((__noreturn__)); + +static void +fatal (char const *const fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + fprintf (stderr, "%s: ", pname); + vlog (fmt, ap); + va_end (ap); + exit (1); +} + +static void +error (char const *const fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + fprintf (stderr, "%s: ", pname); + vlog (fmt, ap); + va_end (ap); +} + + + +//static int +//all_digits (register char const *const s) +//{ +// register char const *r; +// +// for (r = s; *r; r++) +// if (!isdigit (*r)) +// return 0; +// return 1; +//} + +static void * +xmalloc (register unsigned long const size) +{ + register void *const result = malloc (size); + + if (!result) + NSLog(@"Memory exhausted"); + return result; +} + +static void * +xrealloc (register void *const ptr, register unsigned long const size) +{ + register void *const result = realloc (ptr, size); + + if (!result) + fatal ("Memory exhausted"); + return result; +} + +static void +ke_change (register int const ident, + register int const filter, + register int const flags, + register void *const udata) +{ + enum { initial_alloc = 64 }; + register struct kevent *kep; + + if (!ke_vec_alloc) + { + ke_vec_alloc = initial_alloc; + ke_vec = (struct kevent *) xmalloc(ke_vec_alloc * sizeof (struct kevent)); + } + else if (ke_vec_used == ke_vec_alloc) + { + ke_vec_alloc <<= 1; + ke_vec = + (struct kevent *) xrealloc (ke_vec, + ke_vec_alloc * sizeof (struct kevent)); + } + + kep = &ke_vec[ke_vec_used++]; + + kep->ident = ident; + kep->filter = filter; + kep->flags = flags; + kep->fflags = 0; + kep->data = 0; + kep->udata = udata; +} + +static void +do_write (register struct kevent const *const kep) +{ + register int n; + register ecb *const ecbp = (ecb *) kep->udata; + if (ecbp->client != nil){ + +// SFHTTPSocketConnection *c = (__bridge_transfer SFHTTPSConnection*)ecbp->client; +// if ([c shouldCoseSocket]){ +// error ("Error writing socket: %s", strerror (errno)); +// close ((int)kep->ident); +// ecbp->client = nil; +// free (kep->udata); +// return; +// } + + //NSData *d = c.socks_recv_bufArray; + if (0) { //d.length > 0 +// n = write ((size_t)kep->ident, d.bytes, d.length); +// //free (ecbp->buf); /* Free this buffer, no matter what. */ +// // maybe write failure? +// if (n == -1) +// { +// error ("Error writing socket: %s", strerror (errno)); +// close ((int)kep->ident); +// ecbp->client = nil; +// free (kep->udata); +// }else if (n == d.length){ +// NSRange r = NSMakeRange(n, d.length-n); +// c.socks_recv_bufArray = [NSMutableData dataWithData:[d subdataWithRange:r]]; +// ke_change ((int)kep->ident, EVFILT_WRITE, EV_DISABLE, kep->udata); +// ke_change ((int)kep->ident, EVFILT_READ, EV_ENABLE, kep->udata); +// } + }else { + + } + + + //ecbp->client = (__bridge void*)c; + //[c ] + }else { + + error ("Error writing socket: %s", strerror (errno)); + close ((int)kep->ident); + + free (kep->udata); + } + + + +} + +static void +do_read (register struct kevent const *const kep) +{ + enum { bufsize = 1024 }; + auto char buf[bufsize]; + register int n; + register ecb *const ecbp = (ecb *) kep->udata; + if (ecbp->client != nil){ + if ((n = read (kep->ident, buf, bufsize)) == -1) + { + error ("Error reading socket: %s", strerror (errno)); + close ((int)kep->ident); + ecbp->client = nil; + free (kep->udata); + }else if (n == 0) + { + error ("EOF reading socket"); + + close ((int)kep->ident); + ecbp->client = nil; + free (kep->udata); + }else { +// ecbp->buf = (char *) xmalloc (1); +// free(ecbp->buf); +// NSData * d = [NSData dataWithBytesNoCopy:buf length:n]; +// SFHTTPSocketConnection *c = (__bridge_transfer SFHTTPSocketConnection*)ecbp->client; +// [c incomingData:d len:d.length]; + } + + + //ecbp->client = (__bridge void*)c; + //[c ] + }else { + error ("client dead "); + close ((int)kep->ident); + free (kep->udata); + } + + + + //ecbp->bufsiz = n; + //memcpy (ecbp->buf, buf, n); + + + ke_change ((int)kep->ident, EVFILT_READ, EV_DISABLE, kep->udata); + ke_change ((int)kep->ident, EVFILT_WRITE, EV_ENABLE, kep->udata); +} + +static void +do_accept (register struct kevent const *const kep) +{ + _exit(0); +// auto sockaddr_in sin; +// auto socklen_t sinsiz; +// register int s; +// register ecb *ecbp; +// +// if ((s = accept ((int)kep->ident, (struct sockaddr *)&sin, &sinsiz)) == -1) +// fatal ("Error in accept(): %s", strerror (errno)); +// +// ecbp = (ecb *) xmalloc (sizeof (ecb)); +// if (ecbp->client == nil){ +// SFHTTPSocketConnection *c = [[SFHTTPSocketConnection alloc] init]; +// //ecbp->client = (__bridge void*)c; +// [[SFTCPConnectionManager shared] addSocketConnection:c]; +// ecbp->client = (__bridge_retained void*)c; +// } +// ecbp->do_read = do_read; +// ecbp->do_write = do_write; +// ecbp->buf = NULL; +// ecbp->bufsiz = 0; +// +// ke_change (s, EVFILT_READ, EV_ADD | EV_ENABLE, ecbp); +// ke_change (s, EVFILT_WRITE, EV_ADD | EV_DISABLE, ecbp); +} + +static void event_loop (register int const kq) +__attribute__ ((__noreturn__)); + +static void +event_loop (register int const kq) +{ + for (;;) + { + register int n; + register struct kevent const *kep; + + n = kevent (kq, ke_vec, ke_vec_used, ke_vec, ke_vec_alloc, NULL); + ke_vec_used = 0; /* Already processed all changes. */ + + if (n == -1) + fatal ("Error in kevent(): %s", strerror (errno)); + if (n == 0) + fatal ("No events received!"); + + for (kep = ke_vec; kep < &ke_vec[n]; kep++) + { + register ecb const *const ecbp = (ecb *) kep->udata; + + if (kep->filter == EVFILT_READ) + (*ecbp->do_read) (kep); + else + (*ecbp->do_write) (kep); + } + } +} +void stopserver() +{ + +} +int startserver(int any) +{ + auto in_addr listen_addr; + + auto int one = 1; + register int portno = 0; + + register int server_sock; + auto sockaddr_in sin; + register servent *servp; + auto ecb listen_ecb; + register int kq; + + if (any==0) { + listen_addr.s_addr = htonl (INADDR_LOOPBACK); /* Default. */ + }else { + listen_addr.s_addr = htonl (INADDR_ANY); /* Default. */ + } + + + if (portno == 0) + { + if ((servp = getservbyname (servname, protoname)) == NULL) + fatal ("Error getting port number for service `%s': %s", + servname, strerror (errno)); + portno = ntohs (servp->s_port); + } + + if ((server_sock = socket (PF_INET, SOCK_STREAM, 0)) == -1) + fatal ("Error creating socket: %s", strerror (errno)); + + if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) == -1) + fatal ("Error setting SO_REUSEADDR for socket: %s", strerror (errno)); + + memset (&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr = listen_addr; + sin.sin_port = htons (portno); + + if (bind (server_sock, (const struct sockaddr *)&sin, sizeof sin) == -1) + fatal ("Error binding socket: %s", strerror (errno)); + + if (listen (server_sock, 15) == -1) + fatal ("Error listening to socket: %s", strerror (errno)); + + if ((kq = kqueue ()) == -1) + fatal ("Error creating kqueue: %s", strerror (errno)); + + listen_ecb.do_read = do_accept; + listen_ecb.do_write = NULL; + listen_ecb.buf = NULL; + listen_ecb.bufsiz = 0; + + ke_change (server_sock, EVFILT_READ, EV_ADD | EV_ENABLE, &listen_ecb); + + event_loop (kq); +} diff --git a/Shared/proxy/tun/SFAppExtension.swift b/Shared/proxy/tun/SFAppExtension.swift new file mode 100644 index 0000000..c2191b1 --- /dev/null +++ b/Shared/proxy/tun/SFAppExtension.swift @@ -0,0 +1,208 @@ +// +// SFAppExtension.swift +// Surf +// +// Created by 孔祥波 on 8/2/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import Foundation +#if os(iOS) +import UIKit + +#else +import Cocoa + +#endif +import SFSocket +import XProxy +import XRuler +//这个extension for main app的 +extension SFRequestInfo { + func detailString() ->NSAttributedString { + + + var t:String = ""// self.dataDesc(sTime) + var agent:String + + + if self.mode == .TCP{ + agent = "RAW" + }else { + + agent = "\(SFAppIden.shared.appDesc(agent: self.app))" + if let resp = respHeader { + t = "Status: " + String(resp.sCode) + } + } + + var modeString:String = " " + self.mode.description + " " + if self.mode == .HTTP { + if let req = reqHeader { + modeString = " " + req.method.rawValue + " " + }else { + modeString = " " + self.mode.description + " " + } + + + + + } + let rule = self.rule + + // var color:UIColor = UIColor.blackColor() + // if rule.policy == .Reject { + // color = UIColor.redColor() + // }else if rule.policy == .Proxy { + // color = UIColor.greenColor() + // } + let p = rule.policyString() + var x:String + if t.isEmpty { + x = modeString + " " + agent + " \(rule.policyString()) " + self.status.description + " remote " + self.remoteIPaddress + }else { + x = modeString + " " + agent + " " + "\(t) \(rule.policyString()) " + self.status.description + " remote " + self.remoteIPaddress + } + + let s = NSMutableAttributedString(string:x ) + var r = (x as NSString).range(of: p) + //let range = NSMakeRange(r?.startIndex, ) + + + #if os (iOS) + var color:UIColor = UIColor.orange + if rule.policy == .Reject { + color = UIColor.red + }else if rule.policy == .Proxy { + color = UIColor.green + } + + let ra = (x as NSString).range(of: agent) + s.addAttributes([NSAttributedStringKey.backgroundColor:UIColor.red,NSAttributedStringKey.foregroundColor:UIColor.white], range: ra) + + s.addAttributes([NSAttributedStringKey.foregroundColor:color], range: r) + + r = (x as NSString).range(of: modeString) + + s.addAttributes([NSAttributedStringKey.foregroundColor:UIColor.white,NSAttributedStringKey.backgroundColor:UIColor.blue], range: r) + if !t.isEmpty{ + let scode = UIColor.init(red: 0.36, green: 0.65, blue: 0.76, alpha: 1.0) + let srange = (x as NSString).range(of: t) + s.addAttributes([NSAttributedStringKey.foregroundColor:scode], range: srange) + } + + #else + var color:NSColor = NSColor.orange + if rule.policy == .Reject { + color = NSColor.red + }else if rule.policy == .Proxy { + color = NSColor.green + } + + + s.addAttributes([NSAttributedStringKey.foregroundColor:color], range: r) + + r = (x as NSString).range(of: modeString) + + s.addAttributes([NSAttributedStringKey.foregroundColor:NSColor.white,NSAttributedStringKey.backgroundColor:NSColor.blue], range: r) + #endif + return s + + + + } +} +extension SFConfig{ + func writeConfig(name:String,copy:Bool, force:Bool,shareiTunes:Bool) -> SFConfigWriteError { + // copy ,true to groupdir,false save to iTunes share or stand save + // + if configName.isEmpty { + return .noName + } + let storageURL = SFConfigManager.manager.storageURL + if name != configName { + //copy or changed configName + if !copy { + //delete old + let temp = storageURL.appendingPathComponent(configName + configExt) + do { + try fm.removeItem(at: temp) + }catch let e as NSError{ + print("error :\(e.localizedDescription)") + } + }else { + //copy + + } + }else { + //相等就是直接写 + } + //guard let doc = applicationDocumentsDirectory else {return .Other} + var destURL:URL + + if copy { + destURL = storageURL.appendingPathComponent (name + configExt) + }else { + if name.isEmpty { + //stand save + destURL = storageURL.appendingPathComponent (configName + configExt) + }else { + if name == configName { + destURL = storageURL.appendingPathComponent (configName + configExt) + }else { + + destURL = storageURL.appendingPathComponent (name + configExt) + if configName != "surf" { + let temp = storageURL.appendingPathComponent (configName + configExt) + do { + try fm.removeItem(atPath: temp.path) + } catch let e as NSError { + print(e) + } + } + + + } + + } + } + //configName = name + + let data = genData() + + + if force { + if fm.fileExists(atPath: destURL.path){ + try! fm.removeItem(at: destURL) + } + try! data.write(to: destURL, atomically: true,encoding:String.Encoding.utf8) + //这里写也没什么太大问题 + let groupURL = groupContainerURL().appendingPathComponent (name + configExt) + + if fm.fileExists(atPath: groupURL.path) { + try! fm.removeItem(at: groupURL) + } + try! fm.copyItem(at: destURL, to:groupURL ) + }else { + if fm.fileExists(atPath: destURL.path){ + return .exist + }else { + try! data.write(to: destURL, atomically: true,encoding:String.Encoding.utf8) + } + } + + if shareiTunes { + destURL = applicationDocumentsDirectory.appendingPathComponent (name + configExt) + try! data.write(to: destURL, atomically: true,encoding:String.Encoding.utf8) + // do{ + // try + // }catch _{ + // + // } + + } + + + return .success + } +} diff --git a/Shared/proxy/tun/SFAppIden.swift b/Shared/proxy/tun/SFAppIden.swift new file mode 100644 index 0000000..d750ade --- /dev/null +++ b/Shared/proxy/tun/SFAppIden.swift @@ -0,0 +1,78 @@ +// +// SFAppIden.swift +// Surf +// +// Created by abigt on 16/2/15. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation + +class SFAppIden { + static let shared:SFAppIden = SFAppIden() + var agents:[String:String] = [:] + init() { + let url = applicationDocumentsDirectory.appendingPathComponent(agentsFile) + var info:NSDictionary + if fm.fileExists(atPath:url.path) { + info = NSDictionary.init(contentsOf: url)! + + }else { + let u = Bundle.main.path(forResource:agentsFile, ofType: nil)//applicationDocumentsDirectory.appendingPathComponent(agentsFile) + if fm.fileExists(atPath:u!) { + info = NSDictionary.init(contentsOfFile: u!)! + + }else { + info = NSDictionary() + } + } + + for (key,value) in info { + agents[key as! String] = value as? String + } + } + func appDesc(agent:String) ->String{ + //chrome "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2_1 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/48.0.2564.104 Mobile/13D15 Safari/601.1.46" + //Dictionary + for (k,v) in agents { + if agent.range(of: k) != nil { + return v + } + } + + var list = agent.components(separatedBy: "/") + var result:String + if list.count > 1 { + if let a = list.first { + result = a.removingPercentEncoding! + }else { + result = agent.removingPercentEncoding! + } + + }else { + list = agent.components(separatedBy: " ") + if list.count > 0 { + if let a = list.first { + result = a.removingPercentEncoding! + }else { + result = agent.removingPercentEncoding! + } + + }else { + result = agent.removingPercentEncoding! + } + + } + agents[agent] = result + save() + return result + } + func save(){ + let info = NSMutableDictionary() + for (k,v) in agents { + info.setObject(v, forKey: k as NSCopying) + } + let p = applicationDocumentsDirectory.appendingPathComponent(agentsFile) + info.write(to: p, atomically: true) + } +} diff --git a/Shared/proxy/tun/StackHelper.h b/Shared/proxy/tun/StackHelper.h new file mode 100644 index 0000000..507f11d --- /dev/null +++ b/Shared/proxy/tun/StackHelper.h @@ -0,0 +1,60 @@ +// +// StackHelper.h +// Surf +// +// Created by abigt on 15/12/25. +// Copyright © 2015年 abigt. All rights reserved. +// + +#ifndef StackHelper_h +#define StackHelper_h +//#import "lwip/tcp.h" +#include + + +//#include "init.h" +//#include "timers.h" +#import +//#import "sodium.h" + +#import +#include +#include +#include +//#include +//#include "udp.h" +//#include "ip_addr.h" +#ifdef DEBUG +# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +//NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#else +# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); + +//# define DLog(...) +//# define SLog(...) +#endif + +// ALog always displays output regardless of the DEBUG setting +#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); + + +void installSignalHandler(NSString *d); + +void crashSignalHandler(int signal); + +int int2ip(uint32_t ip,char *p); +void lwiplog(const char *fmt, ...); +NSString* objectClassString(id obj); +#define SLog(fmt, ...) testLog(("%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);; +#define FLog(fmt, ...) testLog( @__FILE__,__LINE__,(" " fmt), ##__VA_ARGS__); +void testLog(NSString *f, int line,char *format,...); +void surfLog(char *string,NSString *file,NSInteger line); + +NSString *kernelVersion(void); +NSString *hwVersion(void); +void lwiplog (const char *fmt, ...); +uint64_t reportMemoryUsed(void); + +//CCAlgorithm findCCAlgorithm(int index); +BOOL memoryIssue(void); +#endif /* StackHelper_h */ diff --git a/Shared/proxy/tun/StackHelper.m b/Shared/proxy/tun/StackHelper.m new file mode 100644 index 0000000..79b3fe4 --- /dev/null +++ b/Shared/proxy/tun/StackHelper.m @@ -0,0 +1,194 @@ +// +// StackHelper.c +// Surf +// +// Created by abigt on 15/12/25. +// Copyright © 2015年 abigt. All rights reserved. +// + +#import +#include "StackHelper.h" +#include "SFUtil.h" +//#include "lwipopts.h" + +#include +//#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) +//#else +//#end +#if TARGET_OS_IPHONE +// +////#import "PacketTunnel/Mac/PacketTunnel_Mac-Swift.h" +//#import "PacketTunnel-Swift.h" +#import "PacketTunnel_iOS-Swift.h" +//#endif +//#if TARGET_OS_MAC +#else +#import "PacketTunnel_Mac-Swift.h" +//#import "TunServerUI-Swift.h" +#endif +#import +#include +#include +#include +#include +#include + + + + + + + + + +//#import + + +void crashSignalHandler(int signal) +{ + //let c = FileManager.default.containerURLForSecurityApplicationGroupIdentifier("group.com.abigt.Surf") + //urlContain = c!.appendingPathComponent("Log") + //SFVPNSession *s = [sf session]; + + //NSString *name = @"abc";// s.idenString; + NSString *d = @""; + NSString *fileName = [NSString stringWithFormat:@"Log/%@/crash.log",d]; + NSURL *c = [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.abigt.Surf"] URLByAppendingPathComponent:fileName]; + + const char* fileNameCString = [[c path] cStringUsingEncoding:NSUTF8StringEncoding]; + FILE* crashFile = fopen(fileNameCString, "w"); + int crashLogFileDescriptor = crashFile->_file; + void* callstack[128]; + int frames = backtrace(callstack, 128); + backtrace_symbols_fd(callstack, frames, crashLogFileDescriptor); + char **strs = backtrace_symbols(callstack, frames); + for (int i = 0; i< frames; i++) { + NSString *str =[NSString stringWithUTF8String:strs[i]]; + DLog(@"######%@",str); + } + exit(signal); +} + +void installSignalHandler(NSString *d) +{ + //NSSetUncaughtExceptionHandler(&HandleException); + // learning + //http://www.cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html + //http://devmonologue.com/ios/ios/implementing-crash-reporting-for-ios/ +//#ifdef DEBUG + //signal(SIGABRT, crashSignalHandler); + //signal(SIGSEGV, crashSignalHandler); + //signal(SIGBUS, crashSignalHandler); + //signal(SIGKILL, crashSignalHandler); + signal(SIGSYS, crashSignalHandler); + //signal(SIGTERM, crashSignalHandler); + signal(SIGSTOP, crashSignalHandler); + signal(SIGTSTP, crashSignalHandler); + signal(SIGXCPU, crashSignalHandler); + signal(SIGXFSZ, crashSignalHandler); + //signal(SIGILL, crashSignalHandler); + //signal(SIGFPE, crashSignalHandler); + //signal(SIGPIPE, crashSignalHandler); + signal(SIGTRAP, crashSignalHandler); + + signal(SIGABRT, crashSignalHandler); + signal(SIGILL, crashSignalHandler); + signal(SIGSEGV, crashSignalHandler); + signal(SIGFPE, crashSignalHandler); + signal(SIGBUS, crashSignalHandler); + signal(SIGPIPE, crashSignalHandler); + signal(SIGHUP, SIG_IGN); + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, + SIGHUP, 0, queue); + if (source) { + dispatch_source_set_event_handler(source, ^{ + crashSignalHandler(0); + }); + // Start processing signals + dispatch_resume(source); + } +// signal(SIGABRT, SIG_DFL); +// signal(SIGSEGV, SIG_DFL); +// signal(SIGBUS, SIG_DFL); +//#endif +} + +void lwipassertlog(const char *fmt, ...) +{ +//#ifdef DEBUG + va_list arg_ptr; + va_start(arg_ptr, fmt); + char content[256]; + vsnprintf(content, 256, fmt, arg_ptr); + va_end(arg_ptr); + //surfLog(content, , 0); + //[AxLogger log:[NSString stringWithFormat:@"%s",content] level:AxLoggerLevelInfo category:@"cfunc" file:@__FILE__ line:__LINE__ ud:@{@"test":@"test"} tags:@[@"test"] time:[NSDate date]]; + NSLog(@"%s",content); +//#endif +} + + +NSString* objectClassString(id obj) +{ + NSString *s = NSStringFromClass([obj class]); + NSArray *array = [s componentsSeparatedByString:@"."]; + return array.lastObject; +} + +#include +#include +NSString *kernelVersion(){ + + + char str[256]; + size_t size = sizeof(str); + int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0); + if (ret == 0) { + return [NSString stringWithCString:str encoding:NSUTF8StringEncoding]; + } + return @""; + +} +NSString *hwVersion(){ + + + char str[256]; + size_t size = sizeof(str); + int ret = sysctlbyname("hw.machine", str, &size, NULL, 0); + if (ret == 0) { + return [NSString stringWithCString:str encoding:NSUTF8StringEncoding]; + } + return @""; + +} +uint64_t reportMemoryUsed() +{ + task_vm_info_data_t vmInfo; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + kern_return_t err = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count); + if (err == KERN_SUCCESS){ + uint64_t size = vmInfo.internal + vmInfo.compressed - vmInfo.purgeable_volatile_pmap; + //NSLog(@"current memory use %llu",sizt); + return size; + }else { + return 0; + //NSLog(@"error %d",err); + } + //return static_cast(-1); + +} + +/* + sodium +*/ + + +BOOL memoryIssue() +{ + NSInteger major = [[NSProcessInfo processInfo] operatingSystemVersion].majorVersion; + if (major < 10) { + return YES; + } + return NO; +} diff --git a/Shared/proxy/tun/TCPPcbWrap.h b/Shared/proxy/tun/TCPPcbWrap.h new file mode 100644 index 0000000..da17355 --- /dev/null +++ b/Shared/proxy/tun/TCPPcbWrap.h @@ -0,0 +1,17 @@ +// +// TCPPcbWrap.h +// Surf +// +// Created by yarshure on 16/3/17. +// Copyright © 2016年 yarshure. All rights reserved. +// + + +#import +#import "lwip/tcp.h" +#import "StackHelper.h" +@interface TCPPcbWrap : NSObject + ++ (enum tcp_state) pcbStatus:(SFPcb)pcb; +@end +//pcb->state \ No newline at end of file diff --git a/Shared/proxy/tun/TCPPcbWrap.m b/Shared/proxy/tun/TCPPcbWrap.m new file mode 100644 index 0000000..f48803e --- /dev/null +++ b/Shared/proxy/tun/TCPPcbWrap.m @@ -0,0 +1,40 @@ +// +// TCPPcbWrap.m +// Surf +// +// Created by yarshure on 16/3/17. +// Copyright © 2016年 yarshure. All rights reserved. +// +//const char * const tcp_state_str[] = { +// "CLOSED", +// "LISTEN", +// "SYN_SENT", +// "SYN_RCVD", +// "ESTABLISHED", +// "FIN_WAIT_1", +// "FIN_WAIT_2", +// "CLOSE_WAIT", +// "CLOSING", +// "LAST_ACK", +// "TIME_WAIT" +//}; +//enum tcp_state { +// CLOSED = 0, +// LISTEN = 1, +// SYN_SENT = 2, +// SYN_RCVD = 3, +// ESTABLISHED = 4, +// FIN_WAIT_1 = 5, +// FIN_WAIT_2 = 6, +// CLOSE_WAIT = 7, +// CLOSING = 8, +// LAST_ACK = 9, +// TIME_WAIT = 10 +//}; +#import "TCPPcbWrap.h" + +@implementation TCPPcbWrap ++ (enum tcp_state) pcbStatus:(SFPcb)pcb{ + return pcb ->state; +} +@end diff --git a/Shared/proxy/tun/useragents.plist b/Shared/proxy/tun/useragents.plist new file mode 100644 index 0000000..7cda869 --- /dev/null +++ b/Shared/proxy/tun/useragents.plist @@ -0,0 +1,34 @@ + + + + + FBAN/FBIOS + FaceBook + MicroMessenger Client - 2 + WeChat + Twitter for iPhone + Twitter + Twitter-iPhone + Twitter + CriOS + Chrome + Safari + Safari + Instagram + Instagram + Connect + iTunes Connect + AppStore + App Store + Oasis + TestFlight + com.google.ios.youtube + youtube + 网易云音乐 + 网易云音乐 + 京东 + 京东 + iOS WJLoginSDK + 京东 + + diff --git a/Shared/ruler/ISO_3166.txt b/Shared/ruler/ISO_3166.txt new file mode 100644 index 0000000..a34be9e --- /dev/null +++ b/Shared/ruler/ISO_3166.txt @@ -0,0 +1,249 @@ +CN +AD +AE +AF +AG +AI +AL +AM +AO +AQ +AR +AS +AT +AU +AW +AX +AZ +BA +BB +BD +BE +BF +BG +BH +BI +BJ +BL +BM +BN +BO +BQ +BR +BS +BT +BV +BW +BY +BZ +CA +CC +CD +CF +CG +CH +CI +CK +CL +CM +CO +CR +CU +CV +CW +CX +CY +CZ +DE +DJ +DK +DM +DO +DZ +EC +EE +EG +EH +ER +ES +ET +FI +FJ +FK +FM +FO +FR +GA +GB +GD +GE +GF +GG +GH +GI +GL +GM +GN +GP +GQ +GR +GS +GT +GU +GW +GY +HK +HM +HN +HR +HT +HU +ID +IE +IL +IM +IN +IO +IQ +IR +IS +IT +JE +JM +JO +JP +KE +KG +KH +KI +KM +KN +KP +KR +KW +KY +KZ +LA +LB +LC +LI +LK +LR +LS +LT +LU +LV +LY +MA +MC +MD +ME +MF +MG +MH +MK +ML +MM +MN +MO +MP +MQ +MR +MS +MT +MU +MV +MW +MX +MY +MZ +NA +NC +NE +NF +NG +NI +NL +NO +NP +NR +NU +NZ +OM +PA +PE +PF +PG +PH +PK +PL +PM +PN +PR +PS +PT +PW +PY +QA +RE +RO +RS +RU +RW +SA +SB +SC +SD +SE +SG +SH +SI +SJ +SK +SL +SM +SN +SO +SR +SS +ST +SV +SX +SY +SZ +TC +TD +TF +TG +TH +TJ +TK +TL +TM +TN +TO +TR +TT +TV +TW +TZ +UA +UG +UM +US +UY +UZ +VA +VC +VE +VG +VI +VN +VU +WF +WS +YE +YT +ZA +ZM +ZW \ No newline at end of file diff --git a/Surf-Mac/A_BIG_T-Bridging-Header.h b/Surf-Mac/A_BIG_T-Bridging-Header.h new file mode 100644 index 0000000..33be81e --- /dev/null +++ b/Surf-Mac/A_BIG_T-Bridging-Header.h @@ -0,0 +1,28 @@ +// +// Surf-Bridging-Header.h +// Surf +// +// Created by abigt on 15/12/7. +// Copyright © 2015年 abigt. All rights reserved. +// + +#ifndef Surf_Bridging_Header_h +#define Surf_Bridging_Header_h +//#import "ylog.h" + +#include + +# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#ifdef DEBUG + +//NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#else +//# define DLog(...) +//# define SLog(...) +#endif + +// ALog always displays output regardless of the DEBUG setting +#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#import +#import +#endif /* Surf_Bridging_Header_h */ diff --git a/Surf-Mac/About.xib b/Surf-Mac/About.xib new file mode 100644 index 0000000..78734ce --- /dev/null +++ b/Surf-Mac/About.xib @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/AboutWindowController.swift b/Surf-Mac/AboutWindowController.swift new file mode 100644 index 0000000..45f97a1 --- /dev/null +++ b/Surf-Mac/AboutWindowController.swift @@ -0,0 +1,19 @@ +// +// AboutWindowController.swift +// Surf +// +// Created by 孔祥波 on 05/12/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa + +class AboutWindowController: NSWindowController { + + override func windowDidLoad() { + super.windowDidLoad() + + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + +} diff --git a/Surf-Mac/AdvancedWindowController.swift b/Surf-Mac/AdvancedWindowController.swift new file mode 100644 index 0000000..49c572c --- /dev/null +++ b/Surf-Mac/AdvancedWindowController.swift @@ -0,0 +1,77 @@ +// +// AdvancedWindowController.swift +// Surf +// +// Created by abigt on 2016/11/22. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Cocoa +import SFSocket +import XRuler +class AdvancedWindowController: NSWindowController { + + @IBOutlet weak var historyButton:NSButton! + @IBOutlet weak var flagButton:NSButton! + @IBOutlet weak var iCloudButton:NSButton! + override func windowDidLoad() { + super.windowDidLoad() + if ProxyGroupSettings.share.showCountry { + flagButton.state = NSControl.StateValue(rawValue: 1) + }else { + flagButton.state = NSControl.StateValue(rawValue: 0) + } + if ProxyGroupSettings.share.historyEnable { + historyButton.state = NSControl.StateValue(rawValue: 1) + }else { + historyButton.state = NSControl.StateValue(rawValue: 0) + } + if ProxyGroupSettings.share.iCloudSyncEnabled(){ + iCloudButton.state = NSControl.StateValue(rawValue: 1) + }else { + iCloudButton.state = NSControl.StateValue(rawValue: 0) + } + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + func alertMesage(_ msg:String){ + let alert = NSAlert.init() + alert.addButton(withTitle: "OK") + + alert.messageText = msg + alert.icon = NSImage.init(named: NSImage.Name(rawValue: "AppIcon")) + alert.alertStyle = .warning + alert.beginSheetModal(for: self.window!, completionHandler: { (r) in + print(r) + }) + } + @IBAction func ok(_ sender:AnyObject){ + if historyButton.state.rawValue == 1 { + ProxyGroupSettings.share.historyEnable = true + }else { + ProxyGroupSettings.share.historyEnable = false + } + if flagButton.state.rawValue == 1 { + ProxyGroupSettings.share.showCountry = true + }else { + ProxyGroupSettings.share.showCountry = false + } + + let x = UserDefaults.standard.object(forKey: "com.abigt.surf.UbiquityIdentityToken") + if x == nil { + iCloudButton.state = NSControl.StateValue(rawValue: 0) + alertMesage("Invalid iCloud token") + } + if iCloudButton.state.rawValue == 1 { + let delegate = NSApp.delegate as! AppDelegate + delegate.sync() + + ProxyGroupSettings.share.saveiCloudSync(true) + }else { + ProxyGroupSettings.share.saveiCloudSync(false) + } + + try! ProxyGroupSettings.share.save() + window?.performClose(nil) + } + +} diff --git a/Surf-Mac/AdvancedWindowController.xib b/Surf-Mac/AdvancedWindowController.xib new file mode 100644 index 0000000..7b81e4e --- /dev/null +++ b/Surf-Mac/AdvancedWindowController.xib @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/AppDelegate.swift b/Surf-Mac/AppDelegate.swift new file mode 100644 index 0000000..aa2298d --- /dev/null +++ b/Surf-Mac/AppDelegate.swift @@ -0,0 +1,1025 @@ +// +// AppDelegate.swift +// Surf-Mac +// +// Created by abigt on 15/12/22. +// Copyright © 2015年 abigt. All rights reserved. +// + +import Cocoa +import AxLogger +import NetworkExtension +import CoreImage +import SFSocket +import Fabric +import Crashlytics +import Xcon +import XRuler + +fileprivate extension NSTouchBar.CustomizationIdentifier { + + static let touchBar = NSTouchBar.CustomizationIdentifier("com.ToolbarSample.touchBar") +} + +fileprivate extension NSTouchBarItem.Identifier { + + static let popover = NSTouchBarItem.Identifier("com.ToolbarSample.TouchBarItem.popover") + static let fontStyle = NSTouchBarItem.Identifier("com.ToolbarSample.TouchBarItem.fontStyle") + static let popoverSlider = NSTouchBarItem.Identifier("com.ToolbarSample.popoverBar.slider") +} + +@NSApplicationMain +// + +class AppDelegate: NSResponder, NSApplicationDelegate,NSMenuDelegate ,NSTouchBarDelegate,BarcodeScanDelegate{ + weak var serversMenuItem: NSMenuItem? + var logUrl:URL = { + + + let url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + return url.appendingPathComponent("Log") + }() + let dnsqueue:DispatchQueue = DispatchQueue(label:"com.abigt.dns") + @IBOutlet weak var statusView: StatusView! + var targetManager : NEVPNManager? + var managers = [NEVPNManager]() + var configWindow:PreferencesWindowController? + var advancedWindos:AdvancedWindowController? + var aboutWindow:AboutWindowController? + var requestWindow:RequestsWindowController? + var qrWindow:QrWindowController? + var currentConfiguration: String? + var barItem: NSStatusItem! + var connectionButton:NSButton? + var configurations: [String: (String, Bool)] = [:] + var qr = QrController() + + func initMenuBar() { + let icon = NSImage(named: NSImage.Name(rawValue: "GrayDot")) + icon?.isTemplate = true + barItem = NSStatusBar.system.statusItem(withLength: -1) + barItem.view = self.statusView + barItem.menu = NSMenu() + barItem.menu!.delegate = self + } + @objc func qrScan(_ sender:AnyObject) { + + qr.delegate = self + _ = qr.startReading() + } + func addProxy(_ sender:AnyObject){ + + } + func alertMsg(_ msg:String){ + let alert = NSAlert.init() + alert.addButton(withTitle: "OK") + //action.target = self + //action.action = #selector(addProxy(_:)) + + alert.messageText = msg + + alert.alertStyle = .warning + + let x = alert.runModal() + print(x) + } + func barcodeScanDidScan(controller: QrController, configString:String) { + print("qr string \(configString)") + + let alert = NSAlert.init() + alert.addButton(withTitle: "Add") + //action.target = self + //action.action = #selector(addProxy(_:)) + alert.addButton(withTitle: "Cancle") + alert.messageText = configString + + alert.alertStyle = .warning + + let x = alert.runModal() + print(x) + + if !configString.isEmpty && x == NSApplication.ModalResponse.alertFirstButtonReturn{ + let proxy = SFProxy.createProxyWithURL(configString) + if let p = proxy.proxy { + _ = ProxyGroupSettings.share.addProxy(p) + }else { + alertMessage(message: proxy.message) + } + + } + } + func barcodeScanCancelScan(controller: QrController){ + alertMessage(message: "Don't Found QrCode,Please Open QrCode Image and Retry!") + } + @IBAction func pushMenu(_ sender:AnyObject){ + barItem.popUpMenu(barItem.menu!) + } + + func reloadManagers() { + SFVPNManager.shared.loadManager {[weak self] (m, error) in + if let m = m { + SFVPNManager.shared.xpc() + if let ss = self { + ss.observeStatus() + if m.connection.status == .invalid { + SFNETunnelProviderManager.loadOrCreateDefaultWithCompletionHandler({ (m, e) in + ss.showStatus(m!.connection.status) + SFVPNManager.shared.manager = m + }) + }else { + ss.showStatus(m.connection.status) + } + + + //ss.actionButton.isEnabled = true + } + } + + + } + } + /// Register for configuration change notifications. + func observeStatus() { + if let m = SFVPNManager.shared.manager{ + NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: m.connection, queue: OperationQueue.main, using: { [weak self ] notification in + //self.tableView.reloadRowsAtIndexPaths([ NSIndexPath(forRow: index, inSection: 0) ], withRowAnimation: .Fade) + print(index) + if let s = self{ + s.showStatus(m.connection.status) + + } + print(m.connection.status) + }) + } + } + + /// De-register for configuration change notifications. + func stopObservingStatus() { + if let m = SFVPNManager.shared.manager { + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: m.connection) + } + + } + @IBAction func connectVPN(_ sender: AnyObject){ + do { + _ = try SFVPNManager.shared.startStopToggled("") + }catch _ { + + } + + } + + func readImage(name:String) ->NSImage?{ + + guard let p = Bundle.main.path(forResource:name, ofType: "png")else { + return nil + } + return NSImage(contentsOfFile: p) + + } + @IBAction func addVPN(_ sender: AnyObject) { + _ = SFVPNManager.shared.loadManager { [weak self](manager, error) in + + if let _ = self, let _ = manager { + //strong.test(manager) + } + + } + + } + + func showStatus(_ status:NEVPNStatus){ + + switch status{ + case .disconnected: + statusView.iconView.image = NSImage(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + if let item = barItem.menu!.items.first{ + item.title = "Connect" + } + if let btn = connectionButton { + btn.title = "Connect" + } + case .invalid: + statusView.iconView.image = NSImage(named: NSImage.Name(rawValue: "NSStatusUnavailable")) + SSLog("Invalid") + if let item = barItem.menu!.items.first{ + item.title = "Invalid" + } + if let btn = connectionButton { + btn.title = "Invalid" + } + case .connected: + statusView.iconView.image = NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + SSLog("Connected") + if let item = barItem.menu!.items.first{ + item.title = "Disconnect" + } + if let btn = connectionButton { + btn.title = "Disconnect" + } + case .connecting: + statusView.iconView.image = NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + SSLog("Connecting") + if let item = barItem.menu!.items.first{ + item.title = "Connecting" + } + if let btn = connectionButton { + btn.title = "Connecting" + } + case .disconnecting: + statusView.iconView.image = NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + + if let item = barItem.menu!.items.first{ + item.title = "Disconnecting" + } + if let btn = connectionButton { + btn.title = "Disconnecting" + } + case .reasserting: + statusView.iconView.image = NSImage.init(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + + if let item = barItem.menu!.items.first{ + item.title = "Reasserting" + } + if let btn = connectionButton { + btn.title = "Reasserting" + } + } + + + } + @objc func startConfiguration(_ sender: NSMenuItem) { + } + func disconnect(_ sender: AnyObject? = nil) { + + } + func buildMenuItemForManager(_ name: String, valid: Bool) -> NSMenuItem { + let item = NSMenuItem(title: name, action: #selector(AppDelegate.startConfiguration(_:)), keyEquivalent: "") + + if name == currentConfiguration { + item.state = NSControl.StateValue.on + } + + if !valid { + item.action = nil + } + + return item + } + @objc func openProxySConfig(_ sender: AnyObject) { + configWindow = PreferencesWindowController(windowNibName: NSNib.Name(rawValue: "PreferencesWindowController")) + // preferencesWinCtrl = ctrl + + //let config = NSStoryboard.init(name: "Config", bundle: nil) + //configWindow = config.instantiateController(withIdentifier: "main") as? NSWindowController as! PreferencesWindowController? + + configWindow?.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + configWindow?.window?.makeKeyAndOrderFront(self) + } + @objc func openTelegram(_ sender :AnyObject){ + let url = URL.init(string: "https://telegram.me/abigtug") + + NSWorkspace.shared.open(url!) + } + @objc func openConfigDir(_ sender: AnyObject) { + let url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)!.appendingPathComponent("abigt.conf") + + NSWorkspace.shared.open(url) + //NSWorkspace.shared().open(logUrl as URL) + } + @objc func openLogDir(_ sender: AnyObject) { + + + if let m = SFVPNManager.shared.manager { + + let me = SFVPNXPSCommand.HELLO.rawValue + "|Hello Provider" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8), m.connection.status != .invalid + { + do { + try session.sendProviderMessage(message) { [unowned self] response in + if let response = response { + if let responseString = String.init(data:response , encoding: .utf8){ + let list = responseString.components(separatedBy: ":") + let session:String = list.last! + self.openSession(session: session) + + } + + //self.registerStatus() + } else { + self.openSession(session: "") + } + } + } catch { + openSession(session: "") + } + } + }else { + openSession(session: "") + } + + + + } + func openSession(session:String){ + let url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)!.appendingPathComponent("Log/" + session) + if fm.fileExists(atPath: url.path) { + NSWorkspace.shared.openFile(url.path, withApplication: "Terminal") + }else { + let url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + NSWorkspace.shared.open(url) + } + + } + @objc func openRequest(_ sender:AnyObject) { + if requestWindow == nil { + requestWindow = RequestsWindowController(windowNibName: NSNib.Name(rawValue: "RequestsWindowController")) + } + + requestWindow?.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + requestWindow?.window?.makeKeyAndOrderFront(self) + } + func setProxyClicked(_ sender: AnyObject) { + } + func copyCommand(_ sender: AnyObject) { + } + func allowClientsFromLanClicked(_ sender: AnyObject){ + // let image:CGImage = CGDisplayCreateImage(CGDirectDisplayID.init(0))! + // let ciImage:CIImage = CIImage(cgImage: image) + // var message:String = "" + // let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) + // + // let features = detector!.features(in: ciImage) + // + // if features.count > 0{ + // + // for feature in features as! [CIQRCodeFeature]{ + // message += feature.messageString! + // } + // print(message) + // + // + // }else{ + // + // } + + } + @objc func advancedOpen(_ sender: AnyObject){ + if advancedWindos == nil { + advancedWindos = AdvancedWindowController(windowNibName: NSNib.Name(rawValue: "AdvancedWindowController")) + } + + advancedWindos?.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + advancedWindos?.window?.makeKeyAndOrderFront(self) + } + @objc func showQrWindow(_ sender: AnyObject){ + + if ProxyGroupSettings.share.proxys.isEmpty { + alertMessage(message: "Please Add Proxy Server") + return + } + if qrWindow == nil { + qrWindow = QrWindowController(windowNibName: NSNib.Name(rawValue: "QRCodeWindow")) + } + let idx = ProxyGroupSettings.share.selectIndex + qrWindow?.proxy = ProxyGroupSettings.share.proxys[idx] + qrWindow?.showWindow(self) + NSApp.activate(ignoringOtherApps: true) + qrWindow?.window?.makeKeyAndOrderFront(self) + } + @objc func autostartClicked(_ sender: AnyObject){ + + } + + @objc func terminate(_ sender: AnyObject){ + + } + @objc func showAbout(_ sender: AnyObject){ + + NSApp.orderFrontStandardAboutPanel([:]) + + } + func test (){ + let task = Process() + + // Set the task parameters + task.launchPath = "/usr/sbin/lsof" + task.arguments = ["-n", "-i","tcp@127.0.0.1:6152"] + + // Create a Pipe and make the task + // put all the output there + let pipe = Pipe() + task.standardOutput = pipe + + // Launch the task + task.launch() + + // Get the data + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue) + + print(output!) + } + @objc func openHelp(_ sender: AnyObject){ + //thanks.txt + //test() + //pid cant get + let url = Bundle.main.url(forResource: "thanks", withExtension: "txt") + + NSWorkspace.shared.open(url!) + } + func showLogfile(_ sender: AnyObject){ + + } + @objc func update(_ sender: AnyObject){ + let url = URL.init(string: "https://gist.github.com/networkextension/069590ba0e95e2fc322f8d10c4212731") + NSWorkspace.shared.open(url!) + } + func menuNeedsUpdate(_ menu: NSMenu) { + menu.removeAllItems() + + for name in configurations.keys.sorted() { + let item = buildMenuItemForManager(name, valid: configurations[name]!.1) + menu.addItem(item) + } + + menu.addItem(NSMenuItem.separator()) + if let m = SFVPNManager.shared.manager { + let title = m.connection.status.titleForButton + menu.addItem(withTitle:title, action: #selector(AppDelegate.connectVPN(_:)), keyEquivalent: "d") + }else { + menu.addItem(withTitle:"Connect", action: #selector(AppDelegate.connectVPN(_:)), keyEquivalent: "d") + } + + menu.addItem(withTitle: "Request", action: #selector(AppDelegate.openRequest(_:)), keyEquivalent: "r") + menu.addItem(withTitle: "Open Log Path", action: #selector(AppDelegate.openLogDir(_:)), keyEquivalent: "o") + + menu.addItem(NSMenuItem.separator()) + + let item = NSMenuItem(title: "Servers", action: #selector(AppDelegate.advancedOpen(_:)), keyEquivalent: "") + menu.addItem(item) + serversMenuItem = item + if item.submenu == nil { + item.submenu = NSMenu() + updateServersMenu(false) + } + + + + menu.addItem(NSMenuItem(title: "Advanced Preferences ...", action: #selector(AppDelegate.advancedOpen(_:)), keyEquivalent: "")) + menu.addItem(NSMenuItem.separator()) + // + menu.addItem(withTitle: "Generate Qr Code", action: #selector(AppDelegate.showQrWindow(_:)), keyEquivalent: "g") + menu.addItem(withTitle: "Scan Qr Code From Screen", action: #selector(AppDelegate.qrScan(_:)), keyEquivalent: "g") + + menu.addItem(withTitle: "Manual", action: #selector(AppDelegate.update(_:)), keyEquivalent: "u") + menu.addItem(withTitle: "Show Rule Config", action: #selector(AppDelegate.openConfigDir(_:)), keyEquivalent: "") + menu.addItem(withTitle: "Telegram Group", action: #selector(AppDelegate.openTelegram(_:)), keyEquivalent: "") + menu.addItem(withTitle: "Acknowledge", action: #selector(AppDelegate.openHelp(_:)), keyEquivalent: "") + menu.addItem(withTitle: "About", action: #selector(AppDelegate.showAbout(_:)), keyEquivalent: "") + menu.addItem(NSMenuItem.separator()) + menu.addItem(withTitle: "Quit Surfing", action: #selector(AppDelegate.terminate(_:)), keyEquivalent: "q") + } + @IBAction func selectServer(_ sender: NSMenuItem) { + let index = sender.tag + + changeProxy(index: index) + + } + + func changeProxy(index:Int) { + ProxyGroupSettings.share.selectIndex = index + try! ProxyGroupSettings.share.save() + let me = SFVPNXPSCommand.CHANGEPROXY.rawValue + "|\(index)" + //m.connection.status == .connected + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8) + { + do { + try session.sendProviderMessage(message) { [weak self] response in + if let r = String.init(data: response!, encoding: .utf8) , r == proxyChangedOK{ + //print(proxyChangedOK) + //self!.alertMessageAction(r,complete: nil) + + } else { + self!.alertMessage(message:"Failed to Change Proxy") + } + } + } catch let e as NSError{ + alertMessage(message:"Failed to Change Proxy,reason \(e.description)") + } + + } + } + + } + func updateServersMenu(_ update:Bool) { + guard let serversMenuItem = serversMenuItem else {return} + guard let menu = serversMenuItem.submenu else {return} + menu.removeAllItems() + var index = 0 + let profile = ProxyGroupSettings.share + for p in profile.proxys { + var title = "" + if profile.showCountry { + + if !p.serverIP.isEmpty{ + let rusult = Country.setting.geoIPRule(ipString: p.serverIP) + + p.countryFlag = rusult.emoji + p.isoCode = rusult.isoCode + title += p.countryFlag + }else { + hostToIP(proxy: p) + } + + + } + if p.proxyName.isEmpty { + title += p.serverAddress + ":" + p.serverPort + + }else { + title += p.proxyName + "(" + p.serverAddress + ":" + p.serverPort + ")" + } + let em = NSMenuItem(title: title, action: #selector(AppDelegate.selectServer(_:)), keyEquivalent: "") + em.tag = index + if ProxyGroupSettings.share.selectIndex == index { + em.state = NSControl.StateValue(rawValue: 1) + + }else { + em.state = NSControl.StateValue(rawValue: 0) + } + index += 1 + menu.addItem(em) + } + menu.addItem(NSMenuItem.separator()) + menu.addItem(withTitle: "Open Server Preferences ...", action: #selector(AppDelegate.openProxySConfig(_:)), keyEquivalent: "c") + } + func copyConfig(){ + + let firstOpen = UserDefaults.standard.bool(forKey: "firstOpen") + if firstOpen == false { + let c = "abigt.conf"//逗比极客精简版.json","逗比极客全能版.json","abclite普通版.json","abclite去广告版.json","surf_main.json" + + if let p = Bundle.main.path(forResource:c, ofType: nil){ + //let u = groupContainerURL.appendingPathComponent(f) + let u2 = groupContainerURL().appendingPathComponent(c) + do { + // try fm.copyItemAtPath(p, toPath: u.path!) + try fm.copyItem(atPath: p, toPath: u2.path) + }catch let e as NSError { + + alertMessage(message: "copy config file error \(e)") + } + + + }else { + alertMessage(message: "abigt.conf don't Find") + + } + + ProxyGroupSettings.share.config = "abigt" + configExt + try! ProxyGroupSettings.share.save() + UserDefaults.standard.set(true, forKey: "firstOpen") + UserDefaults.standard.synchronize() + }else { + //alertMessage(message: "!firstOpen") + } + } + + func alertMessage(message:String){ + let alert = NSAlert.init() + alert.addButton(withTitle: "OK") + alert.messageText = message + alert.alertStyle = .warning + alert.runModal() + } + // fileprivate extension NSTouchBarCustomizationIdentifier { + // + // static + // } + // + // fileprivate extension NSTouchBarItemIdentifier { + // + // + // static + // static + // }' + // MARK: - NSTouchBar + override func value(forUndefinedKey key: String) -> Any? { + print("forUndefinedKey " + key) + return nil + } + + func applicationDidFinishLaunching(_ notification: Notification) { + Fabric.with([Crashlytics.self]) + XRuler.groupIdentifier = "745WQDK4L7.com.abigt.Surf" + UserDefaults.standard.set(true, forKey: "NSApplicationCrashOnExceptions") + copyConfig() + // testTouchBar() + icloudPrepare() + //NSApp.setActivationPolicy(.accessory) + let baseURL = groupContainerURL().appendingPathComponent("Library/Application Support") + if !fm.fileExists(atPath: baseURL.path){ + do { + try fm.createDirectory(at: baseURL, withIntermediateDirectories:false , attributes: [:]) + }catch let e { + print(e.localizedDescription) + } + } + + initMenuBar() + reloadManagers() + // AxLogger.openLogging(baseURL, date:Date(),debug: true) + // AxLogger.log("test", level: .Info) + installNoti() + updateServersMenu(false) + loadConfig() + //showScan() + } + + func showScan(){ + let queue = DispatchQueue.init(label: ".", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil) + //let queue = DispatchQueue(label: "com.abigt.socket")// DISPATCH_QUEUE_CONCURRENT) + for p in ProxyGroupSettings.share.proxys { + + queue.async(execute: { + + let start = Date() + + + // Look up the host... + let socketfd: Int32 = socket(Int32(AF_INET), SOCK_STREAM, Int32(IPPROTO_TCP)) + let remoteHostName = p.serverAddress + //let port = Intp.serverPort + guard let remoteHost = gethostbyname2((remoteHostName as NSString).utf8String, AF_INET)else { + return + } + //remoteHostEnt?.pointee.h_addr_list + //let remoteHost: UnsafeMutablePointer = gethostbyname(remoteHostName) + + + let d = Date() + + + + p.dnsValue = d.timeIntervalSince(start) + var remoteAddr = sockaddr_in() + remoteAddr.sin_family = sa_family_t(AF_INET) + bcopy(remoteHost.pointee.h_addr_list[0], &remoteAddr.sin_addr.s_addr, Int(remoteHost.pointee.h_length)) + if let port = UInt16(p.serverPort) { + remoteAddr.sin_port = port.bigEndian + + }else { + _ = p.serverPort + print("\(p.serverPort) error") + close(socketfd) + p.tcpValue = -1 + return + } + + + + // Now, do the connection... + let rc = withUnsafePointer(to: &remoteAddr) { + // Temporarily bind the memory at &addr to a single instance of type sockaddr. + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + connect(socketfd, $0, socklen_t(MemoryLayout.stride)) + } + } + + + if rc < 0 { + print("\(p.serverAddress):\(p.serverPort) socket connect failed") + //throw BlueSocketError(code: BlueSocket.SOCKET_ERR_CONNECT_FAILED, reason: self.lastError()) + p.tcpValue = -1 + }else { + let end = Date() + p.tcpValue = end.timeIntervalSince(d ) + close(socketfd) + } + + DispatchQueue.main.async(execute: { [weak self] in + if let StrongSelft = self { + StrongSelft.updateServersMenu(false) + try! ProxyGroupSettings.share.save() + } + + + }) + + }) + } + } + func toUint(signed: Int8) -> UInt8 { + + let unsigned = signed >= 0 ? + UInt8(signed) : + UInt8(signed - Int8.min) + UInt8(Int8.max) + 1 + + return unsigned + } + func hostToIP(proxy:SFProxy) { + dnsqueue.async(execute:{ [weak self ] in + guard let strong = self else {return} + + guard let hostInfo = gethostbyname2((proxy.serverAddress as NSString).utf8String, AF_INET)else { + return + } + + + + + let len = hostInfo.pointee.h_length + let aa = hostInfo.pointee.h_addr_list[0] + var ip = "" + + for i in 0 ..< len { + let x = (aa! + Int(i)).pointee + if i == (len - 1) { + ip += "\(strong.toUint(signed: x))" + break + } + ip += "\(strong.toUint(signed: x))." + + } + proxy.serverIP = ip + DispatchQueue.main.async(execute: { + self!.updateServersMenu(false) + }) + + }) + + + //return ip + } + func installNoti(){ + let notifyCenter = NotificationCenter.default + notifyCenter.addObserver(forName: NSNotification.Name(rawValue: NOTIFY_SERVER_PROFILES_CHANGED), object: nil, queue: nil + , using: { + (note) in + let _ = ProxyGroupSettings.share + //self.showScan() + self.updateServersMenu(true) + //SyncSSLocal() + } + ) + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + func loadConfig(){ + var url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + url.appendPathComponent("abigt.conf") + let config = SFConfig.init(path: url.path, loadRule: true) + print(config.configName) + } + +} + +extension AppDelegate { + @available(OSX 10.12.2, *) + override func makeTouchBar() -> NSTouchBar? { + + let touchBar = NSTouchBar() + touchBar.delegate = self + touchBar.customizationIdentifier = .touchBar + touchBar.defaultItemIdentifiers = [.fontStyle, .popover, .otherItemsProxy] + touchBar.customizationAllowedItemIdentifiers = [.fontStyle, .popover,.otherItemsProxy] + + return touchBar + } + // + // @IBOutlet weak var mytouchBar: NSTouchBar? + // + @available(OSX 10.12.2, *) + + func changeFontSizeBySlider(_ sender:NSSlider) { + + } + @objc func changeFontStyleBySegment(_ sender:NSSegmentedControl){ + let index = sender.selectedSegment + changeProxy(index: index) + + } + // + @available(OSX 10.12.2, *) + func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? { + switch identifier { + + case NSTouchBarItem.Identifier.popover: + + // let popoverItem = NSPopoverTouchBarItem(identifier: identifier) + // popoverItem.customizationLabel = "Font Size" + // popoverItem.collapsedRepresentationLabel = "Font Size" + // + // let secondaryTouchBar = NSTouchBar() + // secondaryTouchBar.delegate = self + // secondaryTouchBar.defaultItemIdentifiers = [.popoverSlider]; + // + // // We can setup a different NSTouchBar instance for popoverTouchBar and pressAndHoldTouchBar property + // // Here we just use the same instance. + // // + // popoverItem.pressAndHoldTouchBar = secondaryTouchBar + // popoverItem.popoverTouchBar = secondaryTouchBar + // + // return popoverItem + let item = NSCustomTouchBarItem(identifier:identifier) + let button = NSButton.init(title: "Connect", target: self, action: #selector(connectVPN)) + self.connectionButton = button + item.view = button + + return item + + case NSTouchBarItem.Identifier.fontStyle: + + var labels:[String] = [] + + var count = 7 + if ProxyGroupSettings.share.proxys.count <= count { + count = ProxyGroupSettings.share.proxys.count + } + for idx in 0 ..< count { + let p = ProxyGroupSettings.share.proxys[idx] + var title = "" + if ProxyGroupSettings.share.showCountry { + + if !p.serverIP.isEmpty{ + let rusult = Country.setting.geoIPRule(ipString: p.serverIP) + + p.countryFlag = rusult.emoji + p.isoCode = rusult.isoCode + title += p.countryFlag + }else { + hostToIP(proxy: p) + } + + } + if p.proxyName.isEmpty { + title += p.serverAddress + + }else { + title += p.proxyName + } + labels.append(title) + } + let fontStyleItem = NSCustomTouchBarItem(identifier: identifier) + fontStyleItem.customizationLabel = "Font Style" + + let fontStyleSegment = NSSegmentedControl(labels: labels, trackingMode: .selectOne, target: self, action: #selector(changeFontStyleBySegment)) + if ProxyGroupSettings.share.selectIndex < count { + fontStyleSegment.selectedSegment = ProxyGroupSettings.share.selectIndex + } + + fontStyleItem.view = fontStyleSegment + + return fontStyleItem; + + case NSTouchBarItem.Identifier.popoverSlider: + + // let sliderItem = NSSliderTouchBarItem(identifier: identifier) + // sliderItem.label = "Size" + // sliderItem.customizationLabel = "Font Size" + // + // let slider = sliderItem.slider + // slider.minValue = 6.0 + // slider.maxValue = 100.0 + // slider.target = self + // slider.action = #selector(changeFontSizeBySlider) + // + // // Set the font size for the slider item to the same value as the stepper. + // slider.integerValue = 18 + // + // slider.bind(NSValueBinding, to: self, withKeyPath: "currentFontSize", options: nil) + // + // return sliderItem + return nil + default: + // let item = NSSliderTouchBarItem(identifier:identifier) + // item.label = "Connect" + // item.target = self + // item.action = #selector(connectVPN) + return nil + } + + } + + // func testTouchBar() { + // + // if ((NSClassFromString("NSTouchBar")) != nil) { + // let popoverSlider = NSTouchBarItemIdentifier("com.ToolbarSample.popoverBar.slider") + // let popover = NSTouchBarItemIdentifier("com.ToolbarSample.TouchBarItem.popover") + // if self.touchBar == nil { + // self.touchBar = makeTouchBar() + // } + // guard let touchBar = touchBar else {return} + // let fontSizeTouchBarItem = touchBar.item(forIdentifier: popover) as! NSPopoverTouchBarItem + // let sliderTouchBar = fontSizeTouchBarItem.popoverTouchBar + // let sliderTouchBarItem = sliderTouchBar.item(forIdentifier: popoverSlider) as! NSSliderTouchBarItem + // let slider = sliderTouchBarItem.slider + // + // // Make the font size slider a bit narrowed, about 250 pixels. + // let views = ["slider" : slider] + // let theConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:[slider(250)]", options: NSLayoutFormatOptions(), metrics: nil, views:views) + // NSLayoutConstraint.activate(theConstraints) + // + // // Set the font size for the slider item to the same value as the stepper. + // slider.integerValue = 10 + // } + // + // } +} +extension AppDelegate { + func icloudPrepare(){ + + let fm = FileManager.default + if let currentiCloudToken = fm.ubiquityIdentityToken{ + let newTokenData:NSData = NSKeyedArchiver.archivedData(withRootObject: currentiCloudToken) as NSData + print("token \(newTokenData)") + UserDefaults.standard.set(newTokenData, forKey: "com.abigt.surf.UbiquityIdentityToken") + let iCloudToken = NSKeyedArchiver.archivedData(withRootObject: currentiCloudToken) + //setObject: newTokenData + //forKey: @"com.apple.MyAppName.UbiquityIdentityToken"]; + }else { + UserDefaults.standard + .removeObject(forKey: "com.abigt.surf.UbiquityIdentityToken") + } + NotificationCenter.default.addObserver(forName: NSNotification.Name.NSUbiquityIdentityDidChange, object: nil, queue: OperationQueue.main) { (noti:Notification) in + print("NSUbiquityIdentityDidChangeNotification") + } + let iCloudEnable = UserDefaults.standard.bool(forKey: "iCloudEnable") + if ProxyGroupSettings.share.iCloudSyncEnabled(){ + sync() + } + } + + func sync() { + + + DispatchQueue.global().async(execute: { [weak self] in + guard let countainer = FileManager.default.url(forUbiquityContainerIdentifier: nil) else { + DispatchQueue.main.async(execute: { + self?.alertMsg("Error Enable iCloud sysnc") + }) + return + } + print("countainer:url \(String(describing: countainer))") + + let documentsDirectory = countainer.appendingPathComponent("Documents"); + if !FileManager.default.fileExists(atPath: documentsDirectory.path){ + try! FileManager.default.createDirectory(atPath: documentsDirectory.path, withIntermediateDirectories: false, attributes: nil) + } + do { + try self!.moverToiCloud(url: documentsDirectory) + }catch let e { + DispatchQueue.main.async(execute: { + self?.alertMsg("icloud sync:\(e.localizedDescription)") + }) + + } + + + }) + + } + func moverToiCloud(url:URL) throws{ + let u = applicationDocumentsDirectory + do { + let fs = try fm.contentsOfDirectory(atPath: (u.path)) + for fp in fs { + if fp.hasSuffix(configExt) { + + let dest = url.appendingPathComponent(fp) + let src = u.appendingPathComponent(fp) + + if FileManager.default.fileExists(atPath: dest.path) { + + }else { + try fm.copyItem(at: src, to: dest) + print("copy \(dest.path)") + } + + } + + } + let sp = groupContainerURL().appendingPathComponent(kProxyGroupFile) + let dp = url.appendingPathComponent("ProxyGroup.json") + if FileManager.default.fileExists(atPath: dp.path) { + try fm.removeItem(at: dp) + } + try fm.copyItem(at: sp, to: dp) + + }catch let e as NSError{ + throw e + + } + + + } +} diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d5d0108 --- /dev/null +++ b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16@2x.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32@2x.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128@2x.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon-1024256w.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon-1024512w-1.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon-1024512w.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon-1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024.png new file mode 100644 index 0000000..33c0d16 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024256w.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024256w.png new file mode 100644 index 0000000..ab8d6c2 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024256w.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024512w-1.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024512w-1.png new file mode 100644 index 0000000..29c9754 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024512w-1.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024512w.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024512w.png new file mode 100644 index 0000000..29c9754 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon-1024512w.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_128.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_128.png new file mode 100644 index 0000000..da82031 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_128.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_128@2x.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_128@2x.png new file mode 100644 index 0000000..ab8d6c2 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_128@2x.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_16.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_16.png new file mode 100644 index 0000000..4714329 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_16.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_16@2x.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_16@2x.png new file mode 100644 index 0000000..693127b Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_16@2x.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_32.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_32.png new file mode 100644 index 0000000..693127b Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_32.png differ diff --git a/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_32@2x.png b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_32@2x.png new file mode 100644 index 0000000..e580ba4 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/AppIcon.appiconset/icon_32@2x.png differ diff --git a/Surf-Mac/Assets.xcassets/Contents.json b/Surf-Mac/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Surf-Mac/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf-Mac/Assets.xcassets/GrayDot.imageset/Contents.json b/Surf-Mac/Assets.xcassets/GrayDot.imageset/Contents.json new file mode 100644 index 0000000..4edb1ee --- /dev/null +++ b/Surf-Mac/Assets.xcassets/GrayDot.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "GrayDot@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "GrayDot.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "GrayDot@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot.png b/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot.png new file mode 100644 index 0000000..905fce2 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot.png differ diff --git a/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot@1x.png b/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot@1x.png new file mode 100644 index 0000000..3e491a6 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot@1x.png differ diff --git a/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot@3x.png b/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot@3x.png new file mode 100644 index 0000000..d6db719 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/GrayDot.imageset/GrayDot@3x.png differ diff --git a/Surf-Mac/Assets.xcassets/GreenDot.imageset/Contents.json b/Surf-Mac/Assets.xcassets/GreenDot.imageset/Contents.json new file mode 100644 index 0000000..298d73d --- /dev/null +++ b/Surf-Mac/Assets.xcassets/GreenDot.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "GreenDot@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "GreenDot.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "GreenDot@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot.png b/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot.png new file mode 100644 index 0000000..86cf5de Binary files /dev/null and b/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot.png differ diff --git a/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot@1x.png b/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot@1x.png new file mode 100644 index 0000000..eaf9686 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot@1x.png differ diff --git a/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot@3x.png b/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot@3x.png new file mode 100644 index 0000000..7f07110 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/GreenDot.imageset/GreenDot@3x.png differ diff --git a/Surf-Mac/Assets.xcassets/RedDot.imageset/Contents.json b/Surf-Mac/Assets.xcassets/RedDot.imageset/Contents.json new file mode 100644 index 0000000..8139a78 --- /dev/null +++ b/Surf-Mac/Assets.xcassets/RedDot.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "RedDot@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "RedDot.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "RedDot@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot.png b/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot.png new file mode 100644 index 0000000..a1284fc Binary files /dev/null and b/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot.png differ diff --git a/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot@1x.png b/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot@1x.png new file mode 100644 index 0000000..e0e69b9 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot@1x.png differ diff --git a/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot@3x.png b/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot@3x.png new file mode 100644 index 0000000..a2ff1a7 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/RedDot.imageset/RedDot@3x.png differ diff --git a/Surf-Mac/Assets.xcassets/StatusIcon.imageset/Contents.json b/Surf-Mac/Assets.xcassets/StatusIcon.imageset/Contents.json new file mode 100644 index 0000000..41958ac --- /dev/null +++ b/Surf-Mac/Assets.xcassets/StatusIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "mac", + "filename" : "StatusIcon.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Surf-Mac/Assets.xcassets/StatusIcon.imageset/StatusIcon.pdf b/Surf-Mac/Assets.xcassets/StatusIcon.imageset/StatusIcon.pdf new file mode 100644 index 0000000..95b6b36 Binary files /dev/null and b/Surf-Mac/Assets.xcassets/StatusIcon.imageset/StatusIcon.pdf differ diff --git a/Surf-Mac/Base.lproj/Main.storyboard b/Surf-Mac/Base.lproj/Main.storyboard new file mode 100644 index 0000000..a1162a9 --- /dev/null +++ b/Surf-Mac/Base.lproj/Main.storyboard @@ -0,0 +1,794 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/Config.storyboard b/Surf-Mac/Config.storyboard new file mode 100644 index 0000000..43fc673 --- /dev/null +++ b/Surf-Mac/Config.storyboard @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/ConfigWindowController.swift b/Surf-Mac/ConfigWindowController.swift new file mode 100644 index 0000000..1e38435 --- /dev/null +++ b/Surf-Mac/ConfigWindowController.swift @@ -0,0 +1,21 @@ +// +// ConfigWindowController.swift +// Surf +// +// Created by 孔祥波 on 21/11/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa + +class ConfigWindowController: NSWindowController,NSTableViewDelegate,NSTableViewDataSource { + + override func windowDidLoad() { + super.windowDidLoad() + + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + deinit { + print("window deinit") + } +} diff --git a/Surf-Mac/Credits.rtf b/Surf-Mac/Credits.rtf new file mode 100644 index 0000000..46576ef --- /dev/null +++ b/Surf-Mac/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/Surf-Mac/Info.plist b/Surf-Mac/Info.plist new file mode 100644 index 0000000..1a50914 --- /dev/null +++ b/Surf-Mac/Info.plist @@ -0,0 +1,70 @@ + + + + + ATSApplicationFontsPath + ionicons.ttf + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + icon.cns + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + A.BIG.T + CFBundleDisplayName + A.BIG.T + CFBundlePackageType + APPL + CFBundleShortVersionString + 2.0.2 + CFBundleSignature + ???? + CFBundleVersion + 100 + Fabric + + APIKey + + Kits + + + KitInfo + + KitName + Crashlytics + + + + LSApplicationCategoryType + public.app-category.productivity + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + + NSHumanReadableCopyright + Copyright © 2017年 A.BIG.T. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + SFApplication + NSUbiquitousContainers + + iCloud.com.abigt.Surf + + NSUbiquitousContainerIsDocumentScopePublic + + NSUbiquitousContainerName + Surf + NSUbiquitousContainerSupportedFolderLevels + Any + + + ic + + + diff --git a/Surf-Mac/MainMenu.xib b/Surf-Mac/MainMenu.xib new file mode 100644 index 0000000..434e3be --- /dev/null +++ b/Surf-Mac/MainMenu.xib @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/PreferencesWindowController.swift b/Surf-Mac/PreferencesWindowController.swift new file mode 100644 index 0000000..6e62b7e --- /dev/null +++ b/Surf-Mac/PreferencesWindowController.swift @@ -0,0 +1,477 @@ +// +// PreferencesWindowController.swift +// ShadowsocksX-NG +// +// Created by 邱宇舟 on 16/6/6. +// Copyright © 2016年 qiuyuzhou. All rights reserved. +// + +import Cocoa +import SFSocket +import Xcon +import XRuler +func ==(lhs:SFProxy,rhs:SFProxy) -> Bool { + + return (lhs.serverPort == rhs.serverPort) && (lhs.serverAddress == rhs.serverAddress) +} +class PreferencesWindowController: NSWindowController + , NSTableViewDataSource, NSTableViewDelegate { + + @IBOutlet weak var typeControl: NSSegmentedControl! + @IBOutlet weak var profilesTableView: NSTableView! + + @IBOutlet weak var profileBox: NSBox! + + + @IBOutlet weak var hostTextField: NSTextField! + @IBOutlet weak var portTextField: NSTextField! + @IBOutlet weak var methodTextField: NSComboBox! + + @IBOutlet weak var methodTextField1:NSTextField! + @IBOutlet weak var passwordTextField: NSTextField! + @IBOutlet weak var remarkTextField: NSTextField! + + @IBOutlet weak var methodInfoTextField: NSTextField! + + @IBOutlet weak var otaCheckBoxBtn: NSButton! + + @IBOutlet weak var copyURLBtn: NSButton! + + @IBOutlet weak var removeButton: NSButton! + + @IBOutlet weak var kcptun:NSButton! + @IBOutlet weak var kcptunComp:NSButton! + + @IBOutlet weak var crytoFiled:NSTextField! + @IBOutlet weak var crytoKeyFiled:NSTextField! + @IBOutlet weak var datashardFiled:NSTextField! + + @IBOutlet weak var parityshardFiled:NSTextField! + + let tableViewDragType: String = "ss.server.profile.data" + + var defaults: UserDefaults! + var profileMgr: ProxyGroupSettings = ProxyGroupSettings.share + + var editingProfile: SFProxy? + + + override func windowDidLoad() { + super.windowDidLoad() + + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + defaults = UserDefaults.standard + + + methodTextField.addItems(withObjectValues: [ + "rc4", + "rc4-md5", + "aes-128-cfb", + "aes-192-cfb", + "aes-256-cfb", + "bf-cfb", + "cast5-cfb", + "des-cfb", + "rc2-cfb", + "salsa20", + "chacha20", + "chacha20-ietf" + ]) + + profilesTableView.reloadData() + bindProfile(0) + updateProfileBoxVisible() + } + + override func awakeFromNib() { + //fixme + //profilesTableView.register([tableViewDragType], forIdentifier: "") + } + + + + @IBAction func addProfile(_ sender: NSButton) { +// if editingProfile != nil { +// +// shakeWindows() +// return +// } + profilesTableView.beginUpdates() + if let profile = SFProxy.create(name: "remakr", type: .SS, address: "", port: "", passwd: "", method: "", tls: false){ + profile.proxyName = "New Server" + if editingProfile != nil { + save(false)//save last editing site + } + + _ = profileMgr.addProxy(profile) + + editingProfile = profile + let index = IndexSet(integer: profileMgr.proxys.count-1) + profilesTableView.insertRows(at: index, withAnimation: .effectFade) + + self.profilesTableView.scrollRowToVisible(self.profileMgr.proxys.count-1) + self.profilesTableView.selectRowIndexes(index, byExtendingSelection: false) + profilesTableView.endUpdates() + updateProfileBoxVisible() + } + + } + + @IBAction func removeProfile(_ sender: NSButton) { + let index = profilesTableView.selectedRow + if index >= 0 { + profilesTableView.beginUpdates() + profileMgr.removeProxy(index, chain: false) + profilesTableView.removeRows(at: IndexSet(integer: index), withAnimation: .effectFade) + profilesTableView.endUpdates() + } + updateProfileBoxVisible() + } + + @IBAction func ok(_ sender: NSButton) { + + save(false) + window?.performClose(nil) + + + NotificationCenter.default + .post(name: Notification.Name(rawValue: NOTIFY_SERVER_PROFILES_CHANGED), object: nil) + } + func save(_ upSelected:Bool) { + if editingProfile != nil { + editingProfile?.serverAddress = hostTextField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + + editingProfile?.password = passwordTextField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + editingProfile?.serverPort = portTextField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + editingProfile?.proxyName = remarkTextField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + if otaCheckBoxBtn.state.rawValue == 1 { + editingProfile?.tlsEnable = true + + }else { + editingProfile?.tlsEnable = false + } + + if kcptun.state.rawValue == 1 { + editingProfile?.kcptun = true + }else { + editingProfile?.kcptun = false + } + editingProfile?.config.key = crytoKeyFiled.stringValue + editingProfile?.config.crypt = crytoFiled.stringValue + if kcptunComp.state.rawValue == 1{ + editingProfile?.config.noComp = true + }else { + editingProfile?.config.noComp = false + } + editingProfile?.config.datashard = Int(datashardFiled.intValue) + editingProfile?.config.parityshard = Int(parityshardFiled.intValue) + switch typeControl.selectedSegment { + case 0: + editingProfile?.method = methodTextField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + editingProfile?.type = .SS + + case 1: + editingProfile?.method = methodTextField1.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + editingProfile?.type = .HTTP + otaCheckBoxBtn.title = "TLS" + case 2: + editingProfile?.type = .SOCKS5 + + editingProfile?.method = methodTextField1.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) + default: + break + } + } + do { + if upSelected { + profileMgr.selectIndex = profilesTableView.selectedRow + } + + try profileMgr.save() + }catch let e { + print(e.localizedDescription) + } + } + @IBAction func cancel(_ sender: NSButton) { + window?.performClose(self) + } + + @IBAction func valueChanged(_ sender:NSSegmentedControl){ + if sender.selectedSegment == 0 { + methodTextField1.isHidden = true + methodTextField.isHidden = false + methodInfoTextField.stringValue = "Method:" + otaCheckBoxBtn.title = "OTA" + + }else { + methodTextField.isHidden = true + methodTextField1.isHidden = false + otaCheckBoxBtn.title = "SSL" + methodInfoTextField.stringValue = "Username:" + } + } + @IBAction func copyCurrentProfileURL2Pasteboard(_ sender: NSButton) { + let index = profilesTableView.selectedRow + if index >= 0 { + _ = profileMgr.proxys[index] + //don't support year +// let ssURL = profile.URL() +// if let url = ssURL { +// // Then copy url to pasteboard +// // TODO Why it not working?? It's ok in objective-c +// let pboard = NSPasteboard.general() +// pboard.clearContents() +// let rs = pboard.writeObjects([url as NSPasteboardWriting]) +// if rs { +// NSLog("copy to pasteboard success") +// } else { +// NSLog("copy to pasteboard failed") +// } +// } + } + } + + func updateProfileBoxVisible() { + if profileMgr.proxys.count <= 1 { + removeButton.isEnabled = false + }else{ + removeButton.isEnabled = true + } + + if profileMgr.proxys.isEmpty { + profileBox.isHidden = true + } else { + profileBox.isHidden = false + } + } + + func bindProfile(_ index:Int) { + NSLog("bind profile \(index)") + if index >= 0 && index < profileMgr.proxys.count { + let temp = profileMgr.proxys[index] + + if editingProfile?.serverAddress != temp.serverAddress && editingProfile?.serverPort != temp.serverPort { + save(false) + } + + + editingProfile = temp + + hostTextField.stringValue = editingProfile!.serverAddress + portTextField.stringValue = editingProfile!.serverPort + + + + + passwordTextField.stringValue = editingProfile!.password + + + remarkTextField.stringValue = editingProfile!.proxyName + crytoFiled.stringValue = editingProfile!.config.crypt + crytoKeyFiled.stringValue = editingProfile!.config.key + if editingProfile!.config.noComp { + kcptunComp.state = NSControl.StateValue(rawValue: 1) + }else { + kcptunComp.state = NSControl.StateValue(rawValue: 0) + } + datashardFiled.intValue = Int32(editingProfile!.config.datashard) + parityshardFiled.intValue = Int32(editingProfile!.config.parityshard) + if editingProfile!.tlsEnable { + otaCheckBoxBtn.state = NSControl.StateValue(rawValue: 1) + }else { + otaCheckBoxBtn.state = NSControl.StateValue(rawValue: 0) + } + switch editingProfile!.type { + case .SS: + methodTextField.stringValue = editingProfile!.method + typeControl.selectedSegment = 0 + methodTextField1.isHidden = true + methodTextField.isHidden = false + methodInfoTextField.stringValue = "Method:" + otaCheckBoxBtn.title = "OTA" + case .HTTP: + methodTextField1.stringValue = editingProfile!.method + typeControl.selectedSegment = 1 + methodTextField.isHidden = true + methodTextField1.isHidden = false + methodInfoTextField.stringValue = "Username:" + otaCheckBoxBtn.title = "TLS" + case .SOCKS5: + methodTextField1.stringValue = editingProfile!.method + typeControl.selectedSegment = 2 + methodTextField.isHidden = true + methodTextField1.isHidden = false + methodInfoTextField.stringValue = "Username:" + otaCheckBoxBtn.title = "TLS" + default: + break + } + + if editingProfile!.kcptun { + kcptun.state = NSControl.StateValue(rawValue: 1) + }else { + kcptun.state = NSControl.StateValue(rawValue: 0) + } + + + } else { + editingProfile = nil + hostTextField.unbind(NSBindingName(rawValue: "value")) + portTextField.unbind(NSBindingName(rawValue: "value")) + + methodTextField.unbind(NSBindingName(rawValue: "value")) + passwordTextField.unbind(NSBindingName(rawValue: "value")) + + remarkTextField.unbind(NSBindingName(rawValue: "value")) + + otaCheckBoxBtn.unbind(NSBindingName(rawValue: "value")) + } + } + + func getDataAtRow(_ index:Int) -> (String, Bool) { + let profile = profileMgr.proxys[index] + //todo + let isActive = (profileMgr.selectIndex == index) + if !profile.proxyName.isEmpty { + return (profile.proxyName, isActive) + } else { + return (profile.serverAddress, isActive) + } + } + + //-------------------------------------------------- + // For NSTableViewDataSource + + func numberOfRows(in tableView: NSTableView) -> Int { + return profileMgr.proxys.count + + } + + func tableView(_ tableView: NSTableView + , objectValueFor tableColumn: NSTableColumn? + , row: Int) -> Any? { + + let (title, isActive) = getDataAtRow(row) + + if tableColumn?.identifier.rawValue == "main" { + return title + } else if tableColumn?.identifier.rawValue == "status" { + if isActive { + return NSImage(named: NSImage.Name(rawValue: "NSMenuOnStateTemplate")) + } else { + return nil + } + } + return "" + } + + // Drag & Drop reorder rows + + func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? { + let item = NSPasteboardItem() + item.setString(String(row), forType: NSPasteboard.PasteboardType(rawValue: tableViewDragType)) + return item + } + + func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int + , proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation { + if dropOperation == .above { + return .move + } + return NSDragOperation() + } + + func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo + , row: Int, dropOperation: NSTableView.DropOperation) -> Bool { + let mgr = profileMgr + var oldIndexes = [Int]() + //MARK ---- +// info.enumerateDraggingItems(options: [], for: tableView, classes: [NSPasteboardItem.self], searchOptions: [:]) { in +// if let str = ($0.0.item as! NSPasteboardItem).string(forType: self.tableViewDragType), let index = Int(str) { +// oldIndexes.append(index) +// } +// } + + var oldIndexOffset = 0 + var newIndexOffset = 0 + + // For simplicity, the code below uses `tableView.moveRowAtIndex` to move rows around directly. + // You may want to move rows in your content array and then call `tableView.reloadData()` instead. + tableView.beginUpdates() + for oldIndex in oldIndexes { + if oldIndex < row { + let o = mgr.removeProxy( oldIndex + oldIndexOffset, chain: false) + //todo + //mgr.proxys.insert(o, at:row - 1) + tableView.moveRow(at: oldIndex + oldIndexOffset, to: row - 1) + oldIndexOffset -= 1 + } else { + let o = mgr.removeProxy( oldIndex,chain: false) + //mgr.proxys.insert(o, at:row + newIndexOffset) + tableView.moveRow(at: oldIndex, to: row + newIndexOffset) + newIndexOffset += 1 + } + } + tableView.endUpdates() + + return true + + } + + //-------------------------------------------------- + // For NSTableViewDelegate + + func tableView(_ tableView: NSTableView + , shouldEdit tableColumn: NSTableColumn?, row: Int) -> Bool { + return false + } + + func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool { + if row < 0 { + editingProfile = nil + return true + } + if editingProfile != nil { + //if !editingProfile.isValid() { + // return false + //} + } + + return true + } + + func tableViewSelectionDidChange(_ notification: Notification) { + if profilesTableView.selectedRow >= 0 { + bindProfile(profilesTableView.selectedRow) + profilesTableView.reloadData() + } else { + if !profileMgr.proxys.isEmpty { + let index = IndexSet(integer: profileMgr.proxys.count - 1) + profilesTableView.selectRowIndexes(index, byExtendingSelection: false) + } + } + } + + func shakeWindows(){ + let numberOfShakes:Int = 8 + let durationOfShake:Float = 0.5 + let vigourOfShake:Float = 0.05 + + let frame:CGRect = (window?.frame)! + let shakeAnimation = CAKeyframeAnimation() + + let shakePath = CGMutablePath() + shakePath.move(to: CGPoint(x:NSMinX(frame), y:NSMinY(frame))) + + for _ in 1...numberOfShakes{ + shakePath.addLine(to: CGPoint(x: NSMinX(frame) - frame.size.width * CGFloat(vigourOfShake), y: NSMinY(frame))) + shakePath.addLine(to: CGPoint(x: NSMinX(frame) + frame.size.width * CGFloat(vigourOfShake), y: NSMinY(frame))) + } + + shakePath.closeSubpath() + shakeAnimation.path = shakePath + shakeAnimation.duration = CFTimeInterval(durationOfShake) + window?.animations = [NSAnimatablePropertyKey(rawValue: "frameOrigin"):shakeAnimation] + window?.animator().setFrameOrigin(window!.frame.origin) + } +} diff --git a/Surf-Mac/PreferencesWindowController.xib b/Surf-Mac/PreferencesWindowController.xib new file mode 100644 index 0000000..ca3970f --- /dev/null +++ b/Surf-Mac/PreferencesWindowController.xib @@ -0,0 +1,477 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/QRCodeWindow.xib b/Surf-Mac/QRCodeWindow.xib new file mode 100644 index 0000000..c54ceb9 --- /dev/null +++ b/Surf-Mac/QRCodeWindow.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Mac/QRView.swift b/Surf-Mac/QRView.swift new file mode 100644 index 0000000..555d38f --- /dev/null +++ b/Surf-Mac/QRView.swift @@ -0,0 +1,19 @@ +// +// QRView.swift +// Surf +// +// Created by 孔祥波 on 12/12/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa + +class QRView: NSView { + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + // Drawing code here. + } + +} diff --git a/Surf-Mac/QrController.swift b/Surf-Mac/QrController.swift new file mode 100644 index 0000000..01ad5a9 --- /dev/null +++ b/Surf-Mac/QrController.swift @@ -0,0 +1,184 @@ +// +// ViewController.swift +// testReadScan +// +// Created by 孔祥波 on 08/12/2016. +// Copyright © 2016 Kong XiangBo. All rights reserved. +// + +import Cocoa +/// The tunnel delegate protocol. +import Foundation +import CoreGraphics +import AVFoundation +@objc public protocol BarcodeScanDelegate: class { + func barcodeScanDidScan(controller: QrController, configString:String) + func barcodeScanCancelScan(controller: QrController) + +} + + +public class QrController: NSObject,AVCaptureVideoDataOutputSampleBufferDelegate{ + + + let kScanQRCodeQueueName = "ScanQRCodeQueueName" + var captureSession: AVCaptureSession? + var input:AVCaptureScreenInput? + //AVCaptureOutput* output; + var lastResult : Bool! + var startDate:Date = Date() + weak var delegate:BarcodeScanDelegate? + + + var timeOut = 5.0 + + @IBAction func cancleAction(_ sender: AnyObject) { + guard let d = self.delegate else{ + return + } + //self.navigationController?.popViewController(animated:(<#T##animated: Bool##Bool#>) + d.barcodeScanCancelScan(controller: self) + } + func startReading() -> Bool{ + // let error: NSError? + if captureSession == nil { + //let captureDevice: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) + + //let input = try! AVCaptureDeviceInput(device: captureDevice) + + + input = AVCaptureScreenInput.init(displayID: CGMainDisplayID()) + input?.capturesMouseClicks = false + input?.minFrameDuration = CMTimeMake(1, 60); + input?.scaleFactor = 0.5 + input?.cropRect = NSScreen.screens.first!.frame + //self.input.cropRect = [self screenRect]; + captureSession = AVCaptureSession() + + captureSession?.sessionPreset = AVCaptureSession.Preset.low + captureSession?.addInput(input!) + + ///let captureMetadataOutput = AVCaptureMetadataOutput() + let captureMetadataOutput = AVCaptureVideoDataOutput() + captureMetadataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable as! String : Int(kCVPixelFormatType_32BGRA)] + captureSession?.addOutput(captureMetadataOutput) + + let dispatchQueue = DispatchQueue(label:kScanQRCodeQueueName) + captureMetadataOutput.setSampleBufferDelegate(self, queue: dispatchQueue) + + } + + + + + + if captureSession?.isRunning == false { + startDate = Date() + captureSession?.startRunning() + } + + + return true + } + + func stopReading(){ + captureSession?.stopRunning() + + } + public func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!){ + + + + let imageBuffer:CVImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!; + + + CVPixelBufferLockBaseAddress(imageBuffer,CVPixelBufferLockFlags(rawValue: 0)); // Lock the image buffer + + let baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); // Get information of the image + let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); + let width = CVPixelBufferGetWidth(imageBuffer); + let height = CVPixelBufferGetHeight(imageBuffer); + let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB(); + + //kCGBitmapByteOrder32Little + //CGBitmapInfo.init(rawValue: <#T##UInt32#>) + + let info = CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue + let newContext:CGContext = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace,bitmapInfo: info )!;// | kCGImageAlphaPremultipliedFirst + let newImage:CGImage = newContext.makeImage()!; + + + //CGColorSpaceRelease(colorSpace); + CVPixelBufferUnlockBaseAddress(imageBuffer,CVPixelBufferLockFlags(rawValue: 0)); + + //let bitmapRep :NSBitmapImageRep = NSBitmapImageRep.init(cgImage: newImage) + //let nsImage = NSImage.init(cgImage: newImage, size: CGSize.init(width: width, height: height)) + //let imageCompression :CGFloat = 0.5; + + + + self.scanImage(newImage) + + } + + + func reportScanResult(result:String!){ + stopReading() + + + guard let d = self.delegate else{ + return + } + let q = DispatchQueue.main + q.async {[weak self] in + d.barcodeScanDidScan(controller: self!, configString: result) + } + + } + + + func scanImage(_ image:CGImage){ + let ciImage:CIImage = CIImage(cgImage:image ) + var message:String = "" + let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) + + let features = detector!.features(in: ciImage) + + if features.count > 0{ + + for feature in features as! [CIQRCodeFeature]{ + message += feature.messageString! + } + print(message) + + + } + if message.isEmpty { + if Date().timeIntervalSince(startDate) > timeOut { + captureSession!.stopRunning() + guard let d = self.delegate else{ + return + } + let q = DispatchQueue.main + q.async {[weak self] in + d.barcodeScanCancelScan(controller: self!) + } + + }else { + + } + + }else { + reportScanResult(result:message) + } +// + + } + + deinit { + print("Qr Scan deinit") + } + + +} + diff --git a/Surf-Mac/QrWindowController.swift b/Surf-Mac/QrWindowController.swift new file mode 100644 index 0000000..a85582d --- /dev/null +++ b/Surf-Mac/QrWindowController.swift @@ -0,0 +1,54 @@ +// +// QrWindowController.swift +// Surf +// +// Created by 孔祥波 on 08/12/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa +import SFSocket +import CoreGraphics +import AppKit +import Xcon +class QrWindowController: NSWindowController { + + @IBOutlet var imageView: NSImageView! + var proxy:SFProxy! + override func windowDidLoad() { + super.windowDidLoad() + generateQRCodeScale(scale: 1.0) + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. + } + func generateQRCodeScale(scale:CGFloat){ + // + // ss://aes-256-cfb:fb4b532cb4180c9037c5b64bb3c09f7e@108.61.126.194:14860" + + let base64Encoded = proxy.base64String() + let stringData = base64Encoded.data(using: .utf8, allowLossyConversion: false) + let filter = CIFilter(name: "CIQRCodeGenerator") + guard let f = filter else { + return + } + f.setValue(stringData, forKey: "inputMessage") + f.setValue("M", forKey: "inputCorrectionLevel") + + guard let image = f.outputImage else { + return + } + + let cgImage = CIContext(options:nil).createCGImage(image, from:image.extent ) + let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB(); + let bytesPerRow = 2560 + let info = CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue + let newContext:CGContext = CGContext(data: nil, width: 500 , height: 500, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace,bitmapInfo: info )!; + newContext.interpolationQuality = .none + newContext.draw(cgImage!, in: CGRect.init(x: 0, y: 0, width: 500, height: 500)) + let newImage:CGImage = newContext.makeImage()!; + let nsImage = NSImage.init(cgImage:newImage, size: CGSize.init(width: 250 , height: 250)) + self.imageView.image = nsImage + + + + } +} diff --git a/Surf-Mac/SFApplication.swift b/Surf-Mac/SFApplication.swift new file mode 100644 index 0000000..6b7e7fd --- /dev/null +++ b/Surf-Mac/SFApplication.swift @@ -0,0 +1,40 @@ +// +// SFApplication.swift +// Surf +// +// Created by 孔祥波 on 25/11/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa +@objc(SFApplication) +class SFApplication: NSApplication { + override func sendEvent(_ event: NSEvent) { + if event.type == NSEvent.EventType.keyDown { + //NSEventModifierFlags + if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == NSEvent.ModifierFlags.command.rawValue { + switch event.charactersIgnoringModifiers!.lowercased() { + case "x": + if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return } + case "c": + if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return } + case "v": + if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return } + case "z": + if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return } + case "a": + if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return } + default: + break + } + } + else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue == (NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue)) { + if event.charactersIgnoringModifiers == "Z" { + if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return } + } + } + } + return super.sendEvent(event) + } + +} diff --git a/Surf-Mac/SFMono-Regular.otf b/Surf-Mac/SFMono-Regular.otf new file mode 100644 index 0000000..dc4febd Binary files /dev/null and b/Surf-Mac/SFMono-Regular.otf differ diff --git a/Surf-Mac/SWBQRCodeWindowController.swift b/Surf-Mac/SWBQRCodeWindowController.swift new file mode 100644 index 0000000..3b286c0 --- /dev/null +++ b/Surf-Mac/SWBQRCodeWindowController.swift @@ -0,0 +1,18 @@ +// +// SWBQRCodeWindowController.swift +// Surf +// +// Created by abigt on 2016/11/21. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Cocoa + +class SWBQRCodeWindowController: NSViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do view setup here. + } + +} diff --git a/Surf-Mac/StatusView.swift b/Surf-Mac/StatusView.swift new file mode 100644 index 0000000..26d4d4b --- /dev/null +++ b/Surf-Mac/StatusView.swift @@ -0,0 +1,164 @@ +// +// StatusView.swift +// Surf +// +// Created by 孔祥波 on 21/11/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa +import SFSocket +import XRuler +import NetworkExtension +import SwiftyJSON +class StatusView: NSView { + var report:SFVPNStatistics = SFVPNStatistics.shared + var reportTimer:Timer? + @IBOutlet weak var iconView: NSImageView! + @IBOutlet weak var upView: NSTextField! + @IBOutlet weak var downView: NSTextField! + @IBOutlet weak var upTrafficeView: NSTextField! + @IBOutlet weak var downTrafficView: NSTextField! + @IBOutlet weak var buttonView: NSButton! + override func awakeFromNib() { + let font = NSFont.init(name: "ionicons", size: 10) + config() + upView.font = font + + downView.font = font + downView.stringValue = "\u{f35d}" + + upView.stringValue = "\u{f366}" + + + + } + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + // Drawing code here. + } + func config(){ + if reportTimer == nil { + reportTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(StatusView.requestReportXPC(_:)), userInfo: nil, repeats: true) + return + }else { + if let t = reportTimer, !(t.isValid) { + reportTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(StatusView.requestReportXPC(_:)), userInfo: nil, repeats: true) + } + } + + } + @objc func requestReport(_ timer:Timer){ + let now = getInterfaceTraffic() + if now.TunSent != 0 && now.TunReceived != 0 { + //report.lastTraffice.tx = now.TunSent - + + if now.TunSent > report.totalTraffice.tx { + report.lastTraffice.tx = now.TunSent - report.totalTraffice.tx + + report.lastTraffice.rx = now.TunReceived - report.totalTraffice.rx + report.updateMax() + } + + + + report.totalTraffice.tx = now.TunSent + report.totalTraffice.rx = now.TunReceived + + let t = report.lastTraffice + + + upTrafficeView.stringValue = self.toString(x: t.tx,label: "",speed: true) + downTrafficView.stringValue = self.toString(x: t.rx,label: "",speed: true) + }else { + upTrafficeView.stringValue = "0 B/s" + downTrafficView.stringValue = "0 B/s" + } + //tableView.reloadData() + } + public func toString(x:UInt,label:String,speed:Bool) ->String { + + var s = "/s" + if !speed { + s = "" + } + + if x < 1024{ + return label + " \(x) B" + s + }else if x >= 1024 && x < 1024*1024 { + return label + String(format: "%d KB", Int(Float(x)/1024.0)) + s + }else if x >= 1024*1024 && x < 1024*1024*1024 { + //return label + "\(x/1024/1024) MB" + s + return label + String(format: "%d MB", Int(Float(x)/1024/1024)) + s + }else { + //return label + "\(x/1024/1024/1024) GB" + s + return label + String(format: "%d GB", Int(Float(x)/1024/1024/1024)) + s + } + + } + @objc func requestReportXPC(_ timer:Timer) { + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + //print("\(m.protocolConfiguration)") + let date = NSDate() + let me = SFVPNXPSCommand.STATUS.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8) + + { + do { + try session.sendProviderMessage(message) { [weak self] response in + // print("------\(Date()) %0.2f",Date().timeIntervalSince(d0)) + if response != nil { + self!.processData(data: response!) + //print("------\(Date()) %0.2f",Date().timeIntervalSince(d0)) + } else { + //self!.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + //alertMessageAction("Failed to Get result ",complete: nil) + } + }else { + //alertMessageAction("Connection not Stated",complete: nil) + } + }else { + //alertMessageAction("message dont init",complete: nil) + //tableView.reloadData() + } + + } + func processData(data:Data) { + + //results.removeAll() + //print("111") + //let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) + let obj = try! JSON.init(data: data) + if obj.error == nil { + + //alertMessageAction("message dont init",complete: nil) + report.map(j: obj) + + + + + //bug here + if let m = SFVPNManager.shared.manager, m.connection.status == .connected{ + //chartsView.updateFlow(report.netflow) + //chartsView.isHidden = false + if let last = report.netflow.totalFlows.last { + upTrafficeView.stringValue = self.toString(x: last.tx,label: "",speed: true) + downTrafficView.stringValue = self.toString(x: last.rx,label: "",speed: true) + } + + }else { + + } + //print(report.netflow.currentFlows) + + + + } + + } +} diff --git a/Surf-Mac/Surf-Mac.entitlements b/Surf-Mac/Surf-Mac.entitlements new file mode 100644 index 0000000..3ede36d --- /dev/null +++ b/Surf-Mac/Surf-Mac.entitlements @@ -0,0 +1,45 @@ + + + + + com.apple.application-identifier + 745WQDK4L7.com.abigt.Surf.mac + com.apple.developer.icloud-container-identifiers + + iCloud.com.abigt.Surf + + com.apple.developer.icloud-services + + CloudDocuments + + com.apple.developer.networking.networkextension + + app-proxy-provider + packet-tunnel-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + com.apple.developer.team-identifier + 745WQDK4L7 + com.apple.developer.ubiquity-container-identifiers + + iCloud.com.abigt.Surf + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + 745WQDK4L7.com.abigt.Surf + + com.apple.security.network.client + + com.apple.security.network.server + + keychain-access-groups + + 745WQDK4L7.* + + + diff --git a/Surf-Mac/Surf-Mac.xcconfig b/Surf-Mac/Surf-Mac.xcconfig new file mode 100644 index 0000000..27f5dec --- /dev/null +++ b/Surf-Mac/Surf-Mac.xcconfig @@ -0,0 +1,13 @@ +// +// Surf-Mac.xcconfig +// Surf +// +// Created by 孔祥波 on 16/5/12. +// Copyright © 2016年 abigt. All rights reserved. +// + +HEADER_SEARCH_PATHS = $(inherited) // "$(SRCROOT)/MMDB" + +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/Carthage/Build/Mac/" +HEADER_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/share/include" "$(SRCROOT)/share/include/sodium" "$(SRCROOT)/Shared/header" "$(SRCROOT)/MMDB" "$(SRCROOT)/shared/lwip/badvpn" +USER_HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/Shared/header" "$(SRCROOT)/shared/lwip/src/include/"** "$(SRCROOT)/shared/lwip/custom" "$(SRCROOT)/Shared/proxy/ss" diff --git a/Surf-Mac/ViewController.swift b/Surf-Mac/ViewController.swift new file mode 100644 index 0000000..dfe72c3 --- /dev/null +++ b/Surf-Mac/ViewController.swift @@ -0,0 +1,190 @@ +// +// ViewController.swift +// Surf-Mac +// +// Created by abigt on 15/12/22. +// Copyright © 2015年 abigt. All rights reserved. +// + +import Cocoa +import NetworkExtension +import AppKit +import SFSocket +import Xcon +import XRuler +//import SFSocket +func SSLog(_ object: T, _ file: String = #file, _ function: String = #function, _ line: Int = #line) { + //let fn = file.split { $0 == "/" }.last + let fn = file.split { $0 == "/" }.map(String.init).last + if let f = fn { + let info = "\(f).\(function)[\(line)]:\(object)" + NSLog(info) + } +} +class MainViewController: NSViewController { + + @IBOutlet weak var hostField: NSTextField! + @IBOutlet weak var portField: NSTextField! + @IBOutlet weak var method: NSTextField! + @IBOutlet weak var password: NSSecureTextField! + @IBOutlet weak var actionButton: NSButton! + @IBOutlet weak var statusView: NSImageView! + var targetManager : NEVPNManager? + + //var proxy:SFProxy = SFProxy.init(name: "Proxy", type: .SS, address: "", port: "" , passwd:"", method: "", tls: false) + + @IBAction func saveServer(_ sender: AnyObject) { + + + if let proxy = SFProxy.create(name: "server", type: .SS, address:self.hostField.stringValue, port: self.portField.stringValue, passwd: self.password.stringValue, method: self.method.stringValue, tls: false) { + _ = ProxyGroupSettings.share.addProxy(proxy) + do { + try ProxyGroupSettings.share.save() + }catch let e { + print("\(e.localizedDescription)") + } + }else { + //todo + } + + } + var logUrl:NSURL = { + + + let url = fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + return url.appendingPathComponent("Log") as NSURL + }() + + /// A list of NEVPNManager objects for the packet tunnel configurations. + var managers = [NEVPNManager]() + override func viewDidLoad() { + super.viewDidLoad() + reloadManagers() + // Do any additional setup after loading the view. + } + + @IBAction func showLog(_ sender: AnyObject) { + + NSWorkspace.shared.open(logUrl as URL) + + } + @IBAction func showLogUseTerminal(_ sender: AnyObject) { + + if NSWorkspace.shared.openFile(logUrl.path!, withApplication:"Terminal") { + + }else { + SSLog("can't open") + } + + } + @IBAction func showAppDir(_ sender: AnyObject) { + //let urls = FileManager.default.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) + let url = Bundle.main.bundleURL + if NSWorkspace.shared.openFile(url.path, withApplication:"Terminal") { + + }else { + //SSLog("can't open") + } + } + override var representedObject: Any? { + didSet { + // Update the view, if already loaded. + } + } + + func reloadManagers() { + SFVPNManager.shared.loadManager {[weak self] (m, error) in + if let _ = m { + SFVPNManager.shared.xpc() + if let ss = self { + ss.observeStatus() + ss.actionButton.isEnabled = true + } + } + + + } + } + + + func readImage(name:String) ->NSImage?{ + + guard let p = Bundle.main.path(forResource:name, ofType: "png")else { + return nil + } + return NSImage(contentsOfFile: p) + + } + func refreshProfile(){ + + } + func showStatus(_ status:NEVPNStatus){ + + switch status{ + case .disconnected: + statusView.image = NSImage.init(named:NSImage.Name(rawValue: "GrayDot")) + SSLog("Disconnected") + case .invalid: + statusView.image = NSImage.init(named: NSImage.Name(rawValue: "RedDot")) + SSLog("Invalid") + case .connected: + statusView.image = NSImage.init(named:NSImage.Name(rawValue: "GreenDot")) + SSLog("Connected") + case .connecting: + statusView.image = NSImage.init(named:NSImage.Name(rawValue: "GreenDot")) + SSLog("Connecting") + case .disconnecting: + statusView.image = NSImage.init(named:NSImage.Name(rawValue: "RedDot")) + SSLog("Disconnecting") + case .reasserting: + statusView.image = NSImage.init(named:NSImage.Name(rawValue: "RedDot")) + SSLog("Reasserting") + } + + + } + /// Register for configuration change notifications. + func observeStatus() { + if let m = SFVPNManager.shared.manager{ + NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: m.connection, queue: OperationQueue.main, using: { [weak self ] notification in + //self.tableView.reloadRowsAtIndexPaths([ NSIndexPath(forRow: index, inSection: 0) ], withRowAnimation: .Fade) + print(index) + if let s = self{ + s.showStatus(m.connection.status) + } + print(m.connection.status) + }) + } + } + /// De-register for configuration change notifications. + func stopObservingStatus() { + if let m = SFVPNManager.shared.manager { + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: m.connection) + } + + } + @IBAction func connectVPN(_ sender: AnyObject){ + do { + _ = try SFVPNManager.shared.startStopToggled("") + }catch _ { + + } + + } + + + @IBAction func addVPN(_ sender: AnyObject) { + _ = SFVPNManager.shared.loadManager { [weak self](manager, error) in + + if let strong = self, let manager = manager { + strong.test(manager) + } + + } + + } + func test(_ mangaer:NETunnelProviderManager){ + + } +} + diff --git a/Surf-Mac/en.lproj/InfoPlist.strings b/Surf-Mac/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..8202f43 --- /dev/null +++ b/Surf-Mac/en.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* + InfoPlist.strings + Surf + + Created by 孔祥波 on 16/12/2016. + Copyright © 2016 abigt. All rights reserved. +*/ +"CFBundleDisplayName" = "A.BIG.T"; +"CFBundleName" = "A.BIG.T"; diff --git a/Surf-Mac/genjson.py b/Surf-Mac/genjson.py new file mode 100644 index 0000000..f42968b --- /dev/null +++ b/Surf-Mac/genjson.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +#coding=utf-8 + +import json +import sys +import re +config = {} +General = {} +Proxy = {} +Rule = {} +DOMAINKEYWORD = {} +DOMAINSUFFIX = {} +IPCIDR = {} + + +def fread(file): + dict = {} + i = 0 + for line in file: + i = i+ 1 + print ++i + if re.match('#', line): + print "# and pass" + continue + if re.match('//', line): + print "// and pass" + continue + if len(line) <=2: + print "no need" + line + continue + + if re.match('\[General\]', line): + print "Found General" + dict = General + continue + elif re.match('\[Proxy\]', line): + print "Found Proxy" + dict = Proxy + continue + elif re.match('\[Rule\]', line): + dict = Rule + print "Found Proxy" + continue + else : + #print "Not found block this is rule" + + pass + #print line + list = line.split('=') + if len(list) >1: + print list + x = list[1].split(',') + if len(x)> 1: + if dict == Proxy: + hostconfig = {} + hostconfig['protocol'] = x[0].strip() + hostconfig['host'] = x[1].strip() + hostconfig['port'] = x[2].strip() + hostconfig['methd'] = x[3].strip() + hostconfig['passwd'] = x[4].strip() + #hostconfig['xx'] = x[5] + dict[list[0]] = hostconfig + else: + print line + dict[list[0]] = [str(j).strip() for j in x] + else: + dict[list[0]] = list[1] + + else: + if re.match('DOMAIN-KEYWORD',line): + k = line.split(',') + #k.remove(k[0]) + #r = ', '.join([str(x) for x in k]) + rule = {} + rule["Proxy"] = k[2].strip() + try: + rule["force-remote-dns"] = k[3].strip() + except Exception, e: + print e + + DOMAINKEYWORD[k[1]] = rule + elif re.match('DOMAIN-SUFFIX',line): + k = line.split(',') + #k.remove(k[0]) + #r = ', '.join([str(x) for x in k]) + rule = {} + rule["Proxy"] = k[2].strip() + try: + rule["force-remote-dns"] = k[3].strip() + except Exception, e: + print e + + DOMAINSUFFIX[k[1]] = rule + elif re.match('IP-CIDR',line): + k = line.split(',') + #k.remove(k[0]) + #r = ', '.join([str(x) for x in k]) + rule = {} + rule["Proxy"] = k[2].strip() + try: + rule["no-resolve"] = k[3].strip() + except Exception, e: + print e + + IPCIDR[k[1]] = rule + else: + pass + #print dict + print "[General]" + print General + General["author"] = "yarshure" + General["commnet"] = "这是comment" + print "[Proxy]" + print Proxy + print "[Rule]" + Rule["DOMAIN-KEYWORD"] = DOMAINKEYWORD + Rule["DOMAIN-SUFFIX"] = DOMAINSUFFIX + Rule["IP-CIDR"] = IPCIDR + #print Rule + print "cool" + config["General"] = General + config["Proxy"] = Proxy + config["Rule"] = Rule + + saveRuslt() + # print "[DOMAINKEYWORD]" + # print DOMAINKEYWORD + # print "[DOMAINSUFFIX]" + # print DOMAINSUFFIX + # print "[IPCIDR]" + # print IPCIDR +def saveRuslt(): + #print config + s = json.dumps(config) + f = open("surf.conf","w") + f.write(s) + f.close() +if __name__ == '__main__': + if len(sys.argv) == 1: + print "add surge file path" + surgeconfig = sys.argv[1] + print surgeconfig + file = open(surgeconfig) + fread(file) + file.close() \ No newline at end of file diff --git a/Surf-Mac/icon.icns b/Surf-Mac/icon.icns new file mode 100644 index 0000000..707f269 Binary files /dev/null and b/Surf-Mac/icon.icns differ diff --git a/Surf-Mac/mayflow.config b/Surf-Mac/mayflow.config new file mode 100644 index 0000000..8770eb4 --- /dev/null +++ b/Surf-Mac/mayflow.config @@ -0,0 +1,3700 @@ +# BRICKS Surge configuration file by @leaskh'; +# Get Info: https://github.com/leask/bricks +# Based on: http://surge.run/config-example/ss-module.conf + +[General] +loglevel = notify +bypass-system = true +skip-proxy = 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, localhost, *.local +# dns-server = 8.8.8.8, 8.8.4.4 +bypass-tun = 0.0.0.0/8, 1.0.0.0/9, 1.160.0.0/11, 1.192.0.0/11, 10.0.0.0/8, 14.0.0.0/11, 14.96.0.0/11, 14.128.0.0/11, 14.192.0.0/11, 27.0.0.0/10, 27.96.0.0/11, 27.128.0.0/9, 36.0.0.0/10, 36.96.0.0/11, 36.128.0.0/9, 39.0.0.0/11, 39.64.0.0/10, 39.128.0.0/10, 42.0.0.0/8, 43.224.0.0/11, 45.64.0.0/10, 47.64.0.0/10, 49.0.0.0/9, 49.128.0.0/11, 49.192.0.0/10, 54.192.0.0/11, 58.0.0.0/9, 58.128.0.0/11, 58.192.0.0/10, 59.32.0.0/11, 59.64.0.0/10, 59.128.0.0/9, 60.0.0.0/10, 60.160.0.0/11, 60.192.0.0/10, 61.0.0.0/10, 61.64.0.0/11, 61.128.0.0/10, 61.224.0.0/11, 100.64.0.0/10, 101.0.0.0/9, 101.128.0.0/11, 101.192.0.0/10, 103.0.0.0/10, 103.192.0.0/10, 106.0.0.0/9, 106.224.0.0/11, 110.0.0.0/7, 112.0.0.0/9, 112.128.0.0/11, 112.192.0.0/10, 113.0.0.0/9, 113.128.0.0/11, 113.192.0.0/10, 114.0.0.0/9, 114.128.0.0/11, 114.192.0.0/10, 115.0.0.0/8, 116.0.0.0/8, 117.0.0.0/9, 117.128.0.0/10, 118.0.0.0/11, 118.64.0.0/10, 118.128.0.0/9, 119.0.0.0/9, 119.128.0.0/10, 119.224.0.0/11, 120.0.0.0/10, 120.64.0.0/11, 120.128.0.0/11, 120.192.0.0/10, 121.0.0.0/9, 121.192.0.0/10, 122.0.0.0/7, 124.0.0.0/8, 125.0.0.0/9, 125.160.0.0/11, 125.192.0.0/10, 127.0.0.0/8, 139.0.0.0/11, 139.128.0.0/9, 140.64.0.0/11, 140.128.0.0/11, 140.192.0.0/10, 144.0.0.0/10, 144.96.0.0/11, 144.224.0.0/11, 150.0.0.0/11, 150.96.0.0/11, 150.128.0.0/11, 150.192.0.0/10, 152.96.0.0/11, 153.0.0.0/10, 153.96.0.0/11, 157.0.0.0/10, 157.96.0.0/11, 157.128.0.0/11, 157.224.0.0/11, 159.224.0.0/11, 161.192.0.0/11, 162.96.0.0/11, 163.0.0.0/10, 163.96.0.0/11, 163.128.0.0/10, 163.192.0.0/11, 166.96.0.0/11, 167.128.0.0/10, 167.192.0.0/11, 168.160.0.0/11, 169.254.0.0/16, 171.0.0.0/9, 171.192.0.0/11, 172.16.0.0/12, 175.0.0.0/9, 175.128.0.0/10, 180.64.0.0/10, 180.128.0.0/9, 182.0.0.0/8, 183.0.0.0/10, 183.64.0.0/11, 183.128.0.0/9, 192.0.0.0/24, 192.0.2.0/24, 192.88.99.0/24, 192.96.0.0/11, 192.160.0.0/11, 198.18.0.0/15, 198.51.100.0/24, 202.0.0.0/9, 202.128.0.0/10, 202.192.0.0/11, 203.0.0.0/9, 203.128.0.0/10, 203.192.0.0/11, 210.0.0.0/10, 210.64.0.0/11, 210.160.0.0/11, 210.192.0.0/11, 211.64.0.0/10, 211.128.0.0/10, 218.0.0.0/9, 218.160.0.0/11, 218.192.0.0/10, 219.64.0.0/11, 219.128.0.0/11, 219.192.0.0/10, 220.96.0.0/11, 220.128.0.0/9, 221.0.0.0/11, 221.96.0.0/11, 221.128.0.0/9, 222.0.0.0/8, 223.0.0.0/11, 223.64.0.0/10, 223.128.0.0/9, 192.168.0.0/16 + +[Proxy] +Proxy = http, mf-cdn.senditc.cn, 34208, , + +[Rule] +DOMAIN-KEYWORD,google,Proxy,force-remote-dns +DOMAIN-KEYWORD,facebook,Proxy,force-remote-dns +DOMAIN-KEYWORD,youtube,Proxy,force-remote-dns +DOMAIN-KEYWORD,twitter,Proxy,force-remote-dns +DOMAIN-KEYWORD,instagram,Proxy,force-remote-dns +DOMAIN-KEYWORD,gmail,Proxy,force-remote-dns +DOMAIN-KEYWORD,blogspot,Proxy +DOMAIN-SUFFIX,twimg.com,Proxy,force-remote-dns + +# Remove these lines below if you don't have trouble accessing Apple resources +# Disabled by @Leaskh { +# DOMAIN-SUFFIX,ls.apple.com,DIRECT +# DOMAIN-SUFFIX,lcdn-registration.apple.com,DIRECT +# DOMAIN-SUFFIX,apple.com,Proxy +# DOMAIN-SUFFIX,mzstatic.com,Proxy +# DOMAIN-SUFFIX,itunes.com,Proxy +# DOMAIN-SUFFIX,icloud.com,Proxy +# } + +DOMAIN-SUFFIX,0rz.tw,Proxy +DOMAIN-SUFFIX,0to255.com,Proxy +DOMAIN-SUFFIX,1024.inc.gs,Proxy +DOMAIN-SUFFIX,10conditionsoflove.com,Proxy +DOMAIN-SUFFIX,10musume.com,Proxy +DOMAIN-SUFFIX,123rf.com,Proxy +DOMAIN-SUFFIX,12bet.com,Proxy +DOMAIN-SUFFIX,12vpn.com,Proxy +DOMAIN-SUFFIX,141hongkong.com,Proxy +DOMAIN-SUFFIX,173ng.com,Proxy +DOMAIN-SUFFIX,174.142.105.153,Proxy +DOMAIN-SUFFIX,17t17p.com,Proxy +DOMAIN-SUFFIX,1984bbs.com,Proxy +DOMAIN-SUFFIX,1984bbs.org,Proxy +DOMAIN-SUFFIX,199.59.148.20,Proxy +DOMAIN-SUFFIX,1998cdp.org,Proxy +DOMAIN-SUFFIX,1-apple.com.tw,Proxy +DOMAIN-SUFFIX,1bao.org,Proxy +DOMAIN-SUFFIX,1eew.com,Proxy +DOMAIN-SUFFIX,1pondo.tv,Proxy +DOMAIN-SUFFIX,2000fun.com,Proxy +DOMAIN-SUFFIX,2008xianzhang.info,Proxy +DOMAIN-SUFFIX,213.so,Proxy +DOMAIN-SUFFIX,21andy.com,Proxy +DOMAIN-SUFFIX,228.net.tw,Proxy +DOMAIN-SUFFIX,24smile.org,Proxy +DOMAIN-SUFFIX,2-hand.info,Proxy +DOMAIN-SUFFIX,2shared.com,Proxy +DOMAIN-SUFFIX,301works.org,Proxy +DOMAIN-SUFFIX,315lz.com,Proxy +DOMAIN-SUFFIX,32red.com,Proxy +DOMAIN-SUFFIX,365singles.com.ar,Proxy +DOMAIN-SUFFIX,36rain.com,Proxy +DOMAIN-SUFFIX,3a5a.com,Proxy +DOMAIN-SUFFIX,3boys2girls.com,Proxy +DOMAIN-SUFFIX,3tui.net,Proxy +DOMAIN-SUFFIX,4bluestones.biz,Proxy +DOMAIN-SUFFIX,4chan.org,Proxy +DOMAIN-SUFFIX,4shared.com,Proxy +DOMAIN-SUFFIX,4sq.com,Proxy +DOMAIN-SUFFIX,4sqi.net,Proxy +DOMAIN-SUFFIX,51.ca,Proxy +DOMAIN-SUFFIX,5i01.com,Proxy +DOMAIN-SUFFIX,5isotoi5.org,Proxy +DOMAIN-SUFFIX,5maodang.com,Proxy +DOMAIN-SUFFIX,64museum.org,Proxy +DOMAIN-SUFFIX,6-4.net,Proxy +DOMAIN-SUFFIX,64tianwang.com,Proxy +DOMAIN-SUFFIX,64wiki.com,Proxy +DOMAIN-SUFFIX,666kb.com,Proxy +DOMAIN-SUFFIX,67.220.91.18,Proxy +DOMAIN-SUFFIX,67.220.91.23,Proxy +DOMAIN-SUFFIX,69.65.19.160,Proxy +DOMAIN-SUFFIX,6park.com,Proxy +DOMAIN-SUFFIX,6v6dota.com,Proxy +DOMAIN-SUFFIX,72.52.81.22,Proxy +DOMAIN-SUFFIX,7capture.com,Proxy +DOMAIN-SUFFIX,84000.co,Proxy +DOMAIN-SUFFIX,85.17.73.31,Proxy +DOMAIN-SUFFIX,85st.com,Proxy +DOMAIN-SUFFIX,881903.com,Proxy +DOMAIN-SUFFIX,888.com,Proxy +DOMAIN-SUFFIX,89-64.org,Proxy +DOMAIN-SUFFIX,9001700.com,Proxy +DOMAIN-SUFFIX,908taiwan.org,Proxy +DOMAIN-SUFFIX,91porn.com,Proxy +DOMAIN-SUFFIX,92ccav.com,Proxy +DOMAIN-SUFFIX,9bis.com,Proxy +DOMAIN-SUFFIX,9bis.net,Proxy +DOMAIN-SUFFIX,9to5mac.com,Proxy +DOMAIN-SUFFIX,a5.com.ru,Proxy +DOMAIN-SUFFIX,aamacau.com,Proxy +DOMAIN-SUFFIX,aarki.net,Proxy +DOMAIN-SUFFIX,abc.pp.ru,Proxy +DOMAIN-SUFFIX,abc.xyz,Proxy +DOMAIN-SUFFIX,abercrombie.com,Proxy +DOMAIN-SUFFIX,abitno.linpie.com,Proxy +DOMAIN-SUFFIX,ablwang.com,Proxy +DOMAIN-SUFFIX,aboluowang.com,Proxy +DOMAIN-SUFFIX,aboutgfw.com,Proxy +DOMAIN-SUFFIX,acgkj.com,Proxy +DOMAIN-SUFFIX,ac.jiruan.net,Proxy +DOMAIN-SUFFIX,actimes.com.au,Proxy +DOMAIN-SUFFIX,aculo.us,Proxy +DOMAIN-SUFFIX,adblockplus.org,Proxy +DOMAIN-SUFFIX,addictedtocoffee.de,Proxy +DOMAIN-SUFFIX,addthis.com,Proxy +DOMAIN-SUFFIX,adult.friendfinder.com,Proxy +DOMAIN-SUFFIX,adultfriendfinder.com,Proxy +DOMAIN-SUFFIX,adultkeep.net,Proxy +DOMAIN-SUFFIX,advanscene.com,Proxy +DOMAIN-SUFFIX,advertfan.com,Proxy +DOMAIN-SUFFIX,ae.hao123.com,Proxy +DOMAIN-SUFFIX,aenhancers.com,Proxy +DOMAIN-SUFFIX,af.mil,Proxy +DOMAIN-SUFFIX,agoogleaday.com,Proxy +DOMAIN-SUFFIX,aiph.net,Proxy +DOMAIN-SUFFIX,aisex.com,Proxy +DOMAIN-SUFFIX,ait.org.tw,Proxy +DOMAIN-SUFFIX,aiweiweiblog.com,Proxy +DOMAIN-SUFFIX,aiweiwei.com,Proxy +DOMAIN-SUFFIX,ajaxplorer.info,Proxy +DOMAIN-SUFFIX,ajsands.com,Proxy +DOMAIN-SUFFIX,akamaihd.net,Proxy +DOMAIN-SUFFIX,akamai.net,Proxy +DOMAIN-SUFFIX,akiba-online.com,Proxy +DOMAIN-SUFFIX,alabout.com,Proxy +DOMAIN-SUFFIX,alasbarricadas.org,Proxy +DOMAIN-SUFFIX,alexlur.org,Proxy +DOMAIN-SUFFIX,aliengu.com,Proxy +DOMAIN-SUFFIX,alien-ufos.com,Proxy +DOMAIN-SUFFIX,alkasir.com,Proxy +DOMAIN-SUFFIX,allaboutalpha.com,Proxy +DOMAIN-SUFFIX,allgirlsallowed.org,Proxy +DOMAIN-SUFFIX,alliance.org.hk,Proxy +DOMAIN-SUFFIX,allinfa.com,Proxy +DOMAIN-SUFFIX,allinfo.com,Proxy +DOMAIN-SUFFIX,allmovie.com,Proxy +DOMAIN-SUFFIX,allonlinux.free.fr,Proxy +DOMAIN-SUFFIX,all-that-is-interesting.com,Proxy +DOMAIN-SUFFIX,al-qimmah.net,Proxy +DOMAIN-SUFFIX,alternate-tools.com,Proxy +DOMAIN-SUFFIX,altrec.com,Proxy +DOMAIN-SUFFIX,alvinalexander.com,Proxy +DOMAIN-SUFFIX,alwaysdata.com,Proxy +DOMAIN-SUFFIX,alwaysdata.net,Proxy +DOMAIN-SUFFIX,am730.com.hk,Proxy +DOMAIN-SUFFIX,amazonaws.com,Proxy +DOMAIN-SUFFIX,amazon.com,Proxy +DOMAIN-SUFFIX,ameblo.jp,Proxy +DOMAIN-SUFFIX,americangreencard.com,Proxy +DOMAIN-SUFFIX,amiblockedornot.com,Proxy +DOMAIN-SUFFIX,amnesty.org,Proxy +DOMAIN-SUFFIX,amnestyusa.org,Proxy +DOMAIN-SUFFIX,amnyemachen.org,Proxy +DOMAIN-SUFFIX,amoiist.com,Proxy +DOMAIN-SUFFIX,ampproject.org,Proxy +DOMAIN-SUFFIX,amusingplanet.com,Proxy +DOMAIN-SUFFIX,amzs.me,Proxy +DOMAIN-SUFFIX,analyze-v.com,Proxy +DOMAIN-SUFFIX,anchorfree.com,Proxy +DOMAIN-SUFFIX,ancsconf.org,Proxy +DOMAIN-SUFFIX,andfaraway.net,Proxy +DOMAIN-SUFFIX,android.com,Proxy +DOMAIN-SUFFIX,android-x86.org,Proxy +DOMAIN-SUFFIX,angularjs.org,Proxy +DOMAIN-SUFFIX,animecrazy.net,Proxy +DOMAIN-SUFFIX,aniscartujo.com,Proxy +DOMAIN-SUFFIX,anobii.com,Proxy +DOMAIN-SUFFIX,anontext.com,Proxy +DOMAIN-SUFFIX,anonymizer.com,Proxy +DOMAIN-SUFFIX,anonym.to,Proxy +DOMAIN-SUFFIX,a-normal-day.com,Proxy +DOMAIN-SUFFIX,answering-islam.org,Proxy +DOMAIN-SUFFIX,antd.org,Proxy +DOMAIN-SUFFIX,anthonycalzadilla.com,Proxy +DOMAIN-SUFFIX,anti.anti.cnn.googlepages.com,Proxy +DOMAIN-SUFFIX,antidrm.hpg.ig.com.br,Proxy +DOMAIN-SUFFIX,antiwave.net,Proxy +DOMAIN-SUFFIX,aobo.com.au,Proxy +DOMAIN-SUFFIX,aolchannels.aol.com,Proxy +DOMAIN-SUFFIX,aolnews.com,Proxy +DOMAIN-SUFFIX,aomiwang.com,Proxy +DOMAIN-SUFFIX,apetube.com,Proxy +DOMAIN-SUFFIX,apiary.io,Proxy +DOMAIN-SUFFIX,apidocs.linksalpha.com,Proxy +DOMAIN-SUFFIX,apigee.com,Proxy +DOMAIN-SUFFIX,api.linksalpha.com,Proxy +DOMAIN-SUFFIX,api.path.com,Proxy +DOMAIN-SUFFIX,api.proxlet.com,Proxy +DOMAIN-SUFFIX,api.supertweet.net,Proxy +DOMAIN-SUFFIX,app.box.com,Proxy +DOMAIN-SUFFIX,app.heywire.com,Proxy +DOMAIN-SUFFIX,app.hkatvnews.com,Proxy +DOMAIN-SUFFIX,appleactionews.com,Proxy +DOMAIN-SUFFIX,appledaily.com,Proxy +DOMAIN-SUFFIX,appledaily.com.hk,Proxy +DOMAIN-SUFFIX,appledaily.com.tw,Proxy +DOMAIN-SUFFIX,apps.admob.com,Proxy +DOMAIN-SUFFIX,apps.hloli.net,Proxy +DOMAIN-SUFFIX,appspot.com,Proxy +DOMAIN-SUFFIX,aprs.net,Proxy +DOMAIN-SUFFIX,archdaily.net,Proxy +DOMAIN-SUFFIX,archive.is,Proxy +DOMAIN-SUFFIX,archive.org,Proxy +DOMAIN-SUFFIX,archlinuxarm.org,Proxy +DOMAIN-SUFFIX,arctosia.com,Proxy +DOMAIN-SUFFIX,areca-backup.org,Proxy +DOMAIN-SUFFIX,ar.hao123.com,Proxy +DOMAIN-SUFFIX,arlingtoncemetery.mil,Proxy +DOMAIN-SUFFIX,army.mil,Proxy +DOMAIN-SUFFIX,art-or-porn.com,Proxy +DOMAIN-SUFFIX,artsy.net,Proxy +DOMAIN-SUFFIX,ar.wikipedia.org,Proxy +DOMAIN-SUFFIX,asahichinese.com,Proxy +DOMAIN-SUFFIX,asana.com,Proxy +DOMAIN-SUFFIX,asdfg.jp,Proxy +DOMAIN-SUFFIX,asiaharvest.org,Proxy +DOMAIN-SUFFIX,asianews.it,Proxy +DOMAIN-SUFFIX,asianspiss.com,Proxy +DOMAIN-SUFFIX,asianwomensfilm.de,Proxy +DOMAIN-SUFFIX,askstudent.com,Proxy +DOMAIN-SUFFIX,askynz.net,Proxy +DOMAIN-SUFFIX,assembla.com,Proxy +DOMAIN-SUFFIX,assembly.com,Proxy +DOMAIN-SUFFIX,assets-yammer.com,Proxy +DOMAIN-SUFFIX,astonmartinnews.com,Proxy +DOMAIN-SUFFIX,astrill.com,Proxy +DOMAIN-SUFFIX,atchinese.com,Proxy +DOMAIN-SUFFIX,atc.org.au,Proxy +DOMAIN-SUFFIX,atdmt.com,Proxy +DOMAIN-SUFFIX,atgfw.org,Proxy +DOMAIN-SUFFIX,atj.org.tw,Proxy +DOMAIN-SUFFIX,atlaspost.com,Proxy +DOMAIN-SUFFIX,atnext.com,Proxy +DOMAIN-SUFFIX,avaaz.org,Proxy +DOMAIN-SUFFIX,avast.com,Proxy +DOMAIN-SUFFIX,avdb.in,Proxy +DOMAIN-SUFFIX,avdb.tv,Proxy +DOMAIN-SUFFIX,avidemux.org,Proxy +DOMAIN-SUFFIX,avoision.com,Proxy +DOMAIN-SUFFIX,awardwinningfjords.com,Proxy +DOMAIN-SUFFIX,axureformac.com,Proxy +DOMAIN-SUFFIX,azubu.tv,Proxy +DOMAIN-SUFFIX,babynet.com.hk,Proxy +DOMAIN-SUFFIX,backchina.com,Proxy +DOMAIN-SUFFIX,backpackers.com.tw,Proxy +DOMAIN-SUFFIX,backtotiananmen.com,Proxy +DOMAIN-SUFFIX,badassjs.com,Proxy +DOMAIN-SUFFIX,badoo.com,Proxy +DOMAIN-SUFFIX,baidu.jp,Proxy +DOMAIN-SUFFIX,baixing.me,Proxy +DOMAIN-SUFFIX,bannedbook.org,Proxy +DOMAIN-SUFFIX,barenakedislam.com,Proxy +DOMAIN-SUFFIX,barnabu.co.uk,Proxy +DOMAIN-SUFFIX,basetimesheightdividedby2.com,Proxy +DOMAIN-SUFFIX,bayvoice.net,Proxy +DOMAIN-SUFFIX,bbcchinese.com,Proxy +DOMAIN-SUFFIX,bbc.co,Proxy +DOMAIN-SUFFIX,bbc.com,Proxy +DOMAIN-SUFFIX,bbc.co.uk,Proxy +DOMAIN-SUFFIX,bbci.co.uk,Proxy +DOMAIN-SUFFIX,bbc.in,Proxy +DOMAIN-SUFFIX,bbg.gov,Proxy +DOMAIN-SUFFIX,bbs.cantonese.asia,Proxy +DOMAIN-SUFFIX,bbs.ecstart.com,Proxy +DOMAIN-SUFFIX,bbsfeed.com,Proxy +DOMAIN-SUFFIX,bbs.hanminzu.org,Proxy +DOMAIN-SUFFIX,bbs.kimy.com.tw,Proxy +DOMAIN-SUFFIX,bbsland.com,Proxy +DOMAIN-SUFFIX,bbs.morbell.com,Proxy +DOMAIN-SUFFIX,bbs.mychat.to,Proxy +DOMAIN-SUFFIX,bbsone.com,Proxy +DOMAIN-SUFFIX,bbs.ozchinese.com,Proxy +DOMAIN-SUFFIX,bbs.qmzdd.com,Proxy +DOMAIN-SUFFIX,bbs.sina.com,Proxy +DOMAIN-SUFFIX,bbs.skykiwi.com,Proxy +DOMAIN-SUFFIX,bbs.soul-plus.net,Proxy +DOMAIN-SUFFIX,bbs.tuitui.info,Proxy +DOMAIN-SUFFIX,bb.ttv.com.tw,Proxy +DOMAIN-SUFFIX,bcc.com.tw,Proxy +DOMAIN-SUFFIX,bcchinese.net,Proxy +DOMAIN-SUFFIX,bd.zhe.la,Proxy +DOMAIN-SUFFIX,beanstalkapp.com,Proxy +DOMAIN-SUFFIX,bebo.com,Proxy +DOMAIN-SUFFIX,beeg.com,Proxy +DOMAIN-SUFFIX,behindkink.com,Proxy +DOMAIN-SUFFIX,beijing1989.com,Proxy +DOMAIN-SUFFIX,beijingspring.com,Proxy +DOMAIN-SUFFIX,benjaminste.in,Proxy +DOMAIN-SUFFIX,berlintwitterwall.com,Proxy +DOMAIN-SUFFIX,bestforchina.org,Proxy +DOMAIN-SUFFIX,bestofyoutube.com,Proxy +DOMAIN-SUFFIX,bestvpn.com,Proxy +DOMAIN-SUFFIX,bestvpnservice.com,Proxy +DOMAIN-SUFFIX,bestvpnusa.com,Proxy +DOMAIN-SUFFIX,bet365.com,Proxy +DOMAIN-SUFFIX,beta.iset.com.tw,Proxy +DOMAIN-SUFFIX,beta.usejump.com,Proxy +DOMAIN-SUFFIX,betfair.com,Proxy +DOMAIN-SUFFIX,bettween.com,Proxy +DOMAIN-SUFFIX,betvictor.com,Proxy +DOMAIN-SUFFIX,bewww.net,Proxy +DOMAIN-SUFFIX,beyondfirewall.com,Proxy +DOMAIN-SUFFIX,bfnn.org,Proxy +DOMAIN-SUFFIX,bfsh.hk,Proxy +DOMAIN-SUFFIX,biantailajiao.com,Proxy +DOMAIN-SUFFIX,biantailajiao.in,Proxy +DOMAIN-SUFFIX,biblesforamerica.org,Proxy +DOMAIN-SUFFIX,bic2011.org,Proxy +DOMAIN-SUFFIX,bigfools.com,Proxy +DOMAIN-SUFFIX,bignews.org,Proxy +DOMAIN-SUFFIX,bigsound.org,Proxy +DOMAIN-SUFFIX,bill2-software.com,Proxy +DOMAIN-SUFFIX,billypan.com,Proxy +DOMAIN-SUFFIX,billywr.com,Proxy +DOMAIN-SUFFIX,bill.zhong.pp.ru,Proxy +DOMAIN-SUFFIX,binaryage.com,Proxy +DOMAIN-SUFFIX,bipic.net,Proxy +DOMAIN-SUFFIX,bitbucket.org,Proxy +DOMAIN-SUFFIX,bitcointalk.org,Proxy +DOMAIN-SUFFIX,bit.ly,Proxy +DOMAIN-SUFFIX,bitshare.com,Proxy +DOMAIN-SUFFIX,bjzc.org,Proxy +DOMAIN-SUFFIX,blinkx.com,Proxy +DOMAIN-SUFFIX,blinw.com,Proxy +DOMAIN-SUFFIX,blip.tv,Proxy +DOMAIN-SUFFIX,blockcn.com,Proxy +DOMAIN-SUFFIX,blog.birdhouseapp.com,Proxy +DOMAIN-SUFFIX,blog.bitly.com,Proxy +DOMAIN-SUFFIX,blogblog.com,Proxy +DOMAIN-SUFFIX,blog.boxcar.io,Proxy +DOMAIN-SUFFIX,blogcatalog.com,Proxy +DOMAIN-SUFFIX,blogcdn.com,Proxy +DOMAIN-SUFFIX,blogcity.me,Proxy +DOMAIN-SUFFIX,blog.com,Proxy +DOMAIN-SUFFIX,blog.davidziegler.net,Proxy +DOMAIN-SUFFIX,blog.dayoneapp.com,Proxy +DOMAIN-SUFFIX,blog.de,Proxy +DOMAIN-SUFFIX,blog.dribbble.com,Proxy +DOMAIN-SUFFIX,blog.exblog.co.jp,Proxy +DOMAIN-SUFFIX,blog.excite.co.jp,Proxy +DOMAIN-SUFFIX,blog.expofutures.com,Proxy +DOMAIN-SUFFIX,blog.fizzik.com,Proxy +DOMAIN-SUFFIX,blog.foolsmountain.com,Proxy +DOMAIN-SUFFIX,blogger.com,Proxy +DOMAIN-SUFFIX,blog.gowalla.com,Proxy +DOMAIN-SUFFIX,blog.hotpotato.com,Proxy +DOMAIN-SUFFIX,blog.ifttt.com,Proxy +DOMAIN-SUFFIX,blogimg.jp,Proxy +DOMAIN-SUFFIX,blog.instagram.com,Proxy +DOMAIN-SUFFIX,blog.instapaper.com,Proxy +DOMAIN-SUFFIX,blog.iphone-dev.org,Proxy +DOMAIN-SUFFIX,blog.istef.info,Proxy +DOMAIN-SUFFIX,blog.jackjia.com,Proxy +DOMAIN-SUFFIX,blog.joeyrobert.org,Proxy +DOMAIN-SUFFIX,blog.kangye.org,Proxy +DOMAIN-SUFFIX,blog.kickstarter.com,Proxy +DOMAIN-SUFFIX,blog.kl.am,Proxy +DOMAIN-SUFFIX,blog.klip.me,Proxy +DOMAIN-SUFFIX,blog.lester850.info,Proxy +DOMAIN-SUFFIX,blog.lightbox.com,Proxy +DOMAIN-SUFFIX,bloglines.com,Proxy +DOMAIN-SUFFIX,bloglovin.com,Proxy +DOMAIN-SUFFIX,blog.mongodb.org,Proxy +DOMAIN-SUFFIX,blog.openinkpot.org,Proxy +DOMAIN-SUFFIX,blog.palm.com,Proxy +DOMAIN-SUFFIX,blog.path.com,Proxy +DOMAIN-SUFFIX,blog.pathtosharepoint.com,Proxy +DOMAIN-SUFFIX,blog.pentalogic.net,Proxy +DOMAIN-SUFFIX,blog.pikchur.com,Proxy +DOMAIN-SUFFIX,blog.pilotmoon.com,Proxy +DOMAIN-SUFFIX,blog.qooza.hk,Proxy +DOMAIN-SUFFIX,blog.ranxiang.com,Proxy +DOMAIN-SUFFIX,blog.rockmelt.com,Proxy +DOMAIN-SUFFIX,blog.romanandreg.com,Proxy +DOMAIN-SUFFIX,blogs.icerocket.com,Proxy +DOMAIN-SUFFIX,blog.sina.com.tw,Proxy +DOMAIN-SUFFIX,blogsmithmedia.com,Proxy +DOMAIN-SUFFIX,blog.sogoo.org,Proxy +DOMAIN-SUFFIX,blog.sparrowmailapp.com,Proxy +DOMAIN-SUFFIX,blogspot.ca,Proxy +DOMAIN-SUFFIX,blogspot.com,Proxy +DOMAIN-SUFFIX,blogspot.com.es,Proxy +DOMAIN-SUFFIX,blogspot.co.uk,Proxy +DOMAIN-SUFFIX,blogspot.hk,Proxy +DOMAIN-SUFFIX,blogspot.jp,Proxy +DOMAIN-SUFFIX,blogspot.ro,Proxy +DOMAIN-SUFFIX,blogspot.sg,Proxy +DOMAIN-SUFFIX,blogs.tampabay.com,Proxy +DOMAIN-SUFFIX,blog.summify.com,Proxy +DOMAIN-SUFFIX,blogs.yahoo.co.jp,Proxy +DOMAIN-SUFFIX,blog.syx86.cn,Proxy +DOMAIN-SUFFIX,blog.syx86.com,Proxy +DOMAIN-SUFFIX,blog.taragana.com,Proxy +DOMAIN-SUFFIX,blogtd.net,Proxy +DOMAIN-SUFFIX,blogtd.org,Proxy +DOMAIN-SUFFIX,blog.tiney.com,Proxy +DOMAIN-SUFFIX,blog.topify.com,Proxy +DOMAIN-SUFFIX,blog.trello.com,Proxy +DOMAIN-SUFFIX,blog.usa.gov,Proxy +DOMAIN-SUFFIX,blog.wenweipo.com,Proxy +DOMAIN-SUFFIX,blog.writelonger.com,Proxy +DOMAIN-SUFFIX,blog.xuite.net,Proxy +DOMAIN-SUFFIX,blog.youthwant.com.tw,Proxy +DOMAIN-SUFFIX,blog.youxu.info,Proxy +DOMAIN-SUFFIX,bloodshed.net,Proxy +DOMAIN-SUFFIX,bloomberg.cn,Proxy +DOMAIN-SUFFIX,bloomberg.com,Proxy +DOMAIN-SUFFIX,bloomberg.de,Proxy +DOMAIN-SUFFIX,bloomfortune.com,Proxy +DOMAIN-SUFFIX,bloomingdales.com,Proxy +DOMAIN-SUFFIX,bnrmetal.com,Proxy +DOMAIN-SUFFIX,boardreader.com,Proxy +DOMAIN-SUFFIX,bobulate.com,Proxy +DOMAIN-SUFFIX,bod.asia,Proxy +DOMAIN-SUFFIX,bolin.netfirms.com,Proxy +DOMAIN-SUFFIX,bonbonme.com,Proxy +DOMAIN-SUFFIX,bonjourlesgeeks.com,Proxy +DOMAIN-SUFFIX,boobstagram.com,Proxy +DOMAIN-SUFFIX,book.com.tw,Proxy +DOMAIN-SUFFIX,books.com.tw,Proxy +DOMAIN-SUFFIX,bookshelfporn.com,Proxy +DOMAIN-SUFFIX,bootstrapcdn.com,Proxy +DOMAIN-SUFFIX,botanwang.com,Proxy +DOMAIN-SUFFIX,bot.nu,Proxy +DOMAIN-SUFFIX,bowenpress.com,Proxy +DOMAIN-SUFFIX,box.com,Proxy +DOMAIN-SUFFIX,box.net,Proxy +DOMAIN-SUFFIX,boxunblog.com,Proxy +DOMAIN-SUFFIX,boxunclub.com,Proxy +DOMAIN-SUFFIX,boxun.com,Proxy +DOMAIN-SUFFIX,boxun.tv,Proxy +DOMAIN-SUFFIX,boyfriendtv.com,Proxy +DOMAIN-SUFFIX,boysmaster.com,Proxy +DOMAIN-SUFFIX,bralio.com,Proxy +DOMAIN-SUFFIX,branch.com,Proxy +DOMAIN-SUFFIX,brandonhutchinson.com,Proxy +DOMAIN-SUFFIX,braumeister.org,Proxy +DOMAIN-SUFFIX,bravotube.net,Proxy +DOMAIN-SUFFIX,brazzers.com,Proxy +DOMAIN-SUFFIX,break.com,Proxy +DOMAIN-SUFFIX,breakingtweets.com,Proxy +DOMAIN-SUFFIX,breakwall.net,Proxy +DOMAIN-SUFFIX,br.hao123.com,Proxy +DOMAIN-SUFFIX,briefdream.com,Proxy +DOMAIN-SUFFIX,brightkite.com,Proxy +DOMAIN-SUFFIX,briian.com,Proxy +DOMAIN-SUFFIX,brizzly.com,Proxy +DOMAIN-SUFFIX,broadbook.com,Proxy +DOMAIN-SUFFIX,broadpressinc.com,Proxy +DOMAIN-SUFFIX,browserscope.org,Proxy +DOMAIN-SUFFIX,br.st,Proxy +DOMAIN-SUFFIX,brucewang.net,Proxy +DOMAIN-SUFFIX,bt95.com,Proxy +DOMAIN-SUFFIX,btdigg.org,Proxy +DOMAIN-SUFFIX,btspread.com,Proxy +DOMAIN-SUFFIX,budaedu.org,Proxy +DOMAIN-SUFFIX,buff.ly,Proxy +DOMAIN-SUFFIX,bugclub.org,Proxy +DOMAIN-SUFFIX,bulbous.freeserve.co.uk,Proxy +DOMAIN-SUFFIX,bullogger.com,Proxy +DOMAIN-SUFFIX,bullog.org,Proxy +DOMAIN-SUFFIX,businessinsider.com,Proxy +DOMAIN-SUFFIX,businessinsider.com.au,Proxy +DOMAIN-SUFFIX,businesstimes.com.cn,Proxy +DOMAIN-SUFFIX,businessweek.com,Proxy +DOMAIN-SUFFIX,buugaa.com,Proxy +DOMAIN-SUFFIX,buy.yahoo.com.tw,Proxy +DOMAIN-SUFFIX,buzzhand.com,Proxy +DOMAIN-SUFFIX,buzzurl.jp,Proxy +DOMAIN-SUFFIX,bwsj.hk,Proxy +DOMAIN-SUFFIX,bx.tl,Proxy +DOMAIN-SUFFIX,c1521.biz.tm,Proxy +DOMAIN-SUFFIX,c1522.mooo.com,Proxy +DOMAIN-SUFFIX,cacnw.com,Proxy +DOMAIN-SUFFIX,cactusvpn.com,Proxy +DOMAIN-SUFFIX,cafepress.com,Proxy +DOMAIN-SUFFIX,cahr.org.tw,Proxy +DOMAIN-SUFFIX,calameo.com,Proxy +DOMAIN-SUFFIX,calebelston.com,Proxy +DOMAIN-SUFFIX,cam4.com,Proxy +DOMAIN-SUFFIX,cam4.jp,Proxy +DOMAIN-SUFFIX,cam4.sg,Proxy +DOMAIN-SUFFIX,cams.com,Proxy +DOMAIN-SUFFIX,cams.org.sg,Proxy +DOMAIN-SUFFIX,canadameet.com,Proxy +DOMAIN-SUFFIX,canyu.org,Proxy +DOMAIN-SUFFIX,caobian.info,Proxy +DOMAIN-SUFFIX,caochangqing.com,Proxy +DOMAIN-SUFFIX,cao.im,Proxy +DOMAIN-SUFFIX,cardinalkungfoundation.org,Proxy +DOMAIN-SUFFIX,cari.com.my,Proxy +DOMAIN-SUFFIX,casatibet.org.mx,Proxy +DOMAIN-SUFFIX,caspion.com,Proxy +DOMAIN-SUFFIX,catcatbox.com,Proxy +DOMAIN-SUFFIX,catch22.net,Proxy +DOMAIN-SUFFIX,catfightpayperview.xxx,Proxy +DOMAIN-SUFFIX,catholic.org.hk,Proxy +DOMAIN-SUFFIX,catholic.org.tw,Proxy +DOMAIN-SUFFIX,cattt.com,Proxy +DOMAIN-SUFFIX,cbc.ca,Proxy +DOMAIN-SUFFIX,cbsnews.com,Proxy +DOMAIN-SUFFIX,cbs.ntu.edu.tw,Proxy +DOMAIN-SUFFIX,cbtc.org.hk,Proxy +DOMAIN-SUFFIX,ccavtop10.com,Proxy +DOMAIN-SUFFIX,ccdtr.org,Proxy +DOMAIN-SUFFIX,ccim.org,Proxy +DOMAIN-SUFFIX,cclife.org,Proxy +DOMAIN-SUFFIX,ccthere.com,Proxy +DOMAIN-SUFFIX,cctongbao.com,Proxy +DOMAIN-SUFFIX,ccue.ca,Proxy +DOMAIN-SUFFIX,ccue.com,Proxy +DOMAIN-SUFFIX,cdbook.org,Proxy +DOMAIN-SUFFIX,cdd.me,Proxy +DOMAIN-SUFFIX,cdef.org,Proxy +DOMAIN-SUFFIX,cdig.info,Proxy +DOMAIN-SUFFIX,cdjp.org,Proxy +DOMAIN-SUFFIX,cdnews.com.tw,Proxy +DOMAIN-SUFFIX,cdninstagram.com,Proxy +DOMAIN-SUFFIX,cdn.optimizely.com,Proxy +DOMAIN-SUFFIX,cdn.printfriendly.com,Proxy +DOMAIN-SUFFIX,cdn.softlayer.net,Proxy +DOMAIN-SUFFIX,cdn.sstatic.net,Proxy +DOMAIN-SUFFIX,cdn.staticstuff.net,Proxy +DOMAIN-SUFFIX,cdn.v2ex.com,Proxy +DOMAIN-SUFFIX,cdp1989.org,Proxy +DOMAIN-SUFFIX,cdp1998.org,Proxy +DOMAIN-SUFFIX,cdp2006.org,Proxy +DOMAIN-SUFFIX,cdpa.url.tw,Proxy +DOMAIN-SUFFIX,cdpeu.org,Proxy +DOMAIN-SUFFIX,cdp.sinica.edu.tw,Proxy +DOMAIN-SUFFIX,cdpusa.org,Proxy +DOMAIN-SUFFIX,cdpweb.org,Proxy +DOMAIN-SUFFIX,cdpwu.org,Proxy +DOMAIN-SUFFIX,cdw.com,Proxy +DOMAIN-SUFFIX,cecc.gov,Proxy +DOMAIN-SUFFIX,cellulo.info,Proxy +DOMAIN-SUFFIX,cenci.tk,Proxy +DOMAIN-SUFFIX,cenews.eu,Proxy +DOMAIN-SUFFIX,centralnation.com,Proxy +DOMAIN-SUFFIX,centurys.net,Proxy +DOMAIN-SUFFIX,certificate.revocationcheck.com,Proxy +DOMAIN-SUFFIX,c-est-simple.com,Proxy +DOMAIN-SUFFIX,cfhks.org.hk,Proxy +DOMAIN-SUFFIX,cftfc.com,Proxy +DOMAIN-SUFFIX,cgdepot.org,Proxy +DOMAIN-SUFFIX,cgst.edu,Proxy +DOMAIN-SUFFIX,chandoo.org,Proxy +DOMAIN-SUFFIX,change.org,Proxy +DOMAIN-SUFFIX,changp.com,Proxy +DOMAIN-SUFFIX,chaos.e-spacy.com,Proxy +DOMAIN-SUFFIX,chapm25.com,Proxy +DOMAIN-SUFFIX,chaturbate.com,Proxy +DOMAIN-SUFFIX,chengmingmag.com,Proxy +DOMAIN-SUFFIX,chenguangcheng.com,Proxy +DOMAIN-SUFFIX,chenpokong.com,Proxy +DOMAIN-SUFFIX,cherrysave.com,Proxy +DOMAIN-SUFFIX,chevronwp7.com,Proxy +DOMAIN-SUFFIX,chhongbi.org,Proxy +DOMAIN-SUFFIX,chicagoncmtv.com,Proxy +DOMAIN-SUFFIX,china101.com,Proxy +DOMAIN-SUFFIX,china18.org,Proxy +DOMAIN-SUFFIX,china21.com,Proxy +DOMAIN-SUFFIX,china21.org,Proxy +DOMAIN-SUFFIX,china5000.us,Proxy +DOMAIN-SUFFIX,chinaaffairs.org,Proxy +DOMAIN-SUFFIX,chinaaid.me,Proxy +DOMAIN-SUFFIX,chinaaid.net,Proxy +DOMAIN-SUFFIX,chinaaid.org,Proxy +DOMAIN-SUFFIX,chinaaid.us,Proxy +DOMAIN-SUFFIX,chinachange.org,Proxy +DOMAIN-SUFFIX,chinachannel.hk,Proxy +DOMAIN-SUFFIX,chinacomments.org,Proxy +DOMAIN-SUFFIX,chinadigitaltimes.net,Proxy +DOMAIN-SUFFIX,chinaeweekly.com,Proxy +DOMAIN-SUFFIX,chinafreepress.org,Proxy +DOMAIN-SUFFIX,chinagate.com,Proxy +DOMAIN-SUFFIX,chinageeks.org,Proxy +DOMAIN-SUFFIX,chinagfw.org,Proxy +DOMAIN-SUFFIX,chinagreenparty.org,Proxy +DOMAIN-SUFFIX,chinahorizon.org,Proxy +DOMAIN-SUFFIX,chinahush.com,Proxy +DOMAIN-SUFFIX,chinainperspective.com,Proxy +DOMAIN-SUFFIX,chinainperspective.net,Proxy +DOMAIN-SUFFIX,chinainperspective.org,Proxy +DOMAIN-SUFFIX,chinainterimgov.org,Proxy +DOMAIN-SUFFIX,chinalaborwatch.org,Proxy +DOMAIN-SUFFIX,chinalawandpolicy.com,Proxy +DOMAIN-SUFFIX,chinalawtranslate.com,Proxy +DOMAIN-SUFFIX,chinamule.com,Proxy +DOMAIN-SUFFIX,chinamz.org,Proxy +DOMAIN-SUFFIX,chinarightsia.org,Proxy +DOMAIN-SUFFIX,chinasocialdemocraticparty.com,Proxy +DOMAIN-SUFFIX,chinasoul.org,Proxy +DOMAIN-SUFFIX,chinatimes.com,Proxy +DOMAIN-SUFFIX,chinatweeps.com,Proxy +DOMAIN-SUFFIX,chinaway.org,Proxy +DOMAIN-SUFFIX,china-week.com,Proxy +DOMAIN-SUFFIX,chinaworker.info,Proxy +DOMAIN-SUFFIX,chinaxchina.com,Proxy +DOMAIN-SUFFIX,chinayouth.org.hk,Proxy +DOMAIN-SUFFIX,chinayuanmin.org,Proxy +DOMAIN-SUFFIX,chinesedailynews.com,Proxy +DOMAIN-SUFFIX,chinese.engadget.com,Proxy +DOMAIN-SUFFIX,chinese-hermit.net,Proxy +DOMAIN-SUFFIX,chinese-memorial.org,Proxy +DOMAIN-SUFFIX,chinesen.de,Proxy +DOMAIN-SUFFIX,chinesenewsnet.com,Proxy +DOMAIN-SUFFIX,chinesepen.org,Proxy +DOMAIN-SUFFIX,chinese.rnw.nl,Proxy +DOMAIN-SUFFIX,chinese.soifind.com,Proxy +DOMAIN-SUFFIX,chinesetalks.net,Proxy +DOMAIN-SUFFIX,chingcheong.com,Proxy +DOMAIN-SUFFIX,chithu.org,Proxy +DOMAIN-SUFFIX,chn.chosun.com,Proxy +DOMAIN-SUFFIX,chrdnet.com,Proxy +DOMAIN-SUFFIX,chrispederick.com,Proxy +DOMAIN-SUFFIX,chrispederick.net,Proxy +DOMAIN-SUFFIX,christianstudy.com,Proxy +DOMAIN-SUFFIX,christiantimes.org.hk,Proxy +DOMAIN-SUFFIX,christusrex.org,Proxy +DOMAIN-SUFFIX,chrlawyers.hk,Proxy +DOMAIN-SUFFIX,chrlcg-hk.org,Proxy +DOMAIN-SUFFIX,chromeadblock.com,Proxy +DOMAIN-SUFFIX,chrome.com,Proxy +DOMAIN-SUFFIX,chromeexperiments.com,Proxy +DOMAIN-SUFFIX,chromercise.com,Proxy +DOMAIN-SUFFIX,chromium.org,Proxy +DOMAIN-SUFFIX,ch.shvoong.com,Proxy +DOMAIN-SUFFIX,chubun.com,Proxy +DOMAIN-SUFFIX,chuizi.net,Proxy +DOMAIN-SUFFIX,circlethebayfortibet.org,Proxy +DOMAIN-SUFFIX,citizenlab.org,Proxy +DOMAIN-SUFFIX,citizenscommission.hk,Proxy +DOMAIN-SUFFIX,citizensradio.org,Proxy +DOMAIN-SUFFIX,city365.ca,Proxy +DOMAIN-SUFFIX,city9x.com,Proxy +DOMAIN-SUFFIX,civicparty.hk,Proxy +DOMAIN-SUFFIX,civilhrfront.org,Proxy +DOMAIN-SUFFIX,civilmedia.tw,Proxy +DOMAIN-SUFFIX,cjb.net,Proxy +DOMAIN-SUFFIX,ck101.com,Proxy +DOMAIN-SUFFIX,classicalguitarblog.net,Proxy +DOMAIN-SUFFIX,classically.me,Proxy +DOMAIN-SUFFIX,clb.org.hk,Proxy +DOMAIN-SUFFIX,cl.d0z.net,Proxy +DOMAIN-SUFFIX,clearharmony.net,Proxy +DOMAIN-SUFFIX,clearwisdom.net,Proxy +DOMAIN-SUFFIX,clientsfromhell.net,Proxy +DOMAIN-SUFFIX,cling.omy.sg,Proxy +DOMAIN-SUFFIX,clipfish.de,Proxy +DOMAIN-SUFFIX,cl.ly,Proxy +DOMAIN-SUFFIX,cloudflare.com,Proxy +DOMAIN-SUFFIX,cloudfront.net,Proxy +DOMAIN-SUFFIX,club1069.com,Proxy +DOMAIN-SUFFIX,cl.ufree.org,Proxy +DOMAIN-SUFFIX,cmi.org.tw,Proxy +DOMAIN-SUFFIX,cmoinc.org,Proxy +DOMAIN-SUFFIX,cms.gov,Proxy +DOMAIN-SUFFIX,cmule.com,Proxy +DOMAIN-SUFFIX,cmule.org,Proxy +DOMAIN-SUFFIX,cn2.streetvoice.com,Proxy +DOMAIN-SUFFIX,cna.com.tw,Proxy +DOMAIN-SUFFIX,cnavista.com.tw,Proxy +DOMAIN-SUFFIX,cn.calameo.com,Proxy +DOMAIN-SUFFIX,cn.dayabook.com,Proxy +DOMAIN-SUFFIX,cnd.org,Proxy +DOMAIN-SUFFIX,cn.fmnnow.com,Proxy +DOMAIN-SUFFIX,cn.giganews.com,Proxy +DOMAIN-SUFFIX,cn.ibtimes.com,Proxy +DOMAIN-SUFFIX,cnn.com,Proxy +DOMAIN-SUFFIX,cn.reuters.com,Proxy +DOMAIN-SUFFIX,cn.streetvoice.com,Proxy +DOMAIN-SUFFIX,cn.uncyclopedia.wikia.com,Proxy +DOMAIN-SUFFIX,cn.voa.mobi,Proxy +DOMAIN-SUFFIX,cochina.co,Proxy +DOMAIN-SUFFIX,cochina.org,Proxy +DOMAIN-SUFFIX,cocoapods.org,Proxy +DOMAIN-SUFFIX,cocoa.zonble.net,Proxy +DOMAIN-SUFFIX,code1984.com,Proxy +DOMAIN-SUFFIX,codeboxapp.com,Proxy +DOMAIN-SUFFIX,codeshare.io,Proxy +DOMAIN-SUFFIX,codeskulptor.org,Proxy +DOMAIN-SUFFIX,collateralmurder.com,Proxy +DOMAIN-SUFFIX,collateralmurder.org,Proxy +DOMAIN-SUFFIX,comefromchina.com,Proxy +DOMAIN-SUFFIX,commentshk.com,Proxy +DOMAIN-SUFFIX,compileheart.com,Proxy +DOMAIN-SUFFIX,connectedchina.reuters.com,Proxy +DOMAIN-SUFFIX,connect.facebook.net,Proxy +DOMAIN-SUFFIX,conoyo.com,Proxy +DOMAIN-SUFFIX,contactmagazine.net,Proxy +DOMAIN-SUFFIX,contests.twilio.com,Proxy +DOMAIN-SUFFIX,convio.net,Proxy +DOMAIN-SUFFIX,coobay.com,Proxy +DOMAIN-SUFFIX,cookingtothegoodlife.com,Proxy +DOMAIN-SUFFIX,cool18.com,Proxy +DOMAIN-SUFFIX,coolaler.com,Proxy +DOMAIN-SUFFIX,coolder.com,Proxy +DOMAIN-SUFFIX,coolloud.org.tw,Proxy +DOMAIN-SUFFIX,corumcollege.com,Proxy +DOMAIN-SUFFIX,cotweet.com,Proxy +DOMAIN-SUFFIX,couchdbwiki.com,Proxy +DOMAIN-SUFFIX,coveringweb.com,Proxy +DOMAIN-SUFFIX,cpj.org,Proxy +DOMAIN-SUFFIX,crackle.com,Proxy +DOMAIN-SUFFIX,crashlytics.com,Proxy +DOMAIN-SUFFIX,crchina.org,Proxy +DOMAIN-SUFFIX,crd-net.org,Proxy +DOMAIN-SUFFIX,creaders.net,Proxy +DOMAIN-SUFFIX,crossthewall.net,Proxy +DOMAIN-SUFFIX,crowy.net,Proxy +DOMAIN-SUFFIX,csdparty.com,Proxy +DOMAIN-SUFFIX,c-spanvideo.org,Proxy +DOMAIN-SUFFIX,css.pixnet.in,Proxy +DOMAIN-SUFFIX,csuchen.de,Proxy +DOMAIN-SUFFIX,ctfriend.net,Proxy +DOMAIN-SUFFIX,ctheroux.com,Proxy +DOMAIN-SUFFIX,cthlo.github.io,Proxy +DOMAIN-SUFFIX,ctitv.com.tw,Proxy +DOMAIN-SUFFIX,cts.com.tw,Proxy +DOMAIN-SUFFIX,cubicle17.com,Proxy +DOMAIN-SUFFIX,cuhkacs.org,Proxy +DOMAIN-SUFFIX,cuihua.org,Proxy +DOMAIN-SUFFIX,cuiweiping.net,Proxy +DOMAIN-SUFFIX,culture.tw,Proxy +DOMAIN-SUFFIX,curvefish.com,Proxy +DOMAIN-SUFFIX,cw.com.tw,Proxy +DOMAIN-SUFFIX,cyberghost.natado.com,Proxy +DOMAIN-SUFFIX,cyberghostvpn.com,Proxy +DOMAIN-SUFFIX,cynscribe.com,Proxy +DOMAIN-SUFFIX,cytode.us,Proxy +DOMAIN-SUFFIX,dabr.co.uk,Proxy +DOMAIN-SUFFIX,dabr.me,Proxy +DOMAIN-SUFFIX,dabr.mobi,Proxy +DOMAIN-SUFFIX,dadazim.com,Proxy +DOMAIN-SUFFIX,dadi360.com,Proxy +DOMAIN-SUFFIX,dafagood.com,Proxy +DOMAIN-SUFFIX,dafahao.com,Proxy +DOMAIN-SUFFIX,dailidaili.com,Proxy +DOMAIN-SUFFIX,dailymotion.com,Proxy +DOMAIN-SUFFIX,dailynews.sina.com,Proxy +DOMAIN-SUFFIX,dajiyuan.com,Proxy +DOMAIN-SUFFIX,dajiyuan.eu,Proxy +DOMAIN-SUFFIX,dajusha.baywords.com,Proxy +DOMAIN-SUFFIX,dalailama.com,Proxy +DOMAIN-SUFFIX,dalailamaprotesters.info,Proxy +DOMAIN-SUFFIX,dalailama.ru,Proxy +DOMAIN-SUFFIX,dalailamavisit.org.nz,Proxy +DOMAIN-SUFFIX,dalailamaworld.com,Proxy +DOMAIN-SUFFIX,dalianmeng.org,Proxy +DOMAIN-SUFFIX,daliulian.org,Proxy +DOMAIN-SUFFIX,danke4china.net,Proxy +DOMAIN-SUFFIX,danwei.org,Proxy +DOMAIN-SUFFIX,daolan.net,Proxy +DOMAIN-SUFFIX,darpa.mil,Proxy +DOMAIN-SUFFIX,data-vocabulary.org,Proxy +DOMAIN-SUFFIX,date.fm,Proxy +DOMAIN-SUFFIX,david-kilgour.com,Proxy +DOMAIN-SUFFIX,davidslog.com,Proxy +DOMAIN-SUFFIX,daxa.cn,Proxy +DOMAIN-SUFFIX,dayaarmongol.ning.com,Proxy +DOMAIN-SUFFIX,daylife.com,Proxy +DOMAIN-SUFFIX,dcard.tw,Proxy +DOMAIN-SUFFIX,ddc.com.tw,Proxy +DOMAIN-SUFFIX,deck.ly,Proxy +DOMAIN-SUFFIX,default.secureserver.net,Proxy +DOMAIN-SUFFIX,delcamp.net,Proxy +DOMAIN-SUFFIX,delicious.com,Proxy +DOMAIN-SUFFIX,democrats.org,Proxy +DOMAIN-SUFFIX,demo.opera-mini.net,Proxy +DOMAIN-SUFFIX,derekhsu.homeip.net,Proxy +DOMAIN-SUFFIX,de-sci.org,Proxy +DOMAIN-SUFFIX,desc.se,Proxy +DOMAIN-SUFFIX,designerol.com,Proxy +DOMAIN-SUFFIX,destiny.xfiles.to,Proxy +DOMAIN-SUFFIX,destroy-china.jp,Proxy +DOMAIN-SUFFIX,deutsche-welle.de,Proxy +DOMAIN-SUFFIX,dev102.com,Proxy +DOMAIN-SUFFIX,developers.box.net,Proxy +DOMAIN-SUFFIX,deviantart.com,Proxy +DOMAIN-SUFFIX,deviantart.net,Proxy +DOMAIN-SUFFIX,devio.us,Proxy +DOMAIN-SUFFIX,devpn.com,Proxy +DOMAIN-SUFFIX,dfanning.com,Proxy +DOMAIN-SUFFIX,dfas.mil,Proxy +DOMAIN-SUFFIX,dharamsalanet.com,Proxy +DOMAIN-SUFFIX,diaoyuislands.org,Proxy +DOMAIN-SUFFIX,digicert.com,Proxy +DOMAIN-SUFFIX,digiland.tw,Proxy +DOMAIN-SUFFIX,digitalnomadsproject.org,Proxy +DOMAIN-SUFFIX,digitalocean.com,Proxy +DOMAIN-SUFFIX,diigo.com,Proxy +DOMAIN-SUFFIX,dimitrik.free.fr,Proxy +DOMAIN-SUFFIX,dingoonity.org,Proxy +DOMAIN-SUFFIX,dipity.com,Proxy +DOMAIN-SUFFIX,directcreative.com,Proxy +DOMAIN-SUFFIX,discogs.com,Proxy +DOMAIN-SUFFIX,discuss.com.hk,Proxy +DOMAIN-SUFFIX,disneyrollergirl.net,Proxy +DOMAIN-SUFFIX,disp.cc,Proxy +DOMAIN-SUFFIX,dit-inc.us,Proxy +DOMAIN-SUFFIX,dizhidizhi.com,Proxy +DOMAIN-SUFFIX,dizhuzhishang.com,Proxy +DOMAIN-SUFFIX,djangosnippets.org,Proxy +DOMAIN-SUFFIX,dl.box.net,Proxy +DOMAIN-SUFFIX,dl.dropboxusercontent.com,Proxy +DOMAIN-SUFFIX,dl-laby.jp,Proxy +DOMAIN-SUFFIX,dlsite.com,Proxy +DOMAIN-SUFFIX,dmcdn.net,Proxy +DOMAIN-SUFFIX,dmm.co.jp,Proxy +DOMAIN-SUFFIX,dns2go.com,Proxy +DOMAIN-SUFFIX,dnscrypt.org,Proxy +DOMAIN-SUFFIX,dnsimple.com,Proxy +DOMAIN-SUFFIX,dnssec.net,Proxy +DOMAIN-SUFFIX,docker.com,Proxy +DOMAIN-SUFFIX,do.co,Proxy +DOMAIN-SUFFIX,docs.chef.io,Proxy +DOMAIN-SUFFIX,docs.docker.com,Proxy +DOMAIN-SUFFIX,dogfartnetwork.com,Proxy +DOMAIN-SUFFIX,dojin.com,Proxy +DOMAIN-SUFFIX,dok-forum.net,Proxy +DOMAIN-SUFFIX,dolc.de,Proxy +DOMAIN-SUFFIX,dolf.org.hk,Proxy +DOMAIN-SUFFIX,dollf.com,Proxy +DOMAIN-SUFFIX,domain.club.tw,Proxy +DOMAIN-SUFFIX,domainhelp.search.com,Proxy +DOMAIN-SUFFIX,dongde.com,Proxy +DOMAIN-SUFFIX,dongtaiwang.com,Proxy +DOMAIN-SUFFIX,dongtaiwang.net,Proxy +DOMAIN-SUFFIX,dongyangjing.com,Proxy +DOMAIN-SUFFIX,dontfilter.us,Proxy +DOMAIN-SUFFIX,dontmovetochina.com,Proxy +DOMAIN-SUFFIX,dotheyfolloweachother.com,Proxy +DOMAIN-SUFFIX,dotplane.com,Proxy +DOMAIN-SUFFIX,dotsub.com,Proxy +DOMAIN-SUFFIX,doubleaf.com,Proxy +DOMAIN-SUFFIX,doubleclick.net,Proxy +DOMAIN-SUFFIX,dougscripts.com,Proxy +DOMAIN-SUFFIX,dowei.org,Proxy +DOMAIN-SUFFIX,download.aircrack-ng.org,Proxy +DOMAIN-SUFFIX,download.ithome.com.tw,Proxy +DOMAIN-SUFFIX,doxygen.org,Proxy +DOMAIN-SUFFIX,dphk.org,Proxy +DOMAIN-SUFFIX,dpp.org.tw,Proxy +DOMAIN-SUFFIX,draw.io,Proxy +DOMAIN-SUFFIX,dreammask.org,Proxy +DOMAIN-SUFFIX,drepung.org,Proxy +DOMAIN-SUFFIX,drewolanoff.com,Proxy +DOMAIN-SUFFIX,drgan.net,Proxy +DOMAIN-SUFFIX,dribbble.com,Proxy +DOMAIN-SUFFIX,dropbox.com,Proxy +DOMAIN-SUFFIX,dropboxstatic.com,Proxy +DOMAIN-SUFFIX,dropboxusercontent.com,Proxy +DOMAIN-SUFFIX,droplr.com,Proxy +DOMAIN-SUFFIX,drsunacademy.com,Proxy +DOMAIN-SUFFIX,drtuber.com,Proxy +DOMAIN-SUFFIX,dscn.info,Proxy +DOMAIN-SUFFIX,dtiblog.com,Proxy +DOMAIN-SUFFIX,dtic.mil,Proxy +DOMAIN-SUFFIX,dtiserv2.com,Proxy +DOMAIN-SUFFIX,duckduckgo.com,Proxy +DOMAIN-SUFFIX,duckload.com,Proxy +DOMAIN-SUFFIX,duckmylife.com,Proxy +DOMAIN-SUFFIX,duihuahrjournal.org,Proxy +DOMAIN-SUFFIX,duihua.org,Proxy +DOMAIN-SUFFIX,duoweitimes.com,Proxy +DOMAIN-SUFFIX,duping.net,Proxy +DOMAIN-SUFFIX,duplicati.com,Proxy +DOMAIN-SUFFIX,dupola.com,Proxy +DOMAIN-SUFFIX,dupola.net,Proxy +DOMAIN-SUFFIX,dvorak.org,Proxy +DOMAIN-SUFFIX,dw.com,Proxy +DOMAIN-SUFFIX,dw.de,Proxy +DOMAIN-SUFFIX,dwheeler.com,Proxy +DOMAIN-SUFFIX,dwnews.com,Proxy +DOMAIN-SUFFIX,dwnews.net,Proxy +DOMAIN-SUFFIX,dw-world.com,Proxy +DOMAIN-SUFFIX,dw-world.de,Proxy +DOMAIN-SUFFIX,dy24k.info,Proxy +DOMAIN-SUFFIX,dynawebinc.com,Proxy +DOMAIN-SUFFIX,dyndns.org,Proxy +DOMAIN-SUFFIX,dzze.com,Proxy +DOMAIN-SUFFIX,e123.hk,Proxy +DOMAIN-SUFFIX,ea.com.cn,Proxy +DOMAIN-SUFFIX,eamonnbrennan.com,Proxy +DOMAIN-SUFFIX,earthquake.usgs.gov,Proxy +DOMAIN-SUFFIX,eastturkestan.com,Proxy +DOMAIN-SUFFIX,eastturkistangovernmentinexile.us,Proxy +DOMAIN-SUFFIX,eastturkistan-gov.org,Proxy +DOMAIN-SUFFIX,eastturkistan.net,Proxy +DOMAIN-SUFFIX,ebookbrowse.com,Proxy +DOMAIN-SUFFIX,ebookee.com,Proxy +DOMAIN-SUFFIX,echofon.com,Proxy +DOMAIN-SUFFIX,e-classical.com.tw,Proxy +DOMAIN-SUFFIX,ecministry.net,Proxy +DOMAIN-SUFFIX,ecsm.vs.com,Proxy +DOMAIN-SUFFIX,edgecastcdn.net,Proxy +DOMAIN-SUFFIX,edicypages.com,Proxy +DOMAIN-SUFFIX,editmysite.com,Proxy +DOMAIN-SUFFIX,edoors.com,Proxy +DOMAIN-SUFFIX,edubridge.com,Proxy +DOMAIN-SUFFIX,eevpn.com,Proxy +DOMAIN-SUFFIX,efcc.org.hk,Proxy +DOMAIN-SUFFIX,efksoft.com,Proxy +DOMAIN-SUFFIX,efmoe.com,Proxy +DOMAIN-SUFFIX,e-gold.com,Proxy +DOMAIN-SUFFIX,eic-av.com,Proxy +DOMAIN-SUFFIX,e-info.org.tw,Proxy +DOMAIN-SUFFIX,electionsmeter.com,Proxy +DOMAIN-SUFFIX,elementaryos.org,Proxy +DOMAIN-SUFFIX,elgoog.im,Proxy +DOMAIN-SUFFIX,elpais.com,Proxy +DOMAIN-SUFFIX,eltondisney.com,Proxy +DOMAIN-SUFFIX,emacsblog.org,Proxy +DOMAIN-SUFFIX,embedly.com,Proxy +DOMAIN-SUFFIX,embr.in,Proxy +DOMAIN-SUFFIX,emory.edu,Proxy +DOMAIN-SUFFIX,emule-ed2k.com,Proxy +DOMAIN-SUFFIX,emuparadise.me,Proxy +DOMAIN-SUFFIX,enewstree.com,Proxy +DOMAIN-SUFFIX,en.favotter.net,Proxy +DOMAIN-SUFFIX,engadget.com,Proxy +DOMAIN-SUFFIX,englishfromengland.co.uk,Proxy +DOMAIN-SUFFIX,en.hao123.com,Proxy +DOMAIN-SUFFIX,enormego.com,Proxy +DOMAIN-SUFFIX,entermap.com,Proxy +DOMAIN-SUFFIX,en.wikipedia.org,Proxy +DOMAIN-SUFFIX,episcopalchurch.org,Proxy +DOMAIN-SUFFIX,epochtimes-bg.com,Proxy +DOMAIN-SUFFIX,epochtimes.co.il,Proxy +DOMAIN-SUFFIX,epochtimes.co.kr,Proxy +DOMAIN-SUFFIX,epochtimes.com,Proxy +DOMAIN-SUFFIX,epochtimes.com.tw,Proxy +DOMAIN-SUFFIX,epochtimes.de,Proxy +DOMAIN-SUFFIX,epochtimes.fr,Proxy +DOMAIN-SUFFIX,epochtimes.ie,Proxy +DOMAIN-SUFFIX,epochtimes.jp,Proxy +DOMAIN-SUFFIX,epochtimes-romania.com,Proxy +DOMAIN-SUFFIX,epochtimes.ru,Proxy +DOMAIN-SUFFIX,epochtimes.se,Proxy +DOMAIN-SUFFIX,epochtimestr.com,Proxy +DOMAIN-SUFFIX,epochweekly.com,Proxy +DOMAIN-SUFFIX,erabaru.net,Proxy +DOMAIN-SUFFIX,erepublik.com,Proxy +DOMAIN-SUFFIX,erights.net,Proxy +DOMAIN-SUFFIX,eriversoft.com,Proxy +DOMAIN-SUFFIX,erktv.com,Proxy +DOMAIN-SUFFIX,ernestmandel.org,Proxy +DOMAIN-SUFFIX,eslite.com,Proxy +DOMAIN-SUFFIX,etaa.org.au,Proxy +DOMAIN-SUFFIX,etaiwannews.com,Proxy +DOMAIN-SUFFIX,etizer.org,Proxy +DOMAIN-SUFFIX,etools.ncol.com,Proxy +DOMAIN-SUFFIX,e-traderland.net,Proxy +DOMAIN-SUFFIX,ettoday.net,Proxy +DOMAIN-SUFFIX,eulam.com,Proxy +DOMAIN-SUFFIX,eurekavpt.com,Proxy +DOMAIN-SUFFIX,evchk.wikia.com,Proxy +DOMAIN-SUFFIX,eventful.com,Proxy +DOMAIN-SUFFIX,everyday-carry.com,Proxy +DOMAIN-SUFFIX,exblog.jp,Proxy +DOMAIN-SUFFIX,expatshield.com,Proxy +DOMAIN-SUFFIX,exploader.net,Proxy +DOMAIN-SUFFIX,expressvpn.com,Proxy +DOMAIN-SUFFIX,extremetube.com,Proxy +DOMAIN-SUFFIX,eyespirit.info,Proxy +DOMAIN-SUFFIX,eyevio.jp,Proxy +DOMAIN-SUFFIX,eyny.com,Proxy +DOMAIN-SUFFIX,ezpc.tk,Proxy +DOMAIN-SUFFIX,ezpeer.com,Proxy +DOMAIN-SUFFIX,fabric.io,Proxy +DOMAIN-SUFFIX,facebook.com,Proxy +DOMAIN-SUFFIX,facebook.net,Proxy +DOMAIN-SUFFIX,facebookquotes4u.com,Proxy +DOMAIN-SUFFIX,facesofnyfw.com,Proxy +DOMAIN-SUFFIX,facesoftibetanselfimmolators.info,Proxy +DOMAIN-SUFFIX,fail.hk,Proxy +DOMAIN-SUFFIX,faithfuleye.com,Proxy +DOMAIN-SUFFIX,faiththedog.info,Proxy +DOMAIN-SUFFIX,fakku.net,Proxy +DOMAIN-SUFFIX,falsefire.com,Proxy +DOMAIN-SUFFIX,falunart.org,Proxy +DOMAIN-SUFFIX,falunasia.info,Proxy +DOMAIN-SUFFIX,falun-co.org,Proxy +DOMAIN-SUFFIX,falundafa-dc.org,Proxy +DOMAIN-SUFFIX,falundafa-florida.org,Proxy +DOMAIN-SUFFIX,falundafamuseum.org,Proxy +DOMAIN-SUFFIX,falundafa-nc.org,Proxy +DOMAIN-SUFFIX,falundafa.org,Proxy +DOMAIN-SUFFIX,falungong.org.uk,Proxy +DOMAIN-SUFFIX,falunhr.org,Proxy +DOMAIN-SUFFIX,faluninfo.net,Proxy +DOMAIN-SUFFIX,falun-ny.net,Proxy +DOMAIN-SUFFIX,falunpilipinas.net,Proxy +DOMAIN-SUFFIX,falunworld.net,Proxy +DOMAIN-SUFFIX,familyfed.org,Proxy +DOMAIN-SUFFIX,famunion.com,Proxy +DOMAIN-SUFFIX,fangbinxing.com,Proxy +DOMAIN-SUFFIX,fangeming.com,Proxy +DOMAIN-SUFFIX,fanglizhi.info,Proxy +DOMAIN-SUFFIX,fangongheike.com,Proxy +DOMAIN-SUFFIX,fangong.org,Proxy +DOMAIN-SUFFIX,fan-qiang.com,Proxy +DOMAIN-SUFFIX,fanqianghou.com,Proxy +DOMAIN-SUFFIX,fanqiangyakexi.net,Proxy +DOMAIN-SUFFIX,fanswong.com,Proxy +DOMAIN-SUFFIX,fanyue.info,Proxy +DOMAIN-SUFFIX,fapdu.com,Proxy +DOMAIN-SUFFIX,farwestchina.com,Proxy +DOMAIN-SUFFIX,fastly.net,Proxy +DOMAIN-SUFFIX,fastpic.ru,Proxy +DOMAIN-SUFFIX,faststone.org,Proxy +DOMAIN-SUFFIX,favorious.com,Proxy +DOMAIN-SUFFIX,favstar.fm,Proxy +DOMAIN-SUFFIX,fawanghuihui.org,Proxy +DOMAIN-SUFFIX,faydao.com,Proxy +DOMAIN-SUFFIX,fbcdn.net,Proxy +DOMAIN-SUFFIX,fb.com,Proxy +DOMAIN-SUFFIX,fb.me,Proxy +DOMAIN-SUFFIX,fbsbx.com,Proxy +DOMAIN-SUFFIX,fc2blog.net,Proxy +DOMAIN-SUFFIX,fc2china.com,Proxy +DOMAIN-SUFFIX,fc2.com,Proxy +DOMAIN-SUFFIX,fdc89.jp,Proxy +DOMAIN-SUFFIX,feedblitz.com,Proxy +DOMAIN-SUFFIX,feedbooks.mobi,Proxy +DOMAIN-SUFFIX,feedburner.com,Proxy +DOMAIN-SUFFIX,feedly.com,Proxy +DOMAIN-SUFFIX,feeds2.feedburner.com,Proxy +DOMAIN-SUFFIX,feeds.feedburner.com,Proxy +DOMAIN-SUFFIX,feeds.fileforum.com,Proxy +DOMAIN-SUFFIX,feedzshare.com,Proxy +DOMAIN-SUFFIX,feelssh.com,Proxy +DOMAIN-SUFFIX,feer.com,Proxy +DOMAIN-SUFFIX,feitianacademy.org,Proxy +DOMAIN-SUFFIX,feitian-california.org,Proxy +DOMAIN-SUFFIX,felixcat.net,Proxy +DOMAIN-SUFFIX,feministteacher.com,Proxy +DOMAIN-SUFFIX,fengzhenghu.com,Proxy +DOMAIN-SUFFIX,ff.im,Proxy +DOMAIN-SUFFIX,fflick.com,Proxy +DOMAIN-SUFFIX,fgmtv.net,Proxy +DOMAIN-SUFFIX,fgmtv.org,Proxy +DOMAIN-SUFFIX,filefactory.com,Proxy +DOMAIN-SUFFIX,files2me.com,Proxy +DOMAIN-SUFFIX,fileserve.com,Proxy +DOMAIN-SUFFIX,fillthesquare.org,Proxy +DOMAIN-SUFFIX,finalion.jp,Proxy +DOMAIN-SUFFIX,findbook.tw,Proxy +DOMAIN-SUFFIX,fingerdaily.com,Proxy +DOMAIN-SUFFIX,finler.net,Proxy +DOMAIN-SUFFIX,fireofliberty.org,Proxy +DOMAIN-SUFFIX,firstfivefollowers.com,Proxy +DOMAIN-SUFFIX,flecheinthepeche.fr,Proxy +DOMAIN-SUFFIX,fleshbot.com,Proxy +DOMAIN-SUFFIX,flexibits.com,Proxy +DOMAIN-SUFFIX,flickr.com,Proxy +DOMAIN-SUFFIX,flickrhivemind.net,Proxy +DOMAIN-SUFFIX,flightcaster.com,Proxy +DOMAIN-SUFFIX,flipboard.com,Proxy +DOMAIN-SUFFIX,focustaiwan.tw,Proxy +DOMAIN-SUFFIX,focusvpn.com,Proxy +DOMAIN-SUFFIX,fofg.org,Proxy +DOMAIN-SUFFIX,fofldfradio.org,Proxy +DOMAIN-SUFFIX,fooooo.com,Proxy +DOMAIN-SUFFIX,footwiball.com,Proxy +DOMAIN-SUFFIX,forum4hk.com,Proxy +DOMAIN-SUFFIX,forum.baby-kingdom.com,Proxy +DOMAIN-SUFFIX,forum.cyberctm.com,Proxy +DOMAIN-SUFFIX,forum.idsam.com,Proxy +DOMAIN-SUFFIX,forum.iset.com.tw,Proxy +DOMAIN-SUFFIX,forum.my903.com,Proxy +DOMAIN-SUFFIX,forum.mymaji.com,Proxy +DOMAIN-SUFFIX,forum.omy.sg,Proxy +DOMAIN-SUFFIX,forum.palmislife.com,Proxy +DOMAIN-SUFFIX,forum.setty.com.tw,Proxy +DOMAIN-SUFFIX,forum.sina.com.hk,Proxy +DOMAIN-SUFFIX,forum.slime.com.tw,Proxy +DOMAIN-SUFFIX,forum.tvb.com,Proxy +DOMAIN-SUFFIX,fotop.net,Proxy +DOMAIN-SUFFIX,fourface.nodesnoop.com,Proxy +DOMAIN-SUFFIX,fourthinternational.org,Proxy +DOMAIN-SUFFIX,foxdie.us,Proxy +DOMAIN-SUFFIX,foxgay.com,Proxy +DOMAIN-SUFFIX,foxsub.com,Proxy +DOMAIN-SUFFIX,foxtang.com,Proxy +DOMAIN-SUFFIX,fpmtmexico.org,Proxy +DOMAIN-SUFFIX,fpmt.org,Proxy +DOMAIN-SUFFIX,fpmt-osel.org,Proxy +DOMAIN-SUFFIX,fpmt.tw,Proxy +DOMAIN-SUFFIX,fqok.org,Proxy +DOMAIN-SUFFIX,fqrouter.com,Proxy +DOMAIN-SUFFIX,franklc.com,Proxy +DOMAIN-SUFFIX,freakshare.com,Proxy +DOMAIN-SUFFIX,fredwilson.vc,Proxy +DOMAIN-SUFFIX,free4u.com.ar,Proxy +DOMAIN-SUFFIX,freealim.com,Proxy +DOMAIN-SUFFIX,freechal.com,Proxy +DOMAIN-SUFFIX,freechina.net,Proxy +DOMAIN-SUFFIX,freedomcollection.org,Proxy +DOMAIN-SUFFIX,freedomhouse.org,Proxy +DOMAIN-SUFFIX,freeforums.org,Proxy +DOMAIN-SUFFIX,free.fr,Proxy +DOMAIN-SUFFIX,freegao.com,Proxy +DOMAIN-SUFFIX,freegateget.googlepages.com,Proxy +DOMAIN-SUFFIX,free-gate.org,Proxy +DOMAIN-SUFFIX,free-hada-now.org,Proxy +DOMAIN-SUFFIX,freelotto.com,Proxy +DOMAIN-SUFFIX,freeman2.com,Proxy +DOMAIN-SUFFIX,freemoren.com,Proxy +DOMAIN-SUFFIX,freemorenews.com,Proxy +DOMAIN-SUFFIX,freenet-china.org,Proxy +DOMAIN-SUFFIX,freenetproject.org,Proxy +DOMAIN-SUFFIX,freenewscn.com,Proxy +DOMAIN-SUFFIX,freeopenvpn.com,Proxy +DOMAIN-SUFFIX,freeoz.org,Proxy +DOMAIN-SUFFIX,freepik.com,Proxy +DOMAIN-SUFFIX,free-ssh.com,Proxy +DOMAIN-SUFFIX,freessh.us,Proxy +DOMAIN-SUFFIX,freetibetanheroes.org,Proxy +DOMAIN-SUFFIX,freetibet.net,Proxy +DOMAIN-SUFFIX,freetibet.org,Proxy +DOMAIN-SUFFIX,freevpn.nl,Proxy +DOMAIN-SUFFIX,freewallpaper4.me,Proxy +DOMAIN-SUFFIX,freewebs.com,Proxy +DOMAIN-SUFFIX,freeweibo.com,Proxy +DOMAIN-SUFFIX,freexinwen.com,Proxy +DOMAIN-SUFFIX,freeyoutubeproxy.net,Proxy +DOMAIN-SUFFIX,friendfeed.com,Proxy +DOMAIN-SUFFIX,friendfeed-media.com,Proxy +DOMAIN-SUFFIX,friends-of-tibet.org,Proxy +DOMAIN-SUFFIX,friendsoftibet.org,Proxy +DOMAIN-SUFFIX,fring.com,Proxy +DOMAIN-SUFFIX,fringenetwork.com,Proxy +DOMAIN-SUFFIX,frommel.net,Proxy +DOMAIN-SUFFIX,frontlinedefenders.org,Proxy +DOMAIN-SUFFIX,fscked.org,Proxy +DOMAIN-SUFFIX,fsurf.com,Proxy +DOMAIN-SUFFIX,ftchinese.com,Proxy +DOMAIN-SUFFIX,fuckcnnic.net,Proxy +DOMAIN-SUFFIX,fuckgfw.com,Proxy +DOMAIN-SUFFIX,fuckgfw.org,Proxy +DOMAIN-SUFFIX,fulue.com,Proxy +DOMAIN-SUFFIX,funf.tw,Proxy +DOMAIN-SUFFIX,funp.com,Proxy +DOMAIN-SUFFIX,furhhdl.org,Proxy +DOMAIN-SUFFIX,furinkan.com,Proxy +DOMAIN-SUFFIX,furl.net,Proxy +DOMAIN-SUFFIX,futurechinaforum.org,Proxy +DOMAIN-SUFFIX,futureme.org,Proxy +DOMAIN-SUFFIX,futuremessage.org,Proxy +DOMAIN-SUFFIX,fuyin.net,Proxy +DOMAIN-SUFFIX,fw.cm,Proxy +DOMAIN-SUFFIX,fxnetworks.com,Proxy +DOMAIN-SUFFIX,fzh999.com,Proxy +DOMAIN-SUFFIX,fzh999.net,Proxy +DOMAIN-SUFFIX,gabocorp.com,Proxy +DOMAIN-SUFFIX,gaeproxy.com,Proxy +DOMAIN-SUFFIX,gaforum.org,Proxy +DOMAIN-SUFFIX,galenwu.com,Proxy +DOMAIN-SUFFIX,game735.com,Proxy +DOMAIN-SUFFIX,gamebase.com.tw,Proxy +DOMAIN-SUFFIX,gamer.com.tw,Proxy +DOMAIN-SUFFIX,gamez.com.tw,Proxy +DOMAIN-SUFFIX,ganges.com,Proxy +DOMAIN-SUFFIX,gaoming.net,Proxy +DOMAIN-SUFFIX,gaopi.net,Proxy +DOMAIN-SUFFIX,gaozhisheng.net,Proxy +DOMAIN-SUFFIX,gaozhisheng.org,Proxy +DOMAIN-SUFFIX,gappp.org,Proxy +DOMAIN-SUFFIX,gardennetworks.com,Proxy +DOMAIN-SUFFIX,gardennetworks.org,Proxy +DOMAIN-SUFFIX,gartlive.com,Proxy +DOMAIN-SUFFIX,gather.com,Proxy +DOMAIN-SUFFIX,gaymap.cc,Proxy +DOMAIN-SUFFIX,gaytube.com,Proxy +DOMAIN-SUFFIX,gazotube.com,Proxy +DOMAIN-SUFFIX,gcc.org.hk,Proxy +DOMAIN-SUFFIX,gclooney.com,Proxy +DOMAIN-SUFFIX,g.co,Proxy +DOMAIN-SUFFIX,gcpnews.com,Proxy +DOMAIN-SUFFIX,gdbt.net,Proxy +DOMAIN-SUFFIX,gdzf.org,Proxy +DOMAIN-SUFFIX,geek-art.net,Proxy +DOMAIN-SUFFIX,geekerhome.com,Proxy +DOMAIN-SUFFIX,geekmade.co.uk,Proxy +DOMAIN-SUFFIX,geekmanuals.com,Proxy +DOMAIN-SUFFIX,g.e-hentai.org,Proxy +DOMAIN-SUFFIX,generesis.com,Proxy +DOMAIN-SUFFIX,gentlecuff.com,Proxy +DOMAIN-SUFFIX,genuitec.com,Proxy +DOMAIN-SUFFIX,geocities.co.jp,Proxy +DOMAIN-SUFFIX,geocities.com,Proxy +DOMAIN-SUFFIX,geocities.jp,Proxy +DOMAIN-SUFFIX,geohot.com,Proxy +DOMAIN-SUFFIX,geometrictools.com,Proxy +DOMAIN-SUFFIX,getchu.com,Proxy +DOMAIN-SUFFIX,getcloudapp.com,Proxy +DOMAIN-SUFFIX,getcomposer.org,Proxy +DOMAIN-SUFFIX,get-digital-help.com,Proxy +DOMAIN-SUFFIX,getfoxyproxy.org,Proxy +DOMAIN-SUFFIX,getfreedur.com,Proxy +DOMAIN-SUFFIX,getgom.com,Proxy +DOMAIN-SUFFIX,getiton.com,Proxy +DOMAIN-SUFFIX,getjetso.com,Proxy +DOMAIN-SUFFIX,getlantern.org,Proxy +DOMAIN-SUFFIX,getnarrative.com,Proxy +DOMAIN-SUFFIX,getprismatic.com,Proxy +DOMAIN-SUFFIX,getsmartlinks.com,Proxy +DOMAIN-SUFFIX,getsocialscope.com,Proxy +DOMAIN-SUFFIX,getuploader.com,Proxy +DOMAIN-SUFFIX,getyouram.com,Proxy +DOMAIN-SUFFIX,gfw.org.ua,Proxy +DOMAIN-SUFFIX,ggpht.com,Proxy +DOMAIN-SUFFIX,ggssl.com,Proxy +DOMAIN-SUFFIX,ghconduit.com,Proxy +DOMAIN-SUFFIX,ghost.org,Proxy +DOMAIN-SUFFIX,ghut.org,Proxy +DOMAIN-SUFFIX,giga-web.jp,Proxy +DOMAIN-SUFFIX,gigporno.ru,Proxy +DOMAIN-SUFFIX,gimpshop.com,Proxy +DOMAIN-SUFFIX,girlbanker.com,Proxy +DOMAIN-SUFFIX,gist.github.com,Proxy +DOMAIN-SUFFIX,github.com,Proxy +DOMAIN-SUFFIX,github.io,Proxy +DOMAIN-SUFFIX,githubusercontent.com,Proxy +DOMAIN-SUFFIX,git-scm.com,Proxy +DOMAIN-SUFFIX,givemesomethingtoread.com,Proxy +DOMAIN-SUFFIX,glennhilton.com,Proxy +DOMAIN-SUFFIX,globaldelight.com,Proxy +DOMAIN-SUFFIX,global.hkepc.com,Proxy +DOMAIN-SUFFIX,globaljihad.net,Proxy +DOMAIN-SUFFIX,globalmuseumoncommunism.org,Proxy +DOMAIN-SUFFIX,globalrescue.hopto.org,Proxy +DOMAIN-SUFFIX,globalrescue.net,Proxy +DOMAIN-SUFFIX,globalvoicesonline.org,Proxy +DOMAIN-SUFFIX,glue-static.s3-external-3.amazonaws.com,Proxy +DOMAIN-SUFFIX,gmail.com,Proxy +DOMAIN-SUFFIX,gmbd.cn,Proxy +DOMAIN-SUFFIX,gmhz.org,Proxy +DOMAIN-SUFFIX,gmiddle.com,Proxy +DOMAIN-SUFFIX,gmiddle.net,Proxy +DOMAIN-SUFFIX,gmll.org,Proxy +DOMAIN-SUFFIX,gmodules.com,Proxy +DOMAIN-SUFFIX,gmozomg.izihost.org,Proxy +DOMAIN-SUFFIX,gnci.org.hk,Proxy +DOMAIN-SUFFIX,gnuradio.org,Proxy +DOMAIN-SUFFIX,goagent.biz,Proxy +DOMAIN-SUFFIX,goagentplus.com,Proxy +DOMAIN-SUFFIX,godaddy.com,Proxy +DOMAIN-SUFFIX,godfootsteps.org,Proxy +DOMAIN-SUFFIX,godsdirectcontact.org.tw,Proxy +DOMAIN-SUFFIX,gokbayrak.com,Proxy +DOMAIN-SUFFIX,golang.org,Proxy +DOMAIN-SUFFIX,goldbetsports.com,Proxy +DOMAIN-SUFFIX,goldenmelody.com.tw,Proxy +DOMAIN-SUFFIX,goldwave.com,Proxy +DOMAIN-SUFFIX,gongmeng.info,Proxy +DOMAIN-SUFFIX,gongm.in,Proxy +DOMAIN-SUFFIX,gongminliliang.com,Proxy +DOMAIN-SUFFIX,gongwt.com,Proxy +DOMAIN-SUFFIX,goodreaders.com,Proxy +DOMAIN-SUFFIX,goodreads.com,Proxy +DOMAIN-SUFFIX,goodtv.com.tw,Proxy +DOMAIN-SUFFIX,goodtv.tv,Proxy +DOMAIN-SUFFIX,goofind.com,Proxy +DOMAIN-SUFFIX,goo.gl,Proxy +DOMAIN-SUFFIX,googleadservices.com,Proxy +DOMAIN-SUFFIX,google.ae,Proxy +DOMAIN-SUFFIX,google.am,Proxy +DOMAIN-SUFFIX,google-analytics.com,Proxy +DOMAIN-SUFFIX,googleapis.com,Proxy +DOMAIN-SUFFIX,googleartproject.com,Proxy +DOMAIN-SUFFIX,google.as,Proxy +DOMAIN-SUFFIX,google.at,Proxy +DOMAIN-SUFFIX,google.az,Proxy +DOMAIN-SUFFIX,google.ba,Proxy +DOMAIN-SUFFIX,google.be,Proxy +DOMAIN-SUFFIX,google.bg,Proxy +DOMAIN-SUFFIX,google.bi,Proxy +DOMAIN-SUFFIX,google.bs,Proxy +DOMAIN-SUFFIX,google.ca,Proxy +DOMAIN-SUFFIX,google-cardboard.com,Proxy +DOMAIN-SUFFIX,google.cd,Proxy +DOMAIN-SUFFIX,google.cg,Proxy +DOMAIN-SUFFIX,google.ch,Proxy +DOMAIN-SUFFIX,google.ci,Proxy +DOMAIN-SUFFIX,google.cl,Proxy +DOMAIN-SUFFIX,google.cn,Proxy +DOMAIN-SUFFIX,google.co.bw,Proxy +DOMAIN-SUFFIX,google.co.ck,Proxy +DOMAIN-SUFFIX,google.co.cr,Proxy +DOMAIN-SUFFIX,googlecode.com,Proxy +DOMAIN-SUFFIX,google.co.hu,Proxy +DOMAIN-SUFFIX,google.co.id,Proxy +DOMAIN-SUFFIX,google.co.il,Proxy +DOMAIN-SUFFIX,google.co.in,Proxy +DOMAIN-SUFFIX,google.co.jp,Proxy +DOMAIN-SUFFIX,google.co.ke,Proxy +DOMAIN-SUFFIX,google.co.kr,Proxy +DOMAIN-SUFFIX,google.co.ls,Proxy +DOMAIN-SUFFIX,google.com,Proxy +DOMAIN-SUFFIX,google.co.ma,Proxy +DOMAIN-SUFFIX,google.com.af,Proxy +DOMAIN-SUFFIX,google.com.ag,Proxy +DOMAIN-SUFFIX,google.com.ar,Proxy +DOMAIN-SUFFIX,google.com.au,Proxy +DOMAIN-SUFFIX,google.com.bd,Proxy +DOMAIN-SUFFIX,google.com.bh,Proxy +DOMAIN-SUFFIX,google.com.bo,Proxy +DOMAIN-SUFFIX,google.com.br,Proxy +DOMAIN-SUFFIX,google.com.bz,Proxy +DOMAIN-SUFFIX,google.com.co,Proxy +DOMAIN-SUFFIX,google.com.cu,Proxy +DOMAIN-SUFFIX,google.com.do,Proxy +DOMAIN-SUFFIX,google.com.ec,Proxy +DOMAIN-SUFFIX,google.com.eg,Proxy +DOMAIN-SUFFIX,google.com.et,Proxy +DOMAIN-SUFFIX,google.com.gi,Proxy +DOMAIN-SUFFIX,google.com.gt,Proxy +DOMAIN-SUFFIX,google.com.hk,Proxy +DOMAIN-SUFFIX,google.com.jm,Proxy +DOMAIN-SUFFIX,google.com.ly,Proxy +DOMAIN-SUFFIX,googlecommerce.com,Proxy +DOMAIN-SUFFIX,google.com.mt,Proxy +DOMAIN-SUFFIX,google.com.mx,Proxy +DOMAIN-SUFFIX,google.com.my,Proxy +DOMAIN-SUFFIX,google.com.na,Proxy +DOMAIN-SUFFIX,google.com.nf,Proxy +DOMAIN-SUFFIX,google.com.ni,Proxy +DOMAIN-SUFFIX,google.com.np,Proxy +DOMAIN-SUFFIX,google.com.om,Proxy +DOMAIN-SUFFIX,google.com.pa,Proxy +DOMAIN-SUFFIX,google.com.pe,Proxy +DOMAIN-SUFFIX,google.com.ph,Proxy +DOMAIN-SUFFIX,google.com.pk,Proxy +DOMAIN-SUFFIX,google.com.pr,Proxy +DOMAIN-SUFFIX,google.com.py,Proxy +DOMAIN-SUFFIX,google.com.sa,Proxy +DOMAIN-SUFFIX,google.com.sb,Proxy +DOMAIN-SUFFIX,google.com.sg,Proxy +DOMAIN-SUFFIX,google.com.sv,Proxy +DOMAIN-SUFFIX,google.com.tj,Proxy +DOMAIN-SUFFIX,google.com.tr,Proxy +DOMAIN-SUFFIX,google.com.tw,Proxy +DOMAIN-SUFFIX,google.com.ua,Proxy +DOMAIN-SUFFIX,google.com.uy,Proxy +DOMAIN-SUFFIX,google.com.vc,Proxy +DOMAIN-SUFFIX,google.com.vn,Proxy +DOMAIN-SUFFIX,google.co.nz,Proxy +DOMAIN-SUFFIX,google.co.th,Proxy +DOMAIN-SUFFIX,google.co.ug,Proxy +DOMAIN-SUFFIX,google.co.uk,Proxy +DOMAIN-SUFFIX,google.co.uz,Proxy +DOMAIN-SUFFIX,google.co.ve,Proxy +DOMAIN-SUFFIX,google.co.vi,Proxy +DOMAIN-SUFFIX,google.co.zm,Proxy +DOMAIN-SUFFIX,google.de,Proxy +DOMAIN-SUFFIX,google.dj,Proxy +DOMAIN-SUFFIX,google.dk,Proxy +DOMAIN-SUFFIX,google.dm,Proxy +DOMAIN-SUFFIX,googledomains.com,Proxy +DOMAIN-SUFFIX,googledrive.com,Proxy +DOMAIN-SUFFIX,googleearth.com,Proxy +DOMAIN-SUFFIX,google.es,Proxy +DOMAIN-SUFFIX,google.fi,Proxy +DOMAIN-SUFFIX,google.fm,Proxy +DOMAIN-SUFFIX,google.fr,Proxy +DOMAIN-SUFFIX,google.gl,Proxy +DOMAIN-SUFFIX,google.gm,Proxy +DOMAIN-SUFFIX,google.gr,Proxy +DOMAIN-SUFFIX,googlegroups.com,Proxy +DOMAIN-SUFFIX,google.hn,Proxy +DOMAIN-SUFFIX,googlehosted.com,Proxy +DOMAIN-SUFFIX,google.hr,Proxy +DOMAIN-SUFFIX,google.ht,Proxy +DOMAIN-SUFFIX,google.ie,Proxy +DOMAIN-SUFFIX,google.is,Proxy +DOMAIN-SUFFIX,google.it,Proxy +DOMAIN-SUFFIX,google.jo,Proxy +DOMAIN-SUFFIX,google.kg,Proxy +DOMAIN-SUFFIX,google.kz,Proxy +DOMAIN-SUFFIX,googlelabs.com,Proxy +DOMAIN-SUFFIX,google.li,Proxy +DOMAIN-SUFFIX,google.lk,Proxy +DOMAIN-SUFFIX,google.lt,Proxy +DOMAIN-SUFFIX,google.lu,Proxy +DOMAIN-SUFFIX,google.lv,Proxy +DOMAIN-SUFFIX,googlemail.com,Proxy +DOMAIN-SUFFIX,google.mn,Proxy +DOMAIN-SUFFIX,google.ms,Proxy +DOMAIN-SUFFIX,google.mu,Proxy +DOMAIN-SUFFIX,google.mw,Proxy +DOMAIN-SUFFIX,google.nl,Proxy +DOMAIN-SUFFIX,google.no,Proxy +DOMAIN-SUFFIX,google.nu,Proxy +DOMAIN-SUFFIX,google.off.ai,Proxy +DOMAIN-SUFFIX,googlepages.com,Proxy +DOMAIN-SUFFIX,google.pl,Proxy +DOMAIN-SUFFIX,googleplus.com,Proxy +DOMAIN-SUFFIX,google.pn,Proxy +DOMAIN-SUFFIX,google.pt,Proxy +DOMAIN-SUFFIX,google.ro,Proxy +DOMAIN-SUFFIX,google.ru,Proxy +DOMAIN-SUFFIX,google.rw,Proxy +DOMAIN-SUFFIX,google.sc,Proxy +DOMAIN-SUFFIX,google.se,Proxy +DOMAIN-SUFFIX,google.sh,Proxy +DOMAIN-SUFFIX,googlesile.com,Proxy +DOMAIN-SUFFIX,google.sk,Proxy +DOMAIN-SUFFIX,google.sm,Proxy +DOMAIN-SUFFIX,google.sn,Proxy +DOMAIN-SUFFIX,googlesource.com,Proxy +DOMAIN-SUFFIX,googlesyndication.com,Proxy +DOMAIN-SUFFIX,googletagmanager.com,Proxy +DOMAIN-SUFFIX,googletagservices.com,Proxy +DOMAIN-SUFFIX,google.tm,Proxy +DOMAIN-SUFFIX,google.to,Proxy +DOMAIN-SUFFIX,google.tp,Proxy +DOMAIN-SUFFIX,google.tt,Proxy +DOMAIN-SUFFIX,googleusercontent.com,Proxy +DOMAIN-SUFFIX,google.vg,Proxy +DOMAIN-SUFFIX,googlevideo.com,Proxy +DOMAIN-SUFFIX,google.vu,Proxy +DOMAIN-SUFFIX,google.ws,Proxy +DOMAIN-SUFFIX,gopetition.com,Proxy +DOMAIN-SUFFIX,gospelherald.com,Proxy +DOMAIN-SUFFIX,gotw.ca,Proxy +DOMAIN-SUFFIX,gov.tw,Proxy +DOMAIN-SUFFIX,gpass1.com,Proxy +DOMAIN-SUFFIX,gplusexpertise.com,Proxy +DOMAIN-SUFFIX,grandtrial.org,Proxy +DOMAIN-SUFFIX,grangorz.org,Proxy +DOMAIN-SUFFIX,graphis.ne.jp,Proxy +DOMAIN-SUFFIX,gravatar.com,Proxy +DOMAIN-SUFFIX,graylog2.org,Proxy +DOMAIN-SUFFIX,greasespot.net,Proxy +DOMAIN-SUFFIX,greatfire.org,Proxy +DOMAIN-SUFFIX,greatfirewall.biz,Proxy +DOMAIN-SUFFIX,great-firewall.com,Proxy +DOMAIN-SUFFIX,greatfirewallofchina.net,Proxy +DOMAIN-SUFFIX,greatfirewallofchina.org,Proxy +DOMAIN-SUFFIX,great-roc.org,Proxy +DOMAIN-SUFFIX,greatroc.org,Proxy +DOMAIN-SUFFIX,greatroc.tw,Proxy +DOMAIN-SUFFIX,greatzhonghua.org,Proxy +DOMAIN-SUFFIX,greenparty.org.tw,Proxy +DOMAIN-SUFFIX,greenpeace.com.tw,Proxy +DOMAIN-SUFFIX,greenpeace.org,Proxy +DOMAIN-SUFFIX,greenvpn.net,Proxy +DOMAIN-SUFFIX,groups.google.cn,Proxy +DOMAIN-SUFFIX,gs-discuss.com,Proxy +DOMAIN-SUFFIX,gstatic.com,Proxy +DOMAIN-SUFFIX,gtricks.com,Proxy +DOMAIN-SUFFIX,guancha.org,Proxy +DOMAIN-SUFFIX,gu-chu-sum.org,Proxy +DOMAIN-SUFFIX,guishan.org,Proxy +DOMAIN-SUFFIX,gunsamerica.com,Proxy +DOMAIN-SUFFIX,gun-world.net,Proxy +DOMAIN-SUFFIX,guomin.us,Proxy +DOMAIN-SUFFIX,gutteruncensored.com,Proxy +DOMAIN-SUFFIX,gvlib.com,Proxy +DOMAIN-SUFFIX,gvm.com.tw,Proxy +DOMAIN-SUFFIX,gvt0.com,Proxy +DOMAIN-SUFFIX,gvt1.com,Proxy +DOMAIN-SUFFIX,gyalwarinpoche.com,Proxy +DOMAIN-SUFFIX,gyatsostudio.com,Proxy +DOMAIN-SUFFIX,gzm.tv,Proxy +DOMAIN-SUFFIX,gzone-anime.info,Proxy +DOMAIN-SUFFIX,h1n1china.org,Proxy +DOMAIN-SUFFIX,hacken.cc,Proxy +DOMAIN-SUFFIX,hackthatphone.net,Proxy +DOMAIN-SUFFIX,hahlo.com,Proxy +DOMAIN-SUFFIX,hakkatv.org.tw,Proxy +DOMAIN-SUFFIX,hanunyi.com,Proxy +DOMAIN-SUFFIX,happi-game-center.com,Proxy +DOMAIN-SUFFIX,haproxy.org,Proxy +DOMAIN-SUFFIX,hardsextube.com,Proxy +DOMAIN-SUFFIX,harunyahya.com,Proxy +DOMAIN-SUFFIX,hasaowall.com,Proxy +DOMAIN-SUFFIX,have8.com,Proxy +DOMAIN-SUFFIX,haxx.se,Proxy +DOMAIN-SUFFIX,hbogo.com,Proxy +DOMAIN-SUFFIX,h-china.org,Proxy +DOMAIN-SUFFIX,hdtvb.net,Proxy +DOMAIN-SUFFIX,heartyit.com,Proxy +DOMAIN-SUFFIX,heatsale.com,Proxy +DOMAIN-SUFFIX,hecaitou.net,Proxy +DOMAIN-SUFFIX,hechaji.com,Proxy +DOMAIN-SUFFIX,heeact.edu.tw,Proxy +DOMAIN-SUFFIX,heix.pp.ru,Proxy +DOMAIN-SUFFIX,heiyo.info,Proxy +DOMAIN-SUFFIX,helloandroid.com,Proxy +DOMAIN-SUFFIX,hellonewyork.us,Proxy +DOMAIN-SUFFIX,helloqueer.com,Proxy +DOMAIN-SUFFIX,hellotxt.com,Proxy +DOMAIN-SUFFIX,hellouk.org,Proxy +DOMAIN-SUFFIX,helpeachpeople.com,Proxy +DOMAIN-SUFFIX,helplinfen.com,Proxy +DOMAIN-SUFFIX,help.linksalpha.com,Proxy +DOMAIN-SUFFIX,help.opera.com,Proxy +DOMAIN-SUFFIX,help.trello.com,Proxy +DOMAIN-SUFFIX,helpzhuling.org,Proxy +DOMAIN-SUFFIX,hen.bao.li,Proxy +DOMAIN-SUFFIX,heqinglian.net,Proxy +DOMAIN-SUFFIX,here4news.com,Proxy +DOMAIN-SUFFIX,heungkongdiscuss.com,Proxy +DOMAIN-SUFFIX,hexxeh.net,Proxy +DOMAIN-SUFFIX,hgseav.com,Proxy +DOMAIN-SUFFIX,hidden-advent.org,Proxy +DOMAIN-SUFFIX,hidecloud.com,Proxy +DOMAIN-SUFFIX,hideipvpn.com,Proxy +DOMAIN-SUFFIX,hide.me,Proxy +DOMAIN-SUFFIX,hidemyass.com,Proxy +DOMAIN-SUFFIX,higfw.com,Proxy +DOMAIN-SUFFIX,highcharts.com,Proxy +DOMAIN-SUFFIX,highrockmedia.com,Proxy +DOMAIN-SUFFIX,hihiforum.com,Proxy +DOMAIN-SUFFIX,hihistory.net,Proxy +DOMAIN-SUFFIX,hiitch.com,Proxy +DOMAIN-SUFFIX,hikinggfw.org,Proxy +DOMAIN-SUFFIX,himalayan-foundation.org,Proxy +DOMAIN-SUFFIX,himemix.com,Proxy +DOMAIN-SUFFIX,himemix.net,Proxy +DOMAIN-SUFFIX,hjclub.info,Proxy +DOMAIN-SUFFIX,hk32168.com,Proxy +DOMAIN-SUFFIX,hkbc.net,Proxy +DOMAIN-SUFFIX,hkbf.org,Proxy +DOMAIN-SUFFIX,hkchurch.org,Proxy +DOMAIN-SUFFIX,hkdailynews.com.hk,Proxy +DOMAIN-SUFFIX,hkday.net,Proxy +DOMAIN-SUFFIX,hkej.com,Proxy +DOMAIN-SUFFIX,hkepc.com,Proxy +DOMAIN-SUFFIX,hkfront.org,Proxy +DOMAIN-SUFFIX,hk.geocities.com,Proxy +DOMAIN-SUFFIX,hkgolden.com,Proxy +DOMAIN-SUFFIX,hk.gradconnection.com,Proxy +DOMAIN-SUFFIX,hkgreenradio.org,Proxy +DOMAIN-SUFFIX,hkg.westkit.net,Proxy +DOMAIN-SUFFIX,hkheadline.com,Proxy +DOMAIN-SUFFIX,hkhkhk.com,Proxy +DOMAIN-SUFFIX,hkjc.com,Proxy +DOMAIN-SUFFIX,hk.jiepang.com,Proxy +DOMAIN-SUFFIX,hkjp.easyweb.hk,Proxy +DOMAIN-SUFFIX,hkjp.org,Proxy +DOMAIN-SUFFIX,hk.knowledge.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.myblog.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.news.yahoo.com,Proxy +DOMAIN-SUFFIX,hkptu.org,Proxy +DOMAIN-SUFFIX,hk-pub.com,Proxy +DOMAIN-SUFFIX,hk.rd.yahoo.com,Proxy +DOMAIN-SUFFIX,hkreporter.com,Proxy +DOMAIN-SUFFIX,hkreporter.loved.hk,Proxy +DOMAIN-SUFFIX,hk.search.yahoo.com,Proxy +DOMAIN-SUFFIX,hkupop.hku.hk,Proxy +DOMAIN-SUFFIX,hk.video.news.yahoo.com,Proxy +DOMAIN-SUFFIX,hkwcc.org.hk,Proxy +DOMAIN-SUFFIX,hk.yahoo.com,Proxy +DOMAIN-SUFFIX,hkzone.org,Proxy +DOMAIN-SUFFIX,hnjhj.com,Proxy +DOMAIN-SUFFIX,hocusfoc.us,Proxy +DOMAIN-SUFFIX,hola.com,Proxy +DOMAIN-SUFFIX,hola.org,Proxy +DOMAIN-SUFFIX,holyspiritspeaks.org,Proxy +DOMAIN-SUFFIX,holz.byethost8.com,Proxy +DOMAIN-SUFFIX,homeservershow.com,Proxy +DOMAIN-SUFFIX,home.sina.com,Proxy +DOMAIN-SUFFIX,home.so-net.net.tw,Proxy +DOMAIN-SUFFIX,hongmeimei.com,Proxy +DOMAIN-SUFFIX,hongzhi.li,Proxy +DOMAIN-SUFFIX,hootsuite.com,Proxy +DOMAIN-SUFFIX,hotfile.com,Proxy +DOMAIN-SUFFIX,hotpot.hk,Proxy +DOMAIN-SUFFIX,hotshame.com,Proxy +DOMAIN-SUFFIX,hotspotshield.com,Proxy +DOMAIN-SUFFIX,hougaige.com,Proxy +DOMAIN-SUFFIX,howtoforge.com,Proxy +DOMAIN-SUFFIX,howtogeek.com,Proxy +DOMAIN-SUFFIX,hqcdp.org,Proxy +DOMAIN-SUFFIX,hrcchina.org,Proxy +DOMAIN-SUFFIX,hrcir.com,Proxy +DOMAIN-SUFFIX,hrichina.org,Proxy +DOMAIN-SUFFIX,hrw.org,Proxy +DOMAIN-SUFFIX,hsjp.net,Proxy +DOMAIN-SUFFIX,hsselite.com,Proxy +DOMAIN-SUFFIX,htkou.net,Proxy +DOMAIN-SUFFIX,htl.li,Proxy +DOMAIN-SUFFIX,ht.ly,Proxy +DOMAIN-SUFFIX,html5rocks.com,Proxy +DOMAIN-SUFFIX,htmldog.com,Proxy +DOMAIN-SUFFIX,htxt.it,Proxy +DOMAIN-SUFFIX,huaglad.com,Proxy +DOMAIN-SUFFIX,huanghuagang.org,Proxy +DOMAIN-SUFFIX,huaren.us,Proxy +DOMAIN-SUFFIX,huaxiabao.org,Proxy +DOMAIN-SUFFIX,huaxia-news.com,Proxy +DOMAIN-SUFFIX,huaxin.ph,Proxy +DOMAIN-SUFFIX,hua-yue.net,Proxy +DOMAIN-SUFFIX,hudatoriq.web.id,Proxy +DOMAIN-SUFFIX,hugoroy.eu,Proxy +DOMAIN-SUFFIX,huhaitai.com,Proxy +DOMAIN-SUFFIX,huhamhire.com,Proxy +DOMAIN-SUFFIX,hulu.com,Proxy +DOMAIN-SUFFIX,huluim.com,Proxy +DOMAIN-SUFFIX,humanrightsbriefing.org,Proxy +DOMAIN-SUFFIX,hungerstrikeforaids.org,Proxy +DOMAIN-SUFFIX,hung-ya.com,Proxy +DOMAIN-SUFFIX,huping.net,Proxy +DOMAIN-SUFFIX,hutianyi.net,Proxy +DOMAIN-SUFFIX,hutong9.net,Proxy +DOMAIN-SUFFIX,hwayue.org.tw,Proxy +DOMAIN-SUFFIX,hwinfo.com,Proxy +DOMAIN-SUFFIX,hxwq.org,Proxy +DOMAIN-SUFFIX,hybrid-analysis.com,Proxy +DOMAIN-SUFFIX,hyperrate.com,Proxy +DOMAIN-SUFFIX,hypeshell.com,Proxy +DOMAIN-SUFFIX,i1.hk,Proxy +DOMAIN-SUFFIX,i2p2.de,Proxy +DOMAIN-SUFFIX,i2runner.com,Proxy +DOMAIN-SUFFIX,ialmostlaugh.com,Proxy +DOMAIN-SUFFIX,ianslive.in,Proxy +DOMAIN-SUFFIX,iask.bz,Proxy +DOMAIN-SUFFIX,iask.ca,Proxy +DOMAIN-SUFFIX,ibiblio.org,Proxy +DOMAIN-SUFFIX,iblogserv-f.net,Proxy +DOMAIN-SUFFIX,ibros.org,Proxy +DOMAIN-SUFFIX,i-cable.com,Proxy +DOMAIN-SUFFIX,icij.org,Proxy +DOMAIN-SUFFIX,icl-fi.org,Proxy +DOMAIN-SUFFIX,iconfactory.com,Proxy +DOMAIN-SUFFIX,iconpaper.org,Proxy +DOMAIN-SUFFIX,icu-project.org,Proxy +DOMAIN-SUFFIX,idemocracy.asia,Proxy +DOMAIN-SUFFIX,identi.ca,Proxy +DOMAIN-SUFFIX,id.hao123.com,Proxy +DOMAIN-SUFFIX,idiomconnection.com,Proxy +DOMAIN-SUFFIX,idlcoyote.com,Proxy +DOMAIN-SUFFIX,idouga.com,Proxy +DOMAIN-SUFFIX,idv.tw,Proxy +DOMAIN-SUFFIX,ieasynews.net,Proxy +DOMAIN-SUFFIX,ied2k.net,Proxy +DOMAIN-SUFFIX,ifan.cz.cc,Proxy +DOMAIN-SUFFIX,ifanqiang.com,Proxy +DOMAIN-SUFFIX,ifanr.com,Proxy +DOMAIN-SUFFIX,ifcss.org,Proxy +DOMAIN-SUFFIX,ifjc.org,Proxy +DOMAIN-SUFFIX,ifreewares.com,Proxy +DOMAIN-SUFFIX,if.ttt,Proxy +DOMAIN-SUFFIX,ift.tt,Proxy +DOMAIN-SUFFIX,ifttt.com,Proxy +DOMAIN-SUFFIX,igfw.net,Proxy +DOMAIN-SUFFIX,ignitedetroit.net,Proxy +DOMAIN-SUFFIX,igvita.com,Proxy +DOMAIN-SUFFIX,ihakka.net,Proxy +DOMAIN-SUFFIX,iicns.com,Proxy +DOMAIN-SUFFIX,illusionfactory.com,Proxy +DOMAIN-SUFFIX,ilove80.be,Proxy +DOMAIN-SUFFIX,ilovelongtoes.com,Proxy +DOMAIN-SUFFIX,im88.tw,Proxy +DOMAIN-SUFFIX,imagefap.com,Proxy +DOMAIN-SUFFIX,imageflea.com,Proxy +DOMAIN-SUFFIX,imageoptim.com,Proxy +DOMAIN-SUFFIX,imageshack.us,Proxy +DOMAIN-SUFFIX,imagevenue.com,Proxy +DOMAIN-SUFFIX,imagezilla.net,Proxy +DOMAIN-SUFFIX,imdb.com,Proxy +DOMAIN-SUFFIX,img.dlsite.jp,Proxy +DOMAIN-SUFFIX,imgix.net,Proxy +DOMAIN-SUFFIX,img.ly,Proxy +DOMAIN-SUFFIX,imgur.com,Proxy +DOMAIN-SUFFIX,imkev.com,Proxy +DOMAIN-SUFFIX,imlive.com,Proxy +DOMAIN-SUFFIX,immigration.gov.tw,Proxy +DOMAIN-SUFFIX,im.tv,Proxy +DOMAIN-SUFFIX,incredibox.fr,Proxy +DOMAIN-SUFFIX,infinitylist.com,Proxy +DOMAIN-SUFFIX,infradead.org,Proxy +DOMAIN-SUFFIX,initiativesforchina.org,Proxy +DOMAIN-SUFFIX,inmediahk.net,Proxy +DOMAIN-SUFFIX,innermongolia.org,Proxy +DOMAIN-SUFFIX,instagram.com,Proxy +DOMAIN-SUFFIX,intellectuapp.com,Proxy +DOMAIN-SUFFIX,interestinglaugh.com,Proxy +DOMAIN-SUFFIX,interfaceaddiction.com,Proxy +DOMAIN-SUFFIX,internationalrivers.org,Proxy +DOMAIN-SUFFIX,internetdefenseleague.org,Proxy +DOMAIN-SUFFIX,internetfreedom.org,Proxy +DOMAIN-SUFFIX,internet.org,Proxy +DOMAIN-SUFFIX,internetpopculture.com,Proxy +DOMAIN-SUFFIX,inxian.com,Proxy +DOMAIN-SUFFIX,ipcf.org.tw,Proxy +DOMAIN-SUFFIX,iphone4hongkong.com,Proxy +DOMAIN-SUFFIX,iphonehacks.com,Proxy +DOMAIN-SUFFIX,iphonenews.cc,Proxy +DOMAIN-SUFFIX,iphonix.fr,Proxy +DOMAIN-SUFFIX,ipicture.ru,Proxy +DOMAIN-SUFFIX,ipobar.com,Proxy +DOMAIN-SUFFIX,ippotv.com,Proxy +DOMAIN-SUFFIX,iptorrents.com,Proxy +DOMAIN-SUFFIX,ipvanish.com,Proxy +DOMAIN-SUFFIX,iredmail.org,Proxy +DOMAIN-SUFFIX,iridiumcao.info,Proxy +DOMAIN-SUFFIX,ironbigfools.compython.net,Proxy +DOMAIN-SUFFIX,ironicsoftware.com,Proxy +DOMAIN-SUFFIX,ironpython.net,Proxy +DOMAIN-SUFFIX,isaacmao.com,Proxy +DOMAIN-SUFFIX,isgreat.org,Proxy +DOMAIN-SUFFIX,islamicity.com,Proxy +DOMAIN-SUFFIX,islam.org.hk,Proxy +DOMAIN-SUFFIX,ismaelan.com,Proxy +DOMAIN-SUFFIX,ismprofessional.net,Proxy +DOMAIN-SUFFIX,isohunt.com,Proxy +DOMAIN-SUFFIX,israbox.com,Proxy +DOMAIN-SUFFIX,istockphoto.com,Proxy +DOMAIN-SUFFIX,isunaffairs.com,Proxy +DOMAIN-SUFFIX,isuntv.com,Proxy +DOMAIN-SUFFIX,itaboo.info,Proxy +DOMAIN-SUFFIX,ithelp.ithome.com.tw,Proxy +DOMAIN-SUFFIX,its.caltech.edu,Proxy +DOMAIN-SUFFIX,itshidden.com,Proxy +DOMAIN-SUFFIX,itweet.net,Proxy +DOMAIN-SUFFIX,iu45.com,Proxy +DOMAIN-SUFFIX,iuhrdf.org,Proxy +DOMAIN-SUFFIX,iverycd.com,Proxy +DOMAIN-SUFFIX,ixquick.com,Proxy +DOMAIN-SUFFIX,iyouport.com,Proxy +DOMAIN-SUFFIX,izaobao.us,Proxy +DOMAIN-SUFFIX,izles.net,Proxy +DOMAIN-SUFFIX,jalan.net,Proxy +DOMAIN-SUFFIX,japanfirst.asianfreeforum.com,Proxy +DOMAIN-SUFFIX,japan-whores.com,Proxy +DOMAIN-SUFFIX,javbus.com,Proxy +DOMAIN-SUFFIX,jayparkinsonmd.com,Proxy +DOMAIN-SUFFIX,jbtalks.cc,Proxy +DOMAIN-SUFFIX,jbtalks.com,Proxy +DOMAIN-SUFFIX,jbtalks.my,Proxy +DOMAIN-SUFFIX,jdwsy.com,Proxy +DOMAIN-SUFFIX,jeanyim.com,Proxy +DOMAIN-SUFFIX,jgoodies.com,Proxy +DOMAIN-SUFFIX,jiaoyou8.com,Proxy +DOMAIN-SUFFIX,jiehua.cz,Proxy +DOMAIN-SUFFIX,jieshibaobao.com,Proxy +DOMAIN-SUFFIX,jigong1024.com,Proxy +DOMAIN-SUFFIX,jimoparty.com,Proxy +DOMAIN-SUFFIX,jinbushe.org,Proxy +DOMAIN-SUFFIX,jingpin.org,Proxy +DOMAIN-SUFFIX,jitouch.com,Proxy +DOMAIN-SUFFIX,jkforum.net,Proxy +DOMAIN-SUFFIX,j.mp,Proxy +DOMAIN-SUFFIX,joachims.org,Proxy +DOMAIN-SUFFIX,jobso.tv,Proxy +DOMAIN-SUFFIX,joeedelman.com,Proxy +DOMAIN-SUFFIX,journalofdemocracy.org,Proxy +DOMAIN-SUFFIX,jp.hao123.com,Proxy +DOMAIN-SUFFIX,jpl.nasa.gov,Proxy +DOMAIN-SUFFIX,jpopforum.net,Proxy +DOMAIN-SUFFIX,jshint.com,Proxy +DOMAIN-SUFFIX,juliepost.com,Proxy +DOMAIN-SUFFIX,juliereyc.com,Proxy +DOMAIN-SUFFIX,junauza.com,Proxy +DOMAIN-SUFFIX,junefourth-20.net,Proxy +DOMAIN-SUFFIX,justfreevpn.com,Proxy +DOMAIN-SUFFIX,justtristan.com,Proxy +DOMAIN-SUFFIX,juyuange.org,Proxy +DOMAIN-SUFFIX,juziyue.com,Proxy +DOMAIN-SUFFIX,jwmusic.org,Proxy +DOMAIN-SUFFIX,jwpcdn.com,Proxy +DOMAIN-SUFFIX,jyxf.net,Proxy +DOMAIN-SUFFIX,jyzj.waqn.com,Proxy +DOMAIN-SUFFIX,k2.xrea.com,Proxy +DOMAIN-SUFFIX,kagyuoffice.org,Proxy +DOMAIN-SUFFIX,kagyuoffice.org.tw,Proxy +DOMAIN-SUFFIX,kaiyuan.de,Proxy +DOMAIN-SUFFIX,kakao.com,Proxy +DOMAIN-SUFFIX,kanzhongguo.com,Proxy +DOMAIN-SUFFIX,kanzhongguo.eu,Proxy +DOMAIN-SUFFIX,karayou.com,Proxy +DOMAIN-SUFFIX,kat.cr,Proxy +DOMAIN-SUFFIX,ka-wai.com,Proxy +DOMAIN-SUFFIX,kcsoftwares.com,Proxy +DOMAIN-SUFFIX,kechara.com,Proxy +DOMAIN-SUFFIX,keepandshare.com,Proxy +DOMAIN-SUFFIX,keepvid.com,Proxy +DOMAIN-SUFFIX,kendincos.net,Proxy +DOMAIN-SUFFIX,kenengba.com,Proxy +DOMAIN-SUFFIX,keontech.net,Proxy +DOMAIN-SUFFIX,khabdha.org,Proxy +DOMAIN-SUFFIX,khmusic.com.tw,Proxy +DOMAIN-SUFFIX,killwall.com,Proxy +DOMAIN-SUFFIX,kineox.free.fr,Proxy +DOMAIN-SUFFIX,kingdomsalvation.org,Proxy +DOMAIN-SUFFIX,kinghost.com,Proxy +DOMAIN-SUFFIX,kingstone.com.tw,Proxy +DOMAIN-SUFFIX,kissbbao.cn,Proxy +DOMAIN-SUFFIX,kiwi.kz,Proxy +DOMAIN-SUFFIX,klip.me,Proxy +DOMAIN-SUFFIX,kmt.org.tw,Proxy +DOMAIN-SUFFIX,knowledgerush.com,Proxy +DOMAIN-SUFFIX,knowledge.yahoo.com,Proxy +DOMAIN-SUFFIX,kodingen.com,Proxy +DOMAIN-SUFFIX,kompozer.net,Proxy +DOMAIN-SUFFIX,koolsolutions.com,Proxy +DOMAIN-SUFFIX,koornk.com,Proxy +DOMAIN-SUFFIX,kt.kcome.org,Proxy +DOMAIN-SUFFIX,kui.name,Proxy +DOMAIN-SUFFIX,kuliwang.com,Proxy +DOMAIN-SUFFIX,kun.im,Proxy +DOMAIN-SUFFIX,kurashsultan.com,Proxy +DOMAIN-SUFFIX,kurtmunger.com,Proxy +DOMAIN-SUFFIX,kusocity.com,Proxy +DOMAIN-SUFFIX,kwcg.ca,Proxy +DOMAIN-SUFFIX,kwongwah.com.my,Proxy +DOMAIN-SUFFIX,kyohk.net,Proxy +DOMAIN-SUFFIX,kzeng.info,Proxy +DOMAIN-SUFFIX,labiennale.org,Proxy +DOMAIN-SUFFIX,ladbrokes.com,Proxy +DOMAIN-SUFFIX,la-forum.org,Proxy +DOMAIN-SUFFIX,lagranepoca.com,Proxy +DOMAIN-SUFFIX,lalulalu.com,Proxy +DOMAIN-SUFFIX,lamenhu.com,Proxy +DOMAIN-SUFFIX,lancome.com,Proxy +DOMAIN-SUFFIX,laogai.org,Proxy +DOMAIN-SUFFIX,laomiu.com,Proxy +DOMAIN-SUFFIX,laoyang.info,Proxy +DOMAIN-SUFFIX,laptoplockdown.com,Proxy +DOMAIN-SUFFIX,laqingdan.net,Proxy +DOMAIN-SUFFIX,larsgeorge.com,Proxy +DOMAIN-SUFFIX,lastfm.es,Proxy +DOMAIN-SUFFIX,lastpass.com,Proxy +DOMAIN-SUFFIX,latelinenews.com,Proxy +DOMAIN-SUFFIX,latibet.org,Proxy +DOMAIN-SUFFIX,latimesblogs.latimes.com,Proxy +DOMAIN-SUFFIX,lazarsearlymusic.com,Proxy +DOMAIN-SUFFIX,leecheukyan.org,Proxy +DOMAIN-SUFFIX,legaltech.law.com,Proxy +DOMAIN-SUFFIX,leirentv.ca,Proxy +DOMAIN-SUFFIX,leisurecafe.ca,Proxy +DOMAIN-SUFFIX,lematin.ch,Proxy +DOMAIN-SUFFIX,lemonde.fr,Proxy +DOMAIN-SUFFIX,lenwhite.com,Proxy +DOMAIN-SUFFIX,lerosua.org,Proxy +DOMAIN-SUFFIX,lesoir.be,Proxy +DOMAIN-SUFFIX,lesscss.org,Proxy +DOMAIN-SUFFIX,letscorp.net,Proxy +DOMAIN-SUFFIX,liansi.org,Proxy +DOMAIN-SUFFIX,lianyue.net,Proxy +DOMAIN-SUFFIX,liaowangxizang.net,Proxy +DOMAIN-SUFFIX,liberal.org.hk,Proxy +DOMAIN-SUFFIX,libertytimes.com.tw,Proxy +DOMAIN-SUFFIX,library.usc.cuhk.edu.hk,Proxy +DOMAIN-SUFFIX,lib.virginia.edu,Proxy +DOMAIN-SUFFIX,licdn.com,Proxy +DOMAIN-SUFFIX,lich355.megabyet.net,Proxy +DOMAIN-SUFFIX,lidecheng.com,Proxy +DOMAIN-SUFFIX,life.fly4ever.me,Proxy +DOMAIN-SUFFIX,lifemiles.com,Proxy +DOMAIN-SUFFIX,limiao.net,Proxy +DOMAIN-SUFFIX,line.me,Proxy +DOMAIN-SUFFIX,line.naver.jp,Proxy +DOMAIN-SUFFIX,linglingfa.com,Proxy +DOMAIN-SUFFIX,lingvodics.com,Proxy +DOMAIN-SUFFIX,linkedin.com,Proxy +DOMAIN-SUFFIX,linkideo.com,Proxy +DOMAIN-SUFFIX,linksalpha.com,Proxy +DOMAIN-SUFFIX,linode.com,Proxy +DOMAIN-SUFFIX,linuxconfig.org,Proxy +DOMAIN-SUFFIX,linux-engineer.net,Proxy +DOMAIN-SUFFIX,linuxreviews.org,Proxy +DOMAIN-SUFFIX,linuxtoy.org,Proxy +DOMAIN-SUFFIX,lipuman.com,Proxy +DOMAIN-SUFFIX,listentoyoutube.com,Proxy +DOMAIN-SUFFIX,list.ly,Proxy +DOMAIN-SUFFIX,listorious.com,Proxy +DOMAIN-SUFFIX,lists.debian.org,Proxy +DOMAIN-SUFFIX,lists.w3.org,Proxy +DOMAIN-SUFFIX,lithium.com,Proxy +DOMAIN-SUFFIX,littlebigdetails.com,Proxy +DOMAIN-SUFFIX,liudejun.com,Proxy +DOMAIN-SUFFIX,liuhanyu.com,Proxy +DOMAIN-SUFFIX,liujianshu.com,Proxy +DOMAIN-SUFFIX,liu.lu,Proxy +DOMAIN-SUFFIX,liuxiaotong.com,Proxy +DOMAIN-SUFFIX,liveleak.com,Proxy +DOMAIN-SUFFIX,livestation.com,Proxy +DOMAIN-SUFFIX,livestream.com,Proxy +DOMAIN-SUFFIX,livevideo.com,Proxy +DOMAIN-SUFFIX,livingonline.us,Proxy +DOMAIN-SUFFIX,livingstream.com,Proxy +DOMAIN-SUFFIX,lizhizhuangbi.com,Proxy +DOMAIN-SUFFIX,lkcn.net,Proxy +DOMAIN-SUFFIX,llnwd.net,Proxy +DOMAIN-SUFFIX,localpresshk.com,Proxy +DOMAIN-SUFFIX,lockdown.com,Proxy +DOMAIN-SUFFIX,lockestek.com,Proxy +DOMAIN-SUFFIX,lofi.e-hentai.org,Proxy +DOMAIN-SUFFIX,logbot.net,Proxy +DOMAIN-SUFFIX,logiqx.com,Proxy +DOMAIN-SUFFIX,logmike.com,Proxy +DOMAIN-SUFFIX,log.riku.me,Proxy +DOMAIN-SUFFIX,loiclemeur.com,Proxy +DOMAIN-SUFFIX,london.neighborhoodr.com,Proxy +DOMAIN-SUFFIX,longhair.hk,Proxy +DOMAIN-SUFFIX,longtermly.net,Proxy +DOMAIN-SUFFIX,lookatgame.com,Proxy +DOMAIN-SUFFIX,lookingglasstheatre.org,Proxy +DOMAIN-SUFFIX,lookpic.com,Proxy +DOMAIN-SUFFIX,looktoronto.com,Proxy +DOMAIN-SUFFIX,lotsawahouse.org,Proxy +DOMAIN-SUFFIX,lotuslight.org.tw,Proxy +DOMAIN-SUFFIX,lovequicksilver.com,Proxy +DOMAIN-SUFFIX,lrfz.com,Proxy +DOMAIN-SUFFIX,lrip.org,Proxy +DOMAIN-SUFFIX,lsd.org.hk,Proxy +DOMAIN-SUFFIX,lsforum.net,Proxy +DOMAIN-SUFFIX,lsmchinese.org,Proxy +DOMAIN-SUFFIX,lsmkorean.org,Proxy +DOMAIN-SUFFIX,lsm.org,Proxy +DOMAIN-SUFFIX,lsmradio.com,Proxy +DOMAIN-SUFFIX,lsxszzg.com,Proxy +DOMAIN-SUFFIX,ltn.com.tw,Proxy +DOMAIN-SUFFIX,luntan.zaobao.com,Proxy +DOMAIN-SUFFIX,lupm.org,Proxy +DOMAIN-SUFFIX,lushstories.com,Proxy +DOMAIN-SUFFIX,lvhai.org,Proxy +DOMAIN-SUFFIX,lvv2.com,Proxy +DOMAIN-SUFFIX,lyricsquote.com,Proxy +DOMAIN-SUFFIX,mac.com,Proxy +DOMAIN-SUFFIX,macgamestore.com,Proxy +DOMAIN-SUFFIX,macrovpn.com,Proxy +DOMAIN-SUFFIX,macys.com,Proxy +DOMAIN-SUFFIX,mad-ar.ch,Proxy +DOMAIN-SUFFIX,madmenunbuttoned.com,Proxy +DOMAIN-SUFFIX,magazines.sina.com.tw,Proxy +DOMAIN-SUFFIX,ma.hao123.com,Proxy +DOMAIN-SUFFIX,maiio.net,Proxy +DOMAIN-SUFFIX,mail-archive.com,Proxy +DOMAIN-SUFFIX,mailchimp.com,Proxy +DOMAIN-SUFFIX,maiplus.com,Proxy +DOMAIN-SUFFIX,makemymood.com,Proxy +DOMAIN-SUFFIX,makzhou.warehouse333.com,Proxy +DOMAIN-SUFFIX,malaysiakini.com,Proxy +DOMAIN-SUFFIX,marc.info,Proxy +DOMAIN-SUFFIX,marco.org,Proxy +DOMAIN-SUFFIX,marguerite.su,Proxy +DOMAIN-SUFFIX,marines.mil,Proxy +DOMAIN-SUFFIX,marinsm.com,Proxy +DOMAIN-SUFFIX,markmail.org,Proxy +DOMAIN-SUFFIX,markmilian.com,Proxy +DOMAIN-SUFFIX,martau.com,Proxy +DOMAIN-SUFFIX,martincartoons.com,Proxy +DOMAIN-SUFFIX,martsangkagyuofficial.org,Proxy +DOMAIN-SUFFIX,maruta.be,Proxy +DOMAIN-SUFFIX,marxist.com,Proxy +DOMAIN-SUFFIX,marxist.net,Proxy +DOMAIN-SUFFIX,marxists.org,Proxy +DOMAIN-SUFFIX,mashable.com,Proxy +DOMAIN-SUFFIX,mash.to,Proxy +DOMAIN-SUFFIX,matainja.com,Proxy +DOMAIN-SUFFIX,mathiew-badimon.com,Proxy +DOMAIN-SUFFIX,matsushimakaede.com,Proxy +DOMAIN-SUFFIX,maturejp.com,Proxy +DOMAIN-SUFFIX,maxgif.com,Proxy +DOMAIN-SUFFIX,mayimayi.com,Proxy +DOMAIN-SUFFIX,mcadforums.com,Proxy +DOMAIN-SUFFIX,mcfog.com,Proxy +DOMAIN-SUFFIX,md-t.org,Proxy +DOMAIN-SUFFIX,mediafire.com,Proxy +DOMAIN-SUFFIX,meetup.com,Proxy +DOMAIN-SUFFIX,mefeedia.com,Proxy +DOMAIN-SUFFIX,megaporn.com,Proxy +DOMAIN-SUFFIX,megaproxy.com,Proxy +DOMAIN-SUFFIX,megarotic.com,Proxy +DOMAIN-SUFFIX,megaupload.com,Proxy +DOMAIN-SUFFIX,megavideo.com,Proxy +DOMAIN-SUFFIX,megurineluka.com,Proxy +DOMAIN-SUFFIX,meirixiaochao.com,Proxy +DOMAIN-SUFFIX,melon-peach.com,Proxy +DOMAIN-SUFFIX,memedia.cn,Proxy +DOMAIN-SUFFIX,memehk.com,Proxy +DOMAIN-SUFFIX,meme.yahoo.com,Proxy +DOMAIN-SUFFIX,memrijttm.org,Proxy +DOMAIN-SUFFIX,merit-times.com.tw,Proxy +DOMAIN-SUFFIX,mesotw.com,Proxy +DOMAIN-SUFFIX,metacafe.com,Proxy +DOMAIN-SUFFIX,metarthunter.com,Proxy +DOMAIN-SUFFIX,meteorshowersonline.com,Proxy +DOMAIN-SUFFIX,metrolife.ca,Proxy +DOMAIN-SUFFIX,metro.taipei,Proxy +DOMAIN-SUFFIX,mfxmedia.com,Proxy +DOMAIN-SUFFIX,mgoon.com,Proxy +DOMAIN-SUFFIX,mgstage.com,Proxy +DOMAIN-SUFFIX,mh4u.org,Proxy +DOMAIN-SUFFIX,mhradio.org,Proxy +DOMAIN-SUFFIX,michaelanti.com,Proxy +DOMAIN-SUFFIX,michaelmarketl.com,Proxy +DOMAIN-SUFFIX,middle-way.net,Proxy +DOMAIN-SUFFIX,mihk.hk,Proxy +DOMAIN-SUFFIX,mihua.org,Proxy +DOMAIN-SUFFIX,mike.cz.cc,Proxy +DOMAIN-SUFFIX,mimivip.com,Proxy +DOMAIN-SUFFIX,mimivv.com,Proxy +DOMAIN-SUFFIX,mindrolling.org,Proxy +DOMAIN-SUFFIX,minghui-a.org,Proxy +DOMAIN-SUFFIX,minghui-b.org,Proxy +DOMAIN-SUFFIX,minghui.org,Proxy +DOMAIN-SUFFIX,minghui-school.org,Proxy +DOMAIN-SUFFIX,mingjinglishi.com,Proxy +DOMAIN-SUFFIX,mingjingnews.com,Proxy +DOMAIN-SUFFIX,mingjingtimes.com,Proxy +DOMAIN-SUFFIX,mingpaocanada.com,Proxy +DOMAIN-SUFFIX,mingpao.com,Proxy +DOMAIN-SUFFIX,mingpaomonthly.com,Proxy +DOMAIN-SUFFIX,mingpaonews.com,Proxy +DOMAIN-SUFFIX,mingpaony.com,Proxy +DOMAIN-SUFFIX,mingpaosf.com,Proxy +DOMAIN-SUFFIX,mingpaotor.com,Proxy +DOMAIN-SUFFIX,mingpaovan.com,Proxy +DOMAIN-SUFFIX,mingshengbao.com,Proxy +DOMAIN-SUFFIX,minimalmac.com,Proxy +DOMAIN-SUFFIX,mininova.org,Proxy +DOMAIN-SUFFIX,ministrybooks.org,Proxy +DOMAIN-SUFFIX,minus.com,Proxy +DOMAIN-SUFFIX,minzhuhua.net,Proxy +DOMAIN-SUFFIX,minzhuzhanxian.com,Proxy +DOMAIN-SUFFIX,minzhuzhongguo.org,Proxy +DOMAIN-SUFFIX,miroguide.com,Proxy +DOMAIN-SUFFIX,mirrorbooks.com,Proxy +DOMAIN-SUFFIX,mitbbs.com,Proxy +DOMAIN-SUFFIX,mixedmedialabs.com,Proxy +DOMAIN-SUFFIX,mixero.com,Proxy +DOMAIN-SUFFIX,mixpod.com,Proxy +DOMAIN-SUFFIX,mixx.com,Proxy +DOMAIN-SUFFIX,mizzmona.com,Proxy +DOMAIN-SUFFIX,mjlsh.usc.cuhk.edu.hk,Proxy +DOMAIN-SUFFIX,mk5000.com,Proxy +DOMAIN-SUFFIX,mlcool.com,Proxy +DOMAIN-SUFFIX,mmaaxx.com,Proxy +DOMAIN-SUFFIX,mmmca.com,Proxy +DOMAIN-SUFFIX,mobatek.net,Proxy +DOMAIN-SUFFIX,mobile01.com,Proxy +DOMAIN-SUFFIX,mobileways.de,Proxy +DOMAIN-SUFFIX,mobypicture.com,Proxy +DOMAIN-SUFFIX,moby.to,Proxy +DOMAIN-SUFFIX,mockable.io,Proxy +DOMAIN-SUFFIX,modedamour.com,Proxy +DOMAIN-SUFFIX,modfetish.com,Proxy +DOMAIN-SUFFIX,modmyi.com,Proxy +DOMAIN-SUFFIX,mog.com,Proxy +DOMAIN-SUFFIX,molihua.org,Proxy +DOMAIN-SUFFIX,mondex.org,Proxy +DOMAIN-SUFFIX,monitorchina.org,Proxy +DOMAIN-SUFFIX,monlamit.org,Proxy +DOMAIN-SUFFIX,morningsun.org,Proxy +DOMAIN-SUFFIX,m.oulove.org,Proxy +DOMAIN-SUFFIX,movabletype.com,Proxy +DOMAIN-SUFFIX,moviefap.com,Proxy +DOMAIN-SUFFIX,moxa.com,Proxy +DOMAIN-SUFFIX,moztw.org,Proxy +DOMAIN-SUFFIX,mp3ye.eu,Proxy +DOMAIN-SUFFIX,mpettis.com,Proxy +DOMAIN-SUFFIX,mpfinance.com,Proxy +DOMAIN-SUFFIX,mpinews.com,Proxy +DOMAIN-SUFFIX,m.plixi.com,Proxy +DOMAIN-SUFFIX,mrdoob.com,Proxy +DOMAIN-SUFFIX,mrtweet.com,Proxy +DOMAIN-SUFFIX,msguancha.com,Proxy +DOMAIN-SUFFIX,m.slandr.net,Proxy +DOMAIN-SUFFIX,m-sport.co.uk,Proxy +DOMAIN-SUFFIX,m-team.cc,Proxy +DOMAIN-SUFFIX,mthruf.com,Proxy +DOMAIN-SUFFIX,m.tweete.net,Proxy +DOMAIN-SUFFIX,mtw.tl,Proxy +DOMAIN-SUFFIX,multiply.com,Proxy +DOMAIN-SUFFIX,multiproxy.org,Proxy +DOMAIN-SUFFIX,multiupload.com,Proxy +DOMAIN-SUFFIX,muouju.com,Proxy +DOMAIN-SUFFIX,muselinks.co.jp,Proxy +DOMAIN-SUFFIX,muzi.com,Proxy +DOMAIN-SUFFIX,muzi.net,Proxy +DOMAIN-SUFFIX,muzu.tv,Proxy +DOMAIN-SUFFIX,mx981.com,Proxy +DOMAIN-SUFFIX,myactimes.com,Proxy +DOMAIN-SUFFIX,my-addr.com,Proxy +DOMAIN-SUFFIX,myaudiocast.com,Proxy +DOMAIN-SUFFIX,myav.com.tw,Proxy +DOMAIN-SUFFIX,myboooks.googlepages.com,Proxy +DOMAIN-SUFFIX,mychinamyhome.com,Proxy +DOMAIN-SUFFIX,mycould.com,Proxy +DOMAIN-SUFFIX,myeclipseide.com,Proxy +DOMAIN-SUFFIX,myequil.com,Proxy +DOMAIN-SUFFIX,myforum.com.hk,Proxy +DOMAIN-SUFFIX,myforum.com.uk,Proxy +DOMAIN-SUFFIX,myfreshnet.com,Proxy +DOMAIN-SUFFIX,my.keso.cn,Proxy +DOMAIN-SUFFIX,myopenid.com,Proxy +DOMAIN-SUFFIX,my.opera.com,Proxy +DOMAIN-SUFFIX,myparagliding.com,Proxy +DOMAIN-SUFFIX,mypopescu.com,Proxy +DOMAIN-SUFFIX,my-proxy.com,Proxy +DOMAIN-SUFFIX,myshare.url.com.tw,Proxy +DOMAIN-SUFFIX,mysinablog.com,Proxy +DOMAIN-SUFFIX,myspace.com,Proxy +DOMAIN-SUFFIX,naacoalition.org,Proxy +DOMAIN-SUFFIX,naitik.net,Proxy +DOMAIN-SUFFIX,nakido.com,Proxy +DOMAIN-SUFFIX,name.com,Proxy +DOMAIN-SUFFIX,namsisi.com,Proxy +DOMAIN-SUFFIX,nanyang.com,Proxy +DOMAIN-SUFFIX,nanyangpost.com,Proxy +DOMAIN-SUFFIX,nanzao.com,Proxy +DOMAIN-SUFFIX,naol.ca,Proxy +DOMAIN-SUFFIX,national-lottery.co.uk,Proxy +DOMAIN-SUFFIX,navicat.com,Proxy +DOMAIN-SUFFIX,navigeaters.com,Proxy +DOMAIN-SUFFIX,navy.mil,Proxy +DOMAIN-SUFFIX,nbc.com,Proxy +DOMAIN-SUFFIX,nccwatch.org.tw,Proxy +DOMAIN-SUFFIX,nch.com.tw,Proxy +DOMAIN-SUFFIX,ncn.org,Proxy +DOMAIN-SUFFIX,nde.de,Proxy +DOMAIN-SUFFIX,ndr.de,Proxy +DOMAIN-SUFFIX,ned.org,Proxy +DOMAIN-SUFFIX,nekoslovakia.net,Proxy +DOMAIN-SUFFIX,nemesis2.qx.net,Proxy +DOMAIN-SUFFIX,netcolony.com,Proxy +DOMAIN-SUFFIX,netflix.com,Proxy +DOMAIN-SUFFIX,netme.cc,Proxy +DOMAIN-SUFFIX,networkedblogs.com,Proxy +DOMAIN-SUFFIX,neverforget8964.org,Proxy +DOMAIN-SUFFIX,new-3lunch.net,Proxy +DOMAIN-SUFFIX,new-akiba.com,Proxy +DOMAIN-SUFFIX,newcenturymc.com,Proxy +DOMAIN-SUFFIX,newcenturynews.com,Proxy +DOMAIN-SUFFIX,newchen.com,Proxy +DOMAIN-SUFFIX,newgrounds.com,Proxy +DOMAIN-SUFFIX,newlandmagazine.com.au,Proxy +DOMAIN-SUFFIX,newmobilelife.com,Proxy +DOMAIN-SUFFIX,news100.com.tw,Proxy +DOMAIN-SUFFIX,newsancai.com,Proxy +DOMAIN-SUFFIX,news.atebits.com,Proxy +DOMAIN-SUFFIX,news.bbc.co.uk,Proxy +DOMAIN-SUFFIX,newscn.org,Proxy +DOMAIN-SUFFIX,news.cnyes.com,Proxy +DOMAIN-SUFFIX,newsforums.bbc.co.uk,Proxy +DOMAIN-SUFFIX,news.ghostery.com,Proxy +DOMAIN-SUFFIX,newsminer.com,Proxy +DOMAIN-SUFFIX,news.msn.com.tw,Proxy +DOMAIN-SUFFIX,news.now.com,Proxy +DOMAIN-SUFFIX,news.omy.sg,Proxy +DOMAIN-SUFFIX,newspeak.cc,Proxy +DOMAIN-SUFFIX,news.sina.com.hk,Proxy +DOMAIN-SUFFIX,news.sina.com.tw,Proxy +DOMAIN-SUFFIX,news.sinchew.com.my,Proxy +DOMAIN-SUFFIX,news.singtao.ca,Proxy +DOMAIN-SUFFIX,newstapa.org,Proxy +DOMAIN-SUFFIX,newtaiwan.com.tw,Proxy +DOMAIN-SUFFIX,newtalk.tw,Proxy +DOMAIN-SUFFIX,newyorktimes.com,Proxy +DOMAIN-SUFFIX,nextmedia.com,Proxy +DOMAIN-SUFFIX,nexton-net.jp,Proxy +DOMAIN-SUFFIX,nexttv.com.tw,Proxy +DOMAIN-SUFFIX,nf.id.au,Proxy +DOMAIN-SUFFIX,nga.mil,Proxy +DOMAIN-SUFFIX,ngensis.com,Proxy +DOMAIN-SUFFIX,ngrok.com,Proxy +DOMAIN-SUFFIX,nic.cz.cc,Proxy +DOMAIN-SUFFIX,nicovideo.jp,Proxy +DOMAIN-SUFFIX,nighost.org,Proxy +DOMAIN-SUFFIX,ninecommentaries.com,Proxy +DOMAIN-SUFFIX,nintendium.com,Proxy +DOMAIN-SUFFIX,niusnews.com,Proxy +DOMAIN-SUFFIX,njactb.org,Proxy +DOMAIN-SUFFIX,njuice.com,Proxy +DOMAIN-SUFFIX,nlfreevpn.com,Proxy +DOMAIN-SUFFIX,nobelprize.org,Proxy +DOMAIN-SUFFIX,nobel.se,Proxy +DOMAIN-SUFFIX,nobodycanstop.us,Proxy +DOMAIN-SUFFIX,nokogiri.org,Proxy +DOMAIN-SUFFIX,nokola.com,Proxy +DOMAIN-SUFFIX,noobbox.com,Proxy +DOMAIN-SUFFIX,norbulingka.org,Proxy +DOMAIN-SUFFIX,nordstrom.com,Proxy +DOMAIN-SUFFIX,nordstromimage.com,Proxy +DOMAIN-SUFFIX,notes.alexdong.com,Proxy +DOMAIN-SUFFIX,novelasia.com,Proxy +DOMAIN-SUFFIX,nownews.com,Proxy +DOMAIN-SUFFIX,nowtorrents.com,Proxy +DOMAIN-SUFFIX,noypf.com,Proxy +DOMAIN-SUFFIX,npa.go.jp,Proxy +DOMAIN-SUFFIX,nps.gov,Proxy +DOMAIN-SUFFIX,nrk.no,Proxy +DOMAIN-SUFFIX,nsc.gov.tw,Proxy +DOMAIN-SUFFIX,ntd.tv,Proxy +DOMAIN-SUFFIX,ntdtv.ca,Proxy +DOMAIN-SUFFIX,ntdtv.co,Proxy +DOMAIN-SUFFIX,ntdtv.com,Proxy +DOMAIN-SUFFIX,ntdtv.org,Proxy +DOMAIN-SUFFIX,ntdtv.ru,Proxy +DOMAIN-SUFFIX,nubiles.net,Proxy +DOMAIN-SUFFIX,nuexpo.com,Proxy +DOMAIN-SUFFIX,nurgo-software.com,Proxy +DOMAIN-SUFFIX,nuuvem.com,Proxy +DOMAIN-SUFFIX,nuvid.com,Proxy +DOMAIN-SUFFIX,nuzcom.com,Proxy +DOMAIN-SUFFIX,nvquan.org,Proxy +DOMAIN-SUFFIX,nwtca.org,Proxy +DOMAIN-SUFFIX,nyaa.se,Proxy +DOMAIN-SUFFIX,nydus.ca,Proxy +DOMAIN-SUFFIX,nysingtao.com,Proxy +DOMAIN-SUFFIX,nytco.com,Proxy +DOMAIN-SUFFIX,nyt.com,Proxy +DOMAIN-SUFFIX,nytimes.com,Proxy +DOMAIN-SUFFIX,nytimg.com,Proxy +DOMAIN-SUFFIX,ny.visiontimes.com,Proxy +DOMAIN-SUFFIX,nzchinese.net.nz,Proxy +DOMAIN-SUFFIX,oasic.net,Proxy +DOMAIN-SUFFIX,observechina.net,Proxy +DOMAIN-SUFFIX,oclp.hk,Proxy +DOMAIN-SUFFIX,ocsp.digicert.com,Proxy +DOMAIN-SUFFIX,october-review.org,Proxy +DOMAIN-SUFFIX,offbeatchina.com,Proxy +DOMAIN-SUFFIX,officeoftibet.com,Proxy +DOMAIN-SUFFIX,ogaoga.org,Proxy +DOMAIN-SUFFIX,oikos.com.tw,Proxy +DOMAIN-SUFFIX,oiktv.com,Proxy +DOMAIN-SUFFIX,oizoblog.com,Proxy +DOMAIN-SUFFIX,okayfreedom.com,Proxy +DOMAIN-SUFFIX,old-cat.net,Proxy +DOMAIN-SUFFIX,old.honeynet.org,Proxy +DOMAIN-SUFFIX,old.nabble.com,Proxy +DOMAIN-SUFFIX,olumpo.com,Proxy +DOMAIN-SUFFIX,olympicwatch.org,Proxy +DOMAIN-SUFFIX,omgili.com,Proxy +DOMAIN-SUFFIX,omnitalk.com,Proxy +DOMAIN-SUFFIX,omnitalk.org,Proxy +DOMAIN-SUFFIX,on.cc,Proxy +DOMAIN-SUFFIX,onedrive.live.com,Proxy +DOMAIN-SUFFIX,one.xthost.info,Proxy +DOMAIN-SUFFIX,onion.city,Proxy +DOMAIN-SUFFIX,onlylady.cn,Proxy +DOMAIN-SUFFIX,onmoon.com,Proxy +DOMAIN-SUFFIX,onmoon.net,Proxy +DOMAIN-SUFFIX,ontrac.com,Proxy +DOMAIN-SUFFIX,oopsforum.com,Proxy +DOMAIN-SUFFIX,open.com.hk,Proxy +DOMAIN-SUFFIX,open-consoles-news.com,Proxy +DOMAIN-SUFFIX,opendemocracy.net,Proxy +DOMAIN-SUFFIX,openid.net,Proxy +DOMAIN-SUFFIX,openleaks.org,Proxy +DOMAIN-SUFFIX,openvpn.net,Proxy +DOMAIN-SUFFIX,openwebster.com,Proxy +DOMAIN-SUFFIX,openwrt.org,Proxy +DOMAIN-SUFFIX,opml.radiotime.com,Proxy +DOMAIN-SUFFIX,opnir.com,Proxy +DOMAIN-SUFFIX,orchidbbs.com,Proxy +DOMAIN-SUFFIX,organharvestinvestigation.net,Proxy +DOMAIN-SUFFIX,orientaldaily.com.my,Proxy +DOMAIN-SUFFIX,orientaldaily.on.cc,Proxy +DOMAIN-SUFFIX,orient-doll.com,Proxy +DOMAIN-SUFFIX,orn.jp,Proxy +DOMAIN-SUFFIX,orzistic.org,Proxy +DOMAIN-SUFFIX,osaka69.com,Proxy +DOMAIN-SUFFIX,osfoora.com,Proxy +DOMAIN-SUFFIX,osmdroid.net,Proxy +DOMAIN-SUFFIX,ourdearamy.com,Proxy +DOMAIN-SUFFIX,oursogo.com,Proxy +DOMAIN-SUFFIX,oursteps.com.au,Proxy +DOMAIN-SUFFIX,overlapr.com,Proxy +DOMAIN-SUFFIX,owind.com,Proxy +DOMAIN-SUFFIX,owl.li,Proxy +DOMAIN-SUFFIX,ow.ly,Proxy +DOMAIN-SUFFIX,oxid.it,Proxy +DOMAIN-SUFFIX,oyax.com,Proxy +DOMAIN-SUFFIX,ozchinese.com,Proxy +DOMAIN-SUFFIX,ozyoyo.com,Proxy +DOMAIN-SUFFIX,pacificpoker.com,Proxy +DOMAIN-SUFFIX,packages.debian.org,Proxy +DOMAIN-SUFFIX,packetix.net,Proxy +DOMAIN-SUFFIX,paddle.com,Proxy +DOMAIN-SUFFIX,padmanet.com,Proxy +DOMAIN-SUFFIX,page2rss.com,Proxy +DOMAIN-SUFFIX,page.bid.yahoo.com,Proxy +DOMAIN-SUFFIX,pagodabox.com,Proxy +DOMAIN-SUFFIX,paint.net,Proxy +DOMAIN-SUFFIX,palacemoon.com,Proxy +DOMAIN-SUFFIX,paljorpublications.com,Proxy +DOMAIN-SUFFIX,pandora.com,Proxy +DOMAIN-SUFFIX,pandora.tv,Proxy +DOMAIN-SUFFIX,panluan.net,Proxy +DOMAIN-SUFFIX,panoramio.com,Proxy +DOMAIN-SUFFIX,pao-pao.net,Proxy +DOMAIN-SUFFIX,paperb.us,Proxy +DOMAIN-SUFFIX,paper.li,Proxy +DOMAIN-SUFFIX,paper-replika.com,Proxy +DOMAIN-SUFFIX,parade.com,Proxy +DOMAIN-SUFFIX,parislemon.com,Proxy +DOMAIN-SUFFIX,parkansky.com,Proxy +DOMAIN-SUFFIX,passion.com,Proxy +DOMAIN-SUFFIX,passiontimes.hk,Proxy +DOMAIN-SUFFIX,pastebin.com,Proxy +DOMAIN-SUFFIX,pastie.org,Proxy +DOMAIN-SUFFIX,pbs.org,Proxy +DOMAIN-SUFFIX,pbwiki.com,Proxy +DOMAIN-SUFFIX,pbworks.com,Proxy +DOMAIN-SUFFIX,pbxes.com,Proxy +DOMAIN-SUFFIX,pbxes.org,Proxy +DOMAIN-SUFFIX,pcdiscuss.com,Proxy +DOMAIN-SUFFIX,p-cdn.com,Proxy +DOMAIN-SUFFIX,pcdvd.com.tw,Proxy +DOMAIN-SUFFIX,pchome.com.tw,Proxy +DOMAIN-SUFFIX,pcij.org,Proxy +DOMAIN-SUFFIX,pct.org.tw,Proxy +DOMAIN-SUFFIX,pdetails.com,Proxy +DOMAIN-SUFFIX,pdproxy.com,Proxy +DOMAIN-SUFFIX,pds.nasa.gov,Proxy +DOMAIN-SUFFIX,peace.ca,Proxy +DOMAIN-SUFFIX,peacefire.org,Proxy +DOMAIN-SUFFIX,peacehall.com,Proxy +DOMAIN-SUFFIX,pearlher.org,Proxy +DOMAIN-SUFFIX,peeasian.com,Proxy +DOMAIN-SUFFIX,peerpong.com,Proxy +DOMAIN-SUFFIX,pekingduck.org,Proxy +DOMAIN-SUFFIX,penchinese.com,Proxy +DOMAIN-SUFFIX,penchinese.net,Proxy +DOMAIN-SUFFIX,pengyulong.com,Proxy +DOMAIN-SUFFIX,penthouse.com,Proxy +DOMAIN-SUFFIX,peopo.org,Proxy +DOMAIN-SUFFIX,percy.in,Proxy +DOMAIN-SUFFIX,perfectgirls.net,Proxy +DOMAIN-SUFFIX,perfectvpn.net,Proxy +DOMAIN-SUFFIX,perfspot.com,Proxy +DOMAIN-SUFFIX,perlhowto.com,Proxy +DOMAIN-SUFFIX,persecutionblog.com,Proxy +DOMAIN-SUFFIX,phayul.com,Proxy +DOMAIN-SUFFIX,philly.com,Proxy +DOMAIN-SUFFIX,phonesat.org,Proxy +DOMAIN-SUFFIX,photodharma.net,Proxy +DOMAIN-SUFFIX,photofocus.com,Proxy +DOMAIN-SUFFIX,photos.dailyme.com,Proxy +DOMAIN-SUFFIX,photo.utom.us,Proxy +DOMAIN-SUFFIX,phuquocservices.com,Proxy +DOMAIN-SUFFIX,picidae.net,Proxy +DOMAIN-SUFFIX,picturedip.com,Proxy +DOMAIN-SUFFIX,picturesocial.com,Proxy +DOMAIN-SUFFIX,pictures.playboy.com,Proxy +DOMAIN-SUFFIX,pidown.com,Proxy +DOMAIN-SUFFIX,pign.net,Proxy +DOMAIN-SUFFIX,pimg.tw,Proxy +DOMAIN-SUFFIX,pin6.com,Proxy +DOMAIN-SUFFIX,pinboard.in,Proxy +DOMAIN-SUFFIX,ping.fm,Proxy +DOMAIN-SUFFIX,pinimg.com,Proxy +DOMAIN-SUFFIX,pinoy-n.com,Proxy +DOMAIN-SUFFIX,pinporn.com,Proxy +DOMAIN-SUFFIX,pinterest.com,Proxy +DOMAIN-SUFFIX,pioneer-worker.forums-free.com,Proxy +DOMAIN-SUFFIX,piposay.com,Proxy +DOMAIN-SUFFIX,piring.com,Proxy +DOMAIN-SUFFIX,pixelqi.com,Proxy +DOMAIN-SUFFIX,pixnet.net,Proxy +DOMAIN-SUFFIX,pk.com,Proxy +DOMAIN-SUFFIX,placemix.com,Proxy +DOMAIN-SUFFIX,planetsuzy.org,Proxy +DOMAIN-SUFFIX,playboy.com,Proxy +DOMAIN-SUFFIX,playpcesor.com,Proxy +DOMAIN-SUFFIX,plays.com.tw,Proxy +DOMAIN-SUFFIX,plm.org.hk,Proxy +DOMAIN-SUFFIX,plunder.com,Proxy +DOMAIN-SUFFIX,plurktop.mmdays.com,Proxy +DOMAIN-SUFFIX,plus28.com,Proxy +DOMAIN-SUFFIX,plusbb.com,Proxy +DOMAIN-SUFFIX,pmates.com,Proxy +DOMAIN-SUFFIX,po2b.com,Proxy +DOMAIN-SUFFIX,podictionary.com,Proxy +DOMAIN-SUFFIX,pokerstars.com,Proxy +DOMAIN-SUFFIX,politicalchina.org,Proxy +DOMAIN-SUFFIX,politicalconsultation.org,Proxy +DOMAIN-SUFFIX,popapp.in,Proxy +DOMAIN-SUFFIX,popularpages.net,Proxy +DOMAIN-SUFFIX,popvote.hk,Proxy +DOMAIN-SUFFIX,popyard.com,Proxy +DOMAIN-SUFFIX,popyard.org,Proxy +DOMAIN-SUFFIX,porn2.com,Proxy +DOMAIN-SUFFIX,pornbase.org,Proxy +DOMAIN-SUFFIX,porn.com,Proxy +DOMAIN-SUFFIX,pornhd.com,Proxy +DOMAIN-SUFFIX,pornhub.com,Proxy +DOMAIN-SUFFIX,pornmm.net,Proxy +DOMAIN-SUFFIX,pornoxo.com,Proxy +DOMAIN-SUFFIX,pornrapidshare.com,Proxy +DOMAIN-SUFFIX,pornstarclub.com,Proxy +DOMAIN-SUFFIX,porntube.com,Proxy +DOMAIN-SUFFIX,pornvisit.com,Proxy +DOMAIN-SUFFIX,portablevpn.nl,Proxy +DOMAIN-SUFFIX,pose.com,Proxy +DOMAIN-SUFFIX,post852.com,Proxy +DOMAIN-SUFFIX,postadult.com,Proxy +DOMAIN-SUFFIX,post.anyu.org,Proxy +DOMAIN-SUFFIX,posterous.com,Proxy +DOMAIN-SUFFIX,post.ly,Proxy +DOMAIN-SUFFIX,powerapple.com,Proxy +DOMAIN-SUFFIX,power.com,Proxy +DOMAIN-SUFFIX,powercx.com,Proxy +DOMAIN-SUFFIX,powerpointninja.com,Proxy +DOMAIN-SUFFIX,prayforchina.net,Proxy +DOMAIN-SUFFIX,premeforwindows7.com,Proxy +DOMAIN-SUFFIX,presentationzen.com,Proxy +DOMAIN-SUFFIX,prestige-av.com,Proxy +DOMAIN-SUFFIX,prisoneralert.com,Proxy +DOMAIN-SUFFIX,pritunl.com,Proxy +DOMAIN-SUFFIX,privacybox.de,Proxy +DOMAIN-SUFFIX,privateinternetaccess.com,Proxy +DOMAIN-SUFFIX,privatepaste.com,Proxy +DOMAIN-SUFFIX,privatetunnel.com,Proxy +DOMAIN-SUFFIX,privoxy.org,Proxy +DOMAIN-SUFFIX,procopytips.com,Proxy +DOMAIN-SUFFIX,proctoru.com,Proxy +DOMAIN-SUFFIX,prosiben.de,Proxy +DOMAIN-SUFFIX,provideocoalition.com,Proxy +DOMAIN-SUFFIX,proxifier.com,Proxy +DOMAIN-SUFFIX,proxomitron.info,Proxy +DOMAIN-SUFFIX,proxy.googlezip.net,Proxy +DOMAIN-SUFFIX,proxy.org,Proxy +DOMAIN-SUFFIX,proxypy.net,Proxy +DOMAIN-SUFFIX,proxyroad.com,Proxy +DOMAIN-SUFFIX,prozz.net,Proxy +DOMAIN-SUFFIX,psblog.name,Proxy +DOMAIN-SUFFIX,psiphon.ca,Proxy +DOMAIN-SUFFIX,psiphon.civisec.org,Proxy +DOMAIN-SUFFIX,pts.org.tw,Proxy +DOMAIN-SUFFIX,ptt.cc,Proxy +DOMAIN-SUFFIX,pubu.com.tw,Proxy +DOMAIN-SUFFIX,puffinbrowser.com,Proxy +DOMAIN-SUFFIX,puffstore.com,Proxy +DOMAIN-SUFFIX,pullfolio.com,Proxy +DOMAIN-SUFFIX,pulse.yahoo.com,Proxy +DOMAIN-SUFFIX,pure18.com,Proxy +DOMAIN-SUFFIX,pureconcepts.net,Proxy +DOMAIN-SUFFIX,pureinsight.org,Proxy +DOMAIN-SUFFIX,purepdf.com,Proxy +DOMAIN-SUFFIX,purevpn.com,Proxy +DOMAIN-SUFFIX,putlocker.com,Proxy +DOMAIN-SUFFIX,puttycm.free.fr,Proxy +DOMAIN-SUFFIX,putty.org,Proxy +DOMAIN-SUFFIX,pwned.com,Proxy +DOMAIN-SUFFIX,pypi.python.org,Proxy +DOMAIN-SUFFIX,python.com,Proxy +DOMAIN-SUFFIX,python.com.tw,Proxy +DOMAIN-SUFFIX,qanote.com,Proxy +DOMAIN-SUFFIX,qidian.ca,Proxy +DOMAIN-SUFFIX,qienkuen.org,Proxy +DOMAIN-SUFFIX,qi-gong.me,Proxy +DOMAIN-SUFFIX,qiwen.lu,Proxy +DOMAIN-SUFFIX,qixianglu.cn,Proxy +DOMAIN-SUFFIX,qkshare.com,Proxy +DOMAIN-SUFFIX,qoos.com,Proxy +DOMAIN-SUFFIX,qq.co.za,Proxy +DOMAIN-SUFFIX,qstatus.com,Proxy +DOMAIN-SUFFIX,qtrac.eu,Proxy +DOMAIN-SUFFIX,qtweeter.com,Proxy +DOMAIN-SUFFIX,quadedge.com,Proxy +DOMAIN-SUFFIX,quitccp.net,Proxy +DOMAIN-SUFFIX,quitccp.org,Proxy +DOMAIN-SUFFIX,quora.com,Proxy +DOMAIN-SUFFIX,quran.com,Proxy +DOMAIN-SUFFIX,qusi8.net,Proxy +DOMAIN-SUFFIX,qvodzy.org,Proxy +DOMAIN-SUFFIX,qxbbs.org,Proxy +DOMAIN-SUFFIX,radicalparty.org,Proxy +DOMAIN-SUFFIX,radiko.jp,Proxy +DOMAIN-SUFFIX,radioaustralia.net.au,Proxy +DOMAIN-SUFFIX,radiohilight.net,Proxy +DOMAIN-SUFFIX,radiovaticana.org,Proxy +DOMAIN-SUFFIX,radiovncr.com,Proxy +DOMAIN-SUFFIX,raidcall.com.tw,Proxy +DOMAIN-SUFFIX,raidtalk.com.tw,Proxy +DOMAIN-SUFFIX,rangzen.com,Proxy +DOMAIN-SUFFIX,rangzen.net,Proxy +DOMAIN-SUFFIX,rangzen.org,Proxy +DOMAIN-SUFFIX,ranyunfei.com,Proxy +DOMAIN-SUFFIX,rapbull.net,Proxy +DOMAIN-SUFFIX,rapidgator.net,Proxy +DOMAIN-SUFFIX,rapidshare8.com,Proxy +DOMAIN-SUFFIX,rapidsharedata.com,Proxy +DOMAIN-SUFFIX,raspberrypi.org,Proxy +DOMAIN-SUFFIX,rcinet.ca,Proxy +DOMAIN-SUFFIX,rconversation.blogs.com,Proxy +DOMAIN-SUFFIX,rd.io,Proxy +DOMAIN-SUFFIX,rdio.com,Proxy +DOMAIN-SUFFIX,read100.com,Proxy +DOMAIN-SUFFIX,readingtimes.com.tw,Proxy +DOMAIN-SUFFIX,readmoo.com,Proxy +DOMAIN-SUFFIX,realcourage.org,Proxy +DOMAIN-SUFFIX,realraptalk.com,Proxy +DOMAIN-SUFFIX,recaptcha.net,Proxy +DOMAIN-SUFFIX,recordhistory.org,Proxy +DOMAIN-SUFFIX,redchinacn.org,Proxy +DOMAIN-SUFFIX,redtube.com,Proxy +DOMAIN-SUFFIX,referer.us,Proxy +DOMAIN-SUFFIX,reflectivecode.com,Proxy +DOMAIN-SUFFIX,rekrytointipalvelut.info,Proxy +DOMAIN-SUFFIX,relaxbbs.com,Proxy +DOMAIN-SUFFIX,releaseinternational.org,Proxy +DOMAIN-SUFFIX,religioustolerance.org,Proxy +DOMAIN-SUFFIX,renminbao.com,Proxy +DOMAIN-SUFFIX,renyurenquan.org,Proxy +DOMAIN-SUFFIX,research.jmsc.hku.hk,Proxy +DOMAIN-SUFFIX,ressim.net,Proxy +DOMAIN-SUFFIX,retaildesignblog.net,Proxy +DOMAIN-SUFFIX,retweeteffect.com,Proxy +DOMAIN-SUFFIX,retweetist.com,Proxy +DOMAIN-SUFFIX,retweetrank.com,Proxy +DOMAIN-SUFFIX,reuters.com,Proxy +DOMAIN-SUFFIX,revleft.com,Proxy +DOMAIN-SUFFIX,revver.com,Proxy +DOMAIN-SUFFIX,rfachina.com,Proxy +DOMAIN-SUFFIX,rfamobile.org,Proxy +DOMAIN-SUFFIX,rfa.org,Proxy +DOMAIN-SUFFIX,rferl.org,Proxy +DOMAIN-SUFFIX,rfi.fr,Proxy +DOMAIN-SUFFIX,rfi.my,Proxy +DOMAIN-SUFFIX,rhcloud.com,Proxy +DOMAIN-SUFFIX,riitek.com,Proxy +DOMAIN-SUFFIX,riku.me,Proxy +DOMAIN-SUFFIX,rileyguide.com,Proxy +DOMAIN-SUFFIX,ritouki.jp,Proxy +DOMAIN-SUFFIX,rlwlw.com,Proxy +DOMAIN-SUFFIX,rmjdw.com,Proxy +DOMAIN-SUFFIX,rnw.nl,Proxy +DOMAIN-SUFFIX,robtex.com,Proxy +DOMAIN-SUFFIX,robustnessiskey.com,Proxy +DOMAIN-SUFFIX,rocmp.org,Proxy +DOMAIN-SUFFIX,rojo.com,Proxy +DOMAIN-SUFFIX,ronjoneswriter.com,Proxy +DOMAIN-SUFFIX,roodo.com,Proxy +DOMAIN-SUFFIX,rosechina.net,Proxy +DOMAIN-SUFFIX,rotten.com,Proxy +DOMAIN-SUFFIX,rottetstudio.com,Proxy +DOMAIN-SUFFIX,rsf-chinese.org,Proxy +DOMAIN-SUFFIX,rsf.org,Proxy +DOMAIN-SUFFIX,rssmeme.com,Proxy +DOMAIN-SUFFIX,rthk.hk,Proxy +DOMAIN-SUFFIX,rthk.hk.edgesuite.net,Proxy +DOMAIN-SUFFIX,rthk.org.hk,Proxy +DOMAIN-SUFFIX,rti.org.tw,Proxy +DOMAIN-SUFFIX,ruanyifeng.com,Proxy +DOMAIN-SUFFIX,rushbee.com,Proxy +DOMAIN-SUFFIX,rutube.ru,Proxy +DOMAIN-SUFFIX,ruyiseek.com,Proxy +DOMAIN-SUFFIX,rxhj.net,Proxy +DOMAIN-SUFFIX,s1heng.com,Proxy +DOMAIN-SUFFIX,s3.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3-eu-west-1.amazonaws.com,Proxy +DOMAIN-SUFFIX,s4miniarchive.com,Proxy +DOMAIN-SUFFIX,s8forum.com,Proxy +DOMAIN-SUFFIX,sacom.hk,Proxy +DOMAIN-SUFFIX,sadpanda.us,Proxy +DOMAIN-SUFFIX,sa.hao123.com,Proxy +DOMAIN-SUFFIX,saiq.me,Proxy +DOMAIN-SUFFIX,sakuralive.com,Proxy +DOMAIN-SUFFIX,salvation.org.hk,Proxy +DOMAIN-SUFFIX,samair.ru,Proxy +DOMAIN-SUFFIX,sambhota.org,Proxy +DOMAIN-SUFFIX,sammyjs.org,Proxy +DOMAIN-SUFFIX,samsoff.es,Proxy +DOMAIN-SUFFIX,sandnoble.com,Proxy +DOMAIN-SUFFIX,sankaizok.com,Proxy +DOMAIN-SUFFIX,sanmin.com.tw,Proxy +DOMAIN-SUFFIX,sapikachu.net,Proxy +DOMAIN-SUFFIX,savemedia.com,Proxy +DOMAIN-SUFFIX,savetibet.de,Proxy +DOMAIN-SUFFIX,savetibet.fr,Proxy +DOMAIN-SUFFIX,savetibet.nl,Proxy +DOMAIN-SUFFIX,savetibet.org,Proxy +DOMAIN-SUFFIX,savetibet.ru,Proxy +DOMAIN-SUFFIX,savevid.com,Proxy +DOMAIN-SUFFIX,say2.info,Proxy +DOMAIN-SUFFIX,sbnation.com,Proxy +DOMAIN-SUFFIX,scalatest.org,Proxy +DOMAIN-SUFFIX,sciencemag.org,Proxy +DOMAIN-SUFFIX,scim.ag,Proxy +DOMAIN-SUFFIX,scmpchinese.com,Proxy +DOMAIN-SUFFIX,scmp.com,Proxy +DOMAIN-SUFFIX,scribd.com,Proxy +DOMAIN-SUFFIX,scriptspot.com,Proxy +DOMAIN-SUFFIX,s-cute.com,Proxy +DOMAIN-SUFFIX,s-dragon.org,Proxy +DOMAIN-SUFFIX,seapuff.com,Proxy +DOMAIN-SUFFIX,secretchina.com,Proxy +DOMAIN-SUFFIX,secretgarden.no,Proxy +DOMAIN-SUFFIX,secure.wikimedia.org,Proxy +DOMAIN-SUFFIX,securitykiss.com,Proxy +DOMAIN-SUFFIX,seesmic.com,Proxy +DOMAIN-SUFFIX,seevpn.com,Proxy +DOMAIN-SUFFIX,seezone.net,Proxy +DOMAIN-SUFFIX,sejie.com,Proxy +DOMAIN-SUFFIX,sendoid.com,Proxy +DOMAIN-SUFFIX,sendspace.com,Proxy +DOMAIN-SUFFIX,sephora.com,Proxy +DOMAIN-SUFFIX,sesawe.net,Proxy +DOMAIN-SUFFIX,sesawe.org,Proxy +DOMAIN-SUFFIX,sethwklein.net,Proxy +DOMAIN-SUFFIX,sevenload.com,Proxy +DOMAIN-SUFFIX,sex-11.com,Proxy +DOMAIN-SUFFIX,sex3.com,Proxy +DOMAIN-SUFFIX,sex8.cc,Proxy +DOMAIN-SUFFIX,sexandsubmission.com,Proxy +DOMAIN-SUFFIX,sex.com,Proxy +DOMAIN-SUFFIX,sexhuang.com,Proxy +DOMAIN-SUFFIX,sexhu.com,Proxy +DOMAIN-SUFFIX,sexinsex.net,Proxy +DOMAIN-SUFFIX,sfileydy.com,Proxy +DOMAIN-SUFFIX,sf.net,Proxy +DOMAIN-SUFFIX,sftuk.org,Proxy +DOMAIN-SUFFIX,sha7.info,Proxy +DOMAIN-SUFFIX,shadow.ma,Proxy +DOMAIN-SUFFIX,shadowsocks.org,Proxy +DOMAIN-SUFFIX,shahamat-english.com,Proxy +DOMAIN-SUFFIX,shangfang.org,Proxy +DOMAIN-SUFFIX,shapeservices.com,Proxy +DOMAIN-SUFFIX,sharebee.com,Proxy +DOMAIN-SUFFIX,sharecool.org,Proxy +DOMAIN-SUFFIX,share.ovi.com,Proxy +DOMAIN-SUFFIX,share.skype.com,Proxy +DOMAIN-SUFFIX,share.youthwant.com.tw,Proxy +DOMAIN-SUFFIX,sharkdolphin.com,Proxy +DOMAIN-SUFFIX,sharpdaily.com.hk,Proxy +DOMAIN-SUFFIX,sharpdaily.hk,Proxy +DOMAIN-SUFFIX,shat-tibet.com,Proxy +DOMAIN-SUFFIX,shaunthesheep.com,Proxy +DOMAIN-SUFFIX,sheikyermami.com,Proxy +DOMAIN-SUFFIX,shellmix.com,Proxy +DOMAIN-SUFFIX,shenshou.org,Proxy +DOMAIN-SUFFIX,shenyun.com,Proxy +DOMAIN-SUFFIX,shenyunperformingarts.org,Proxy +DOMAIN-SUFFIX,shenzhoufilm.com,Proxy +DOMAIN-SUFFIX,shifeike.blog125.fc2blog.net,Proxy +DOMAIN-SUFFIX,shinychan.com,Proxy +DOMAIN-SUFFIX,shitaotv.org,Proxy +DOMAIN-SUFFIX,shixiao.org,Proxy +DOMAIN-SUFFIX,shizhao.org,Proxy +DOMAIN-SUFFIX,shkspr.mobi,Proxy +DOMAIN-SUFFIX,shodanhq.com,Proxy +DOMAIN-SUFFIX,shopping.com,Proxy +DOMAIN-SUFFIX,showbiz.omy.sg,Proxy +DOMAIN-SUFFIX,showtime.jp,Proxy +DOMAIN-SUFFIX,shutterstock.com,Proxy +DOMAIN-SUFFIX,shwchurch3.com,Proxy +DOMAIN-SUFFIX,sidelinesnews.com,Proxy +DOMAIN-SUFFIX,sidelinessportseatery.com,Proxy +DOMAIN-SUFFIX,simplecd.org,Proxy +DOMAIN-SUFFIX,simpleproductivityblog.com,Proxy +DOMAIN-SUFFIX,sin1.g.adnxs.com,Proxy +DOMAIN-SUFFIX,singaporepools.com.sg,Proxy +DOMAIN-SUFFIX,singtao.com,Proxy +DOMAIN-SUFFIX,sinoants.com,Proxy +DOMAIN-SUFFIX,sinocast.com,Proxy +DOMAIN-SUFFIX,sinocism.com,Proxy +DOMAIN-SUFFIX,sino-monthly.com,Proxy +DOMAIN-SUFFIX,sinomontreal.ca,Proxy +DOMAIN-SUFFIX,sinonet.ca,Proxy +DOMAIN-SUFFIX,sinopitt.info,Proxy +DOMAIN-SUFFIX,sinoquebec.com,Proxy +DOMAIN-SUFFIX,sipml5.org,Proxy +DOMAIN-SUFFIX,sis001.com,Proxy +DOMAIN-SUFFIX,sis001.us,Proxy +DOMAIN-SUFFIX,sis.xxx,Proxy +DOMAIN-SUFFIX,site90.net,Proxy +DOMAIN-SUFFIX,sitebro.tw,Proxy +DOMAIN-SUFFIX,sitekreator.com,Proxy +DOMAIN-SUFFIX,siteks.uk.to,Proxy +DOMAIN-SUFFIX,sitemaps.org,Proxy +DOMAIN-SUFFIX,sitetag.us,Proxy +DOMAIN-SUFFIX,si.wsj.net,Proxy +DOMAIN-SUFFIX,sjum.cn,Proxy +DOMAIN-SUFFIX,skimtube.com,Proxy +DOMAIN-SUFFIX,skybet.com,Proxy +DOMAIN-SUFFIX,skyhighpremium.com,Proxy +DOMAIN-SUFFIX,skype.com,Proxy +DOMAIN-SUFFIX,skyvegas.com,Proxy +DOMAIN-SUFFIX,slack.com,Proxy +DOMAIN-SUFFIX,slacker.com,Proxy +DOMAIN-SUFFIX,slack-files.com,Proxy +DOMAIN-SUFFIX,slack-msgs.com,Proxy +DOMAIN-SUFFIX,slashdot.org,Proxy +DOMAIN-SUFFIX,slavasoft.com,Proxy +DOMAIN-SUFFIX,slheng.com,Proxy +DOMAIN-SUFFIX,slickvpn.com,Proxy +DOMAIN-SUFFIX,slideshare.net,Proxy +DOMAIN-SUFFIX,slinkset.com,Proxy +DOMAIN-SUFFIX,slutload.com,Proxy +DOMAIN-SUFFIX,smhric.org,Proxy +DOMAIN-SUFFIX,snapchat.com,Proxy +DOMAIN-SUFFIX,snaptu.com,Proxy +DOMAIN-SUFFIX,sndcdn.com,Proxy +DOMAIN-SUFFIX,sneakme.net,Proxy +DOMAIN-SUFFIX,snooper.co.uk,Proxy +DOMAIN-SUFFIX,snowlionpub.com,Proxy +DOMAIN-SUFFIX,sobees.com,Proxy +DOMAIN-SUFFIX,socialwhale.com,Proxy +DOMAIN-SUFFIX,sockslist.net,Proxy +DOMAIN-SUFFIX,soc.mil,Proxy +DOMAIN-SUFFIX,sod.co.jp,Proxy +DOMAIN-SUFFIX,softether.co.jp,Proxy +DOMAIN-SUFFIX,softether-download.com,Proxy +DOMAIN-SUFFIX,softether.org,Proxy +DOMAIN-SUFFIX,softwarebychuck.com,Proxy +DOMAIN-SUFFIX,softwaredownload.gitbooks.io,Proxy +DOMAIN-SUFFIX,so-ga.net,Proxy +DOMAIN-SUFFIX,sogclub.com,Proxy +DOMAIN-SUFFIX,sogrady.me,Proxy +DOMAIN-SUFFIX,sohcradio.com,Proxy +DOMAIN-SUFFIX,sohfrance.org,Proxy +DOMAIN-SUFFIX,soh.tw,Proxy +DOMAIN-SUFFIX,sokamonline.com,Proxy +DOMAIN-SUFFIX,solozorro.tk,Proxy +DOMAIN-SUFFIX,somee.com,Proxy +DOMAIN-SUFFIX,so-news.com,Proxy +DOMAIN-SUFFIX,songjianjun.com,Proxy +DOMAIN-SUFFIX,sonidodelaesperanza.org,Proxy +DOMAIN-SUFFIX,sopcast.com,Proxy +DOMAIN-SUFFIX,sopcast.org,Proxy +DOMAIN-SUFFIX,sorting-algorithms.com,Proxy +DOMAIN-SUFFIX,soumo.info,Proxy +DOMAIN-SUFFIX,soundcloud.com,Proxy +DOMAIN-SUFFIX,soundofhope.kr,Proxy +DOMAIN-SUFFIX,soundofhope.org,Proxy +DOMAIN-SUFFIX,soup.io,Proxy +DOMAIN-SUFFIX,soupofmedia.com,Proxy +DOMAIN-SUFFIX,sourceforge.net,Proxy +DOMAIN-SUFFIX,southnews.com.tw,Proxy +DOMAIN-SUFFIX,sowers.org.hk,Proxy +DOMAIN-SUFFIX,space-scape.com,Proxy +DOMAIN-SUFFIX,spankbang.com,Proxy +DOMAIN-SUFFIX,spankwire.com,Proxy +DOMAIN-SUFFIX,spapps.co,Proxy +DOMAIN-SUFFIX,spb.com,Proxy +DOMAIN-SUFFIX,speakerdeck.com,Proxy +DOMAIN-SUFFIX,speckleapp.com,Proxy +DOMAIN-SUFFIX,speedpluss.org,Proxy +DOMAIN-SUFFIX,spencertipping.com,Proxy +DOMAIN-SUFFIX,spinejs.com,Proxy +DOMAIN-SUFFIX,sports.williamhill.com,Proxy +DOMAIN-SUFFIX,spotify.com,Proxy +DOMAIN-SUFFIX,springboardplatform.com,Proxy +DOMAIN-SUFFIX,sproutcore.com,Proxy +DOMAIN-SUFFIX,squarespace.com,Proxy +DOMAIN-SUFFIX,srcf.ucam.org,Proxy +DOMAIN-SUFFIX,ssense.com,Proxy +DOMAIN-SUFFIX,ssh91.com,Proxy +DOMAIN-SUFFIX,ssl-images-amazon.com,Proxy +DOMAIN-SUFFIX,sstatic.net,Proxy +DOMAIN-SUFFIX,stackfile.com,Proxy +DOMAIN-SUFFIX,stackoverflow.com,Proxy +DOMAIN-SUFFIX,standupfortibet.org,Proxy +DOMAIN-SUFFIX,stanford.edu,Proxy +DOMAIN-SUFFIX,starp2p.com,Proxy +DOMAIN-SUFFIX,startpage.com,Proxy +DOMAIN-SUFFIX,state168.com,Proxy +DOMAIN-SUFFIX,static.apple.nextmedia.com,Proxy +DOMAIN-SUFFIX,static.byhours.com,Proxy +DOMAIN-SUFFIX,static.digg.com,Proxy +DOMAIN-SUFFIX,staticflickr.com,Proxy +DOMAIN-SUFFIX,status.twhirl.org,Proxy +DOMAIN-SUFFIX,steampowered.com,Proxy +DOMAIN-SUFFIX,steel-storm.com,Proxy +DOMAIN-SUFFIX,stepmania.com,Proxy +DOMAIN-SUFFIX,sthoo.com,Proxy +DOMAIN-SUFFIX,stickam.com,Proxy +DOMAIN-SUFFIX,stickeraction.com,Proxy +DOMAIN-SUFFIX,stonegames.net,Proxy +DOMAIN-SUFFIX,stoneip.info,Proxy +DOMAIN-SUFFIX,stoptibetcrisis.net,Proxy +DOMAIN-SUFFIX,storagenewsletter.com,Proxy +DOMAIN-SUFFIX,storify.com,Proxy +DOMAIN-SUFFIX,stoweboyd.com,Proxy +DOMAIN-SUFFIX,streamingthe.net,Proxy +DOMAIN-SUFFIX,strongvpn.com,Proxy +DOMAIN-SUFFIX,studentsforafreetibet.org,Proxy +DOMAIN-SUFFIX,student.tw,Proxy +DOMAIN-SUFFIX,stuffimreading.com,Proxy +DOMAIN-SUFFIX,stuffimreading.net,Proxy +DOMAIN-SUFFIX,stumbleupon.com,Proxy +DOMAIN-SUFFIX,stupidbeauty.com,Proxy +DOMAIN-SUFFIX,stupidvideos.com,Proxy +DOMAIN-SUFFIX,subacme.rerouted.org,Proxy +DOMAIN-SUFFIX,sublimetext.com,Proxy +DOMAIN-SUFFIX,sufeng.org,Proxy +DOMAIN-SUFFIX,sugarsync.com,Proxy +DOMAIN-SUFFIX,summify.com,Proxy +DOMAIN-SUFFIX,sun1911.com,Proxy +DOMAIN-SUFFIX,sunporno.com,Proxy +DOMAIN-SUFFIX,suoluo.org,Proxy +DOMAIN-SUFFIX,supertweet.net,Proxy +DOMAIN-SUFFIX,surfeasy.com.au,Proxy +DOMAIN-SUFFIX,surrenderat20.net,Proxy +DOMAIN-SUFFIX,suyangg.com,Proxy +DOMAIN-SUFFIX,svwind.com,Proxy +DOMAIN-SUFFIX,sweux.com,Proxy +DOMAIN-SUFFIX,swift-tools.net,Proxy +DOMAIN-SUFFIX,s.xiaod.in,Proxy +DOMAIN-SUFFIX,sydneytoday.com,Proxy +DOMAIN-SUFFIX,sylfoundation.org,Proxy +DOMAIN-SUFFIX,symauth.com,Proxy +DOMAIN-SUFFIX,symcb.com,Proxy +DOMAIN-SUFFIX,symcd.com,Proxy +DOMAIN-SUFFIX,syncback.com,Proxy +DOMAIN-SUFFIX,sysadmin1138.net,Proxy +DOMAIN-SUFFIX,sysresccd.org,Proxy +DOMAIN-SUFFIX,sytes.net,Proxy +DOMAIN-SUFFIX,szbbs.net,Proxy +DOMAIN-SUFFIX,szetowah.org.hk,Proxy +DOMAIN-SUFFIX,t35.com,Proxy +DOMAIN-SUFFIX,t66y.com,Proxy +DOMAIN-SUFFIX,t88.ca,Proxy +DOMAIN-SUFFIX,taa-usa.org,Proxy +DOMAIN-SUFFIX,tablesgenerator.com,Proxy +DOMAIN-SUFFIX,tabtter.jp,Proxy +DOMAIN-SUFFIX,tacem.org,Proxy +DOMAIN-SUFFIX,tafaward.com,Proxy +DOMAIN-SUFFIX,tagwalk.com,Proxy +DOMAIN-SUFFIX,tagxedo.com,Proxy +DOMAIN-SUFFIX,tahr.org.tw,Proxy +DOMAIN-SUFFIX,taipei.gov.tw,Proxy +DOMAIN-SUFFIX,taipeisociety.org,Proxy +DOMAIN-SUFFIX,taiwandaily.net,Proxy +DOMAIN-SUFFIX,taiwankiss.com,Proxy +DOMAIN-SUFFIX,taiwannation.50webs.com,Proxy +DOMAIN-SUFFIX,taiwannation.com,Proxy +DOMAIN-SUFFIX,taiwannation.com.tw,Proxy +DOMAIN-SUFFIX,taiwannews.com.tw,Proxy +DOMAIN-SUFFIX,taiwanonline.cc,Proxy +DOMAIN-SUFFIX,taiwan-sex.com,Proxy +DOMAIN-SUFFIX,taiwantp.net,Proxy +DOMAIN-SUFFIX,taiwantt.org.tw,Proxy +DOMAIN-SUFFIX,taiwanus.net,Proxy +DOMAIN-SUFFIX,taiwanyes.com,Proxy +DOMAIN-SUFFIX,taiwanyes.ning.com,Proxy +DOMAIN-SUFFIX,talk853.com,Proxy +DOMAIN-SUFFIX,talkboxapp.com,Proxy +DOMAIN-SUFFIX,tamiaode.tk,Proxy +DOMAIN-SUFFIX,tanc.org,Proxy +DOMAIN-SUFFIX,tangben.com,Proxy +DOMAIN-SUFFIX,taolun.info,Proxy +DOMAIN-SUFFIX,tap11.com,Proxy +DOMAIN-SUFFIX,tapbots.com,Proxy +DOMAIN-SUFFIX,target.com,Proxy +DOMAIN-SUFFIX,tarr.uspto.gov,Proxy +DOMAIN-SUFFIX,taup.net,Proxy +DOMAIN-SUFFIX,taup.org.tw,Proxy +DOMAIN-SUFFIX,taweet.com,Proxy +DOMAIN-SUFFIX,tbpic.info,Proxy +DOMAIN-SUFFIX,tbsec.org,Proxy +DOMAIN-SUFFIX,tbsn.org,Proxy +DOMAIN-SUFFIX,tbsseattle.org,Proxy +DOMAIN-SUFFIX,tccwonline.org,Proxy +DOMAIN-SUFFIX,tcewf.org,Proxy +DOMAIN-SUFFIX,tchrd.org,Proxy +DOMAIN-SUFFIX,tcno.net,Proxy +DOMAIN-SUFFIX,t.co,Proxy +DOMAIN-SUFFIX,tdesktop.com,Proxy +DOMAIN-SUFFIX,teamseesmic.com,Proxy +DOMAIN-SUFFIX,teashark.com,Proxy +DOMAIN-SUFFIX,tech2.in.com,Proxy +DOMAIN-SUFFIX,techcrunch.com,Proxy +DOMAIN-SUFFIX,techlifeweb.com,Proxy +DOMAIN-SUFFIX,techparaiso.com,Proxy +DOMAIN-SUFFIX,teck.in,Proxy +DOMAIN-SUFFIX,teensinasia.com,Proxy +DOMAIN-SUFFIX,telecomspace.com,Proxy +DOMAIN-SUFFIX,telegram.me,Proxy +DOMAIN-SUFFIX,telegram.org,Proxy +DOMAIN-SUFFIX,telegraph.co.uk,Proxy +DOMAIN-SUFFIX,tenacy.com,Proxy +DOMAIN-SUFFIX,tetronics.com,Proxy +DOMAIN-SUFFIX,tew.org,Proxy +DOMAIN-SUFFIX,theampfactory.com,Proxy +DOMAIN-SUFFIX,theappleblog.com,Proxy +DOMAIN-SUFFIX,theatrum-belli.com,Proxy +DOMAIN-SUFFIX,thebcomplex.com,Proxy +DOMAIN-SUFFIX,theblemish.com,Proxy +DOMAIN-SUFFIX,thebobs.com,Proxy +DOMAIN-SUFFIX,thebodyshop-usa.com,Proxy +DOMAIN-SUFFIX,thechinabeat.org,Proxy +DOMAIN-SUFFIX,thechinastory.org,Proxy +DOMAIN-SUFFIX,thecoveteur.com,Proxy +DOMAIN-SUFFIX,thedailywh.at,Proxy +DOMAIN-SUFFIX,thedieline.com,Proxy +DOMAIN-SUFFIX,thediplomat.com,Proxy +DOMAIN-SUFFIX,thedw.us,Proxy +DOMAIN-SUFFIX,thefourtheye.in,Proxy +DOMAIN-SUFFIX,thefrontier.hk,Proxy +DOMAIN-SUFFIX,thegatesnotes.com,Proxy +DOMAIN-SUFFIX,thegioitinhoc.vn,Proxy +DOMAIN-SUFFIX,theguardian.co,Proxy +DOMAIN-SUFFIX,theguardian.com,Proxy +DOMAIN-SUFFIX,thehots.info,Proxy +DOMAIN-SUFFIX,thehousenews.com,Proxy +DOMAIN-SUFFIX,thehungrydudes.com,Proxy +DOMAIN-SUFFIX,thehun.net,Proxy +DOMAIN-SUFFIX,theinitium.com,Proxy +DOMAIN-SUFFIX,theinternetwishlist.com,Proxy +DOMAIN-SUFFIX,thelifeyoucansave.com,Proxy +DOMAIN-SUFFIX,thelius.org,Proxy +DOMAIN-SUFFIX,thenewslens.com,Proxy +DOMAIN-SUFFIX,thepiratebay.org,Proxy +DOMAIN-SUFFIX,thepiratebay.se,Proxy +DOMAIN-SUFFIX,theqii.info,Proxy +DOMAIN-SUFFIX,thereallove.kr,Proxy +DOMAIN-SUFFIX,thesartorialist.com,Proxy +DOMAIN-SUFFIX,thesnippetapp.com,Proxy +DOMAIN-SUFFIX,thespeeder.com,Proxy +DOMAIN-SUFFIX,thestandnews.com,Proxy +DOMAIN-SUFFIX,the-sun.on.cc,Proxy +DOMAIN-SUFFIX,thetibetconnection.org,Proxy +DOMAIN-SUFFIX,thetibetmuseum.org,Proxy +DOMAIN-SUFFIX,thetibetpost.com,Proxy +DOMAIN-SUFFIX,thetrotskymovie.com,Proxy +DOMAIN-SUFFIX,thevivekspot.com,Proxy +DOMAIN-SUFFIX,thewgo.org,Proxy +DOMAIN-SUFFIX,th.hao123.com,Proxy +DOMAIN-SUFFIX,thinkingtaiwan.com,Proxy +DOMAIN-SUFFIX,thisav.com,Proxy +DOMAIN-SUFFIX,thisiswhyyouarefat.com,Proxy +DOMAIN-SUFFIX,thkphoto.com,Proxy +DOMAIN-SUFFIX,thomasbernhard.org,Proxy +DOMAIN-SUFFIX,threatchaos.com,Proxy +DOMAIN-SUFFIX,throughnightsfire.com,Proxy +DOMAIN-SUFFIX,t.huhaitai.com,Proxy +DOMAIN-SUFFIX,thumbr.io,Proxy +DOMAIN-SUFFIX,thumbzilla.com,Proxy +DOMAIN-SUFFIX,thywords.com,Proxy +DOMAIN-SUFFIX,tiananmenmother.org,Proxy +DOMAIN-SUFFIX,tiananmenuniv.com,Proxy +DOMAIN-SUFFIX,tiananmenuniv.net,Proxy +DOMAIN-SUFFIX,tiandixing.org,Proxy +DOMAIN-SUFFIX,tianhuayuan.com,Proxy +DOMAIN-SUFFIX,tianlawoffice.com,Proxy +DOMAIN-SUFFIX,tiantibooks.org,Proxy +DOMAIN-SUFFIX,tianzhu.org,Proxy +DOMAIN-SUFFIX,tibetaid.org,Proxy +DOMAIN-SUFFIX,tibetalk.com,Proxy +DOMAIN-SUFFIX,tibetan-alliance.org,Proxy +DOMAIN-SUFFIX,tibetanarts.org,Proxy +DOMAIN-SUFFIX,tibetanculture.org,Proxy +DOMAIN-SUFFIX,tibetanpaintings.com,Proxy +DOMAIN-SUFFIX,tibetanphotoproject.com,Proxy +DOMAIN-SUFFIX,tibetanwomen.org,Proxy +DOMAIN-SUFFIX,tibetanyouthcongress.org,Proxy +DOMAIN-SUFFIX,tibet.a.se,Proxy +DOMAIN-SUFFIX,tibet.at,Proxy +DOMAIN-SUFFIX,tibet.ca,Proxy +DOMAIN-SUFFIX,tibetcharity.dk,Proxy +DOMAIN-SUFFIX,tibetcharity.in,Proxy +DOMAIN-SUFFIX,tibetcity.com,Proxy +DOMAIN-SUFFIX,tibetcollection.com,Proxy +DOMAIN-SUFFIX,tibet.com,Proxy +DOMAIN-SUFFIX,tibetcorps.org,Proxy +DOMAIN-SUFFIX,tibetfocus.com,Proxy +DOMAIN-SUFFIX,tibet-foundation.org,Proxy +DOMAIN-SUFFIX,tibet.fr,Proxy +DOMAIN-SUFFIX,tibetfund.org,Proxy +DOMAIN-SUFFIX,tibethouse.jp,Proxy +DOMAIN-SUFFIX,tibethouse.org,Proxy +DOMAIN-SUFFIX,tibet-house-trust.co.uk,Proxy +DOMAIN-SUFFIX,tibethouse.us,Proxy +DOMAIN-SUFFIX,tibet-info.net,Proxy +DOMAIN-SUFFIX,tibet-initiative.de,Proxy +DOMAIN-SUFFIX,tibetjustice.org,Proxy +DOMAIN-SUFFIX,tibet-munich.de,Proxy +DOMAIN-SUFFIX,tibetmuseum.org,Proxy +DOMAIN-SUFFIX,tibet.net,Proxy +DOMAIN-SUFFIX,tibetnetwork.org,Proxy +DOMAIN-SUFFIX,tibet.nu,Proxy +DOMAIN-SUFFIX,tibetoffice.ch,Proxy +DOMAIN-SUFFIX,tibetoffice.com.au,Proxy +DOMAIN-SUFFIX,tibetoffice.org,Proxy +DOMAIN-SUFFIX,tibetonline.com,Proxy +DOMAIN-SUFFIX,tibetonline.tv,Proxy +DOMAIN-SUFFIX,tibetoralhistory.org,Proxy +DOMAIN-SUFFIX,tibet.org,Proxy +DOMAIN-SUFFIX,tibet.org.tw,Proxy +DOMAIN-SUFFIX,tibetrelieffund.co.uk,Proxy +DOMAIN-SUFFIX,tibetsites.com,Proxy +DOMAIN-SUFFIX,tibetsun.com,Proxy +DOMAIN-SUFFIX,tibettimes.net,Proxy +DOMAIN-SUFFIX,tibetwrites.org,Proxy +DOMAIN-SUFFIX,tidyread.com,Proxy +DOMAIN-SUFFIX,tiffanyarment.com,Proxy +DOMAIN-SUFFIX,time.com,Proxy +DOMAIN-SUFFIX,times.hinet.net,Proxy +DOMAIN-SUFFIX,tinychat.com,Proxy +DOMAIN-SUFFIX,tinypaste.com,Proxy +DOMAIN-SUFFIX,tistory.com,Proxy +DOMAIN-SUFFIX,tjholowaychuk.com,Proxy +DOMAIN-SUFFIX,tkcs-collins.com,Proxy +DOMAIN-SUFFIX,tkforum.tk,Proxy +DOMAIN-SUFFIX,t.kun.im,Proxy +DOMAIN-SUFFIX,tldp.org,Proxy +DOMAIN-SUFFIX,tl.gd,Proxy +DOMAIN-SUFFIX,tmagazine.com,Proxy +DOMAIN-SUFFIX,tmi.me,Proxy +DOMAIN-SUFFIX,tnaflix.com,Proxy +DOMAIN-SUFFIX,t.neolee.cn,Proxy +DOMAIN-SUFFIX,tnp.org,Proxy +DOMAIN-SUFFIX,togetter.com,Proxy +DOMAIN-SUFFIX,tokyo-247.com,Proxy +DOMAIN-SUFFIX,tokyocn.com,Proxy +DOMAIN-SUFFIX,tokyo-hot.com,Proxy +DOMAIN-SUFFIX,tomayko.com,Proxy +DOMAIN-SUFFIX,tomsc.com,Proxy +DOMAIN-SUFFIX,tono-oka.jp,Proxy +DOMAIN-SUFFIX,tonyyan.net,Proxy +DOMAIN-SUFFIX,toodoc.com,Proxy +DOMAIN-SUFFIX,toonel.net,Proxy +DOMAIN-SUFFIX,topic.youthwant.com.tw,Proxy +DOMAIN-SUFFIX,topnews.in,Proxy +DOMAIN-SUFFIX,topshare.us,Proxy +DOMAIN-SUFFIX,topshareware.com,Proxy +DOMAIN-SUFFIX,topstyle4.com,Proxy +DOMAIN-SUFFIX,topsy.com,Proxy +DOMAIN-SUFFIX,toptip.ca,Proxy +DOMAIN-SUFFIX,tora.to,Proxy +DOMAIN-SUFFIX,tor.blingblingsquad.net,Proxy +DOMAIN-SUFFIX,torproject.org,Proxy +DOMAIN-SUFFIX,torrentcrazy.com,Proxy +DOMAIN-SUFFIX,torrentproject.se,Proxy +DOMAIN-SUFFIX,torrentz.eu,Proxy +DOMAIN-SUFFIX,tor.updatestar.com,Proxy +DOMAIN-SUFFIX,torvpn.com,Proxy +DOMAIN-SUFFIX,t.orzdream.com,Proxy +DOMAIN-SUFFIX,tosh.comedycentral.com,Proxy +DOMAIN-SUFFIX,touch99.com,Proxy +DOMAIN-SUFFIX,toutfr.com,Proxy +DOMAIN-SUFFIX,tpi.org.tw,Proxy +DOMAIN-SUFFIX,transgressionism.org,Proxy +DOMAIN-SUFFIX,transparency.org,Proxy +DOMAIN-SUFFIX,trans.wenweipo.com,Proxy +DOMAIN-SUFFIX,travelinlocal.com,Proxy +DOMAIN-SUFFIX,treemall.com.tw,Proxy +DOMAIN-SUFFIX,trendsmap.com,Proxy +DOMAIN-SUFFIX,trialofccp.org,Proxy +DOMAIN-SUFFIX,tripod.com,Proxy +DOMAIN-SUFFIX,trouw.nl,Proxy +DOMAIN-SUFFIX,trtc.com.tw,Proxy +DOMAIN-SUFFIX,trt.net.tr,Proxy +DOMAIN-SUFFIX,trulyergonomic.com,Proxy +DOMAIN-SUFFIX,trustedbi.com,Proxy +DOMAIN-SUFFIX,truth101.co.tv,Proxy +DOMAIN-SUFFIX,truthcn.com,Proxy +DOMAIN-SUFFIX,truveo.com,Proxy +DOMAIN-SUFFIX,tsctv.net,Proxy +DOMAIN-SUFFIX,tsdr.uspto.gov,Proxy +DOMAIN-SUFFIX,tsemtulku.com,Proxy +DOMAIN-SUFFIX,tsquare.tv,Proxy +DOMAIN-SUFFIX,tsunagarumon.com,Proxy +DOMAIN-SUFFIX,tsu.org.tw,Proxy +DOMAIN-SUFFIX,tsuru-bird.net,Proxy +DOMAIN-SUFFIX,tt1069.com,Proxy +DOMAIN-SUFFIX,tt-rss.org,Proxy +DOMAIN-SUFFIX,tttan.com,Proxy +DOMAIN-SUFFIX,tu8964.com,Proxy +DOMAIN-SUFFIX,tuanzt.com,Proxy +DOMAIN-SUFFIX,tube8.com,Proxy +DOMAIN-SUFFIX,tube911.com,Proxy +DOMAIN-SUFFIX,tubecao.com,Proxy +DOMAIN-SUFFIX,tube.com,Proxy +DOMAIN-SUFFIX,tubewolf.com,Proxy +DOMAIN-SUFFIX,tuidang.net,Proxy +DOMAIN-SUFFIX,tuidang.org,Proxy +DOMAIN-SUFFIX,tui.orzdream.com,Proxy +DOMAIN-SUFFIX,tumblr.awflasher.com,Proxy +DOMAIN-SUFFIX,tumblr.com,Proxy +DOMAIN-SUFFIX,tumblweed.org,Proxy +DOMAIN-SUFFIX,tumutanzi.com,Proxy +DOMAIN-SUFFIX,tunein.com,Proxy +DOMAIN-SUFFIX,tunnelbear.com,Proxy +DOMAIN-SUFFIX,tuo8.hk,Proxy +DOMAIN-SUFFIX,tuo8.org,Proxy +DOMAIN-SUFFIX,turbobit.net,Proxy +DOMAIN-SUFFIX,turbotwitter.com,Proxy +DOMAIN-SUFFIX,turningtorso.com,Proxy +DOMAIN-SUFFIX,turntable.fm,Proxy +DOMAIN-SUFFIX,tuxtraining.com,Proxy +DOMAIN-SUFFIX,tuzaijidi.com,Proxy +DOMAIN-SUFFIX,tvants.com,Proxy +DOMAIN-SUFFIX,tvb.com,Proxy +DOMAIN-SUFFIX,tvboxnow.com,Proxy +DOMAIN-SUFFIX,tv.com,Proxy +DOMAIN-SUFFIX,tvider.com,Proxy +DOMAIN-SUFFIX,tv-intros.com,Proxy +DOMAIN-SUFFIX,tv.on.cc,Proxy +DOMAIN-SUFFIX,tvunetworks.com,Proxy +DOMAIN-SUFFIX,tw01.org,Proxy +DOMAIN-SUFFIX,twapperkeeper.com,Proxy +DOMAIN-SUFFIX,twa.sh,Proxy +DOMAIN-SUFFIX,twaud.io,Proxy +DOMAIN-SUFFIX,twbbs.net.tw,Proxy +DOMAIN-SUFFIX,twbbs.org,Proxy +DOMAIN-SUFFIX,twbbs.tw,Proxy +DOMAIN-SUFFIX,twblogger.com,Proxy +DOMAIN-SUFFIX,tweepguide.com,Proxy +DOMAIN-SUFFIX,tweeplike.me,Proxy +DOMAIN-SUFFIX,tweepmag.com,Proxy +DOMAIN-SUFFIX,tweepml.org,Proxy +DOMAIN-SUFFIX,tweetbackup.com,Proxy +DOMAIN-SUFFIX,tweetboard.com,Proxy +DOMAIN-SUFFIX,tweetboner.biz,Proxy +DOMAIN-SUFFIX,tweetdeck.com,Proxy +DOMAIN-SUFFIX,tweetedtimes.com,Proxy +DOMAIN-SUFFIX,tweete.net,Proxy +DOMAIN-SUFFIX,tweetmeme.com,Proxy +DOMAIN-SUFFIX,tweetmylast.fm,Proxy +DOMAIN-SUFFIX,tweetphoto.com,Proxy +DOMAIN-SUFFIX,tweetrans.com,Proxy +DOMAIN-SUFFIX,tweetree.com,Proxy +DOMAIN-SUFFIX,tweets.seraph.me,Proxy +DOMAIN-SUFFIX,tweetwally.com,Proxy +DOMAIN-SUFFIX,tweetymail.com,Proxy +DOMAIN-SUFFIX,twerkingbutt.com,Proxy +DOMAIN-SUFFIX,twftp.org,Proxy +DOMAIN-SUFFIX,tw.gigacircle.com,Proxy +DOMAIN-SUFFIX,tw.hao123.com,Proxy +DOMAIN-SUFFIX,twibase.com,Proxy +DOMAIN-SUFFIX,twibble.de,Proxy +DOMAIN-SUFFIX,twibbon.com,Proxy +DOMAIN-SUFFIX,twibs.com,Proxy +DOMAIN-SUFFIX,twicsy.com,Proxy +DOMAIN-SUFFIX,twifan.com,Proxy +DOMAIN-SUFFIX,twiffo.com,Proxy +DOMAIN-SUFFIX,twiggit.org,Proxy +DOMAIN-SUFFIX,twillo.com,Proxy +DOMAIN-SUFFIX,twilog.org,Proxy +DOMAIN-SUFFIX,twimbow.com,Proxy +DOMAIN-SUFFIX,twimg.com,Proxy +DOMAIN-SUFFIX,twimg.edgesuite.net,Proxy +DOMAIN-SUFFIX,twindexx.com,Proxy +DOMAIN-SUFFIX,twip.me,Proxy +DOMAIN-SUFFIX,twipple.jp,Proxy +DOMAIN-SUFFIX,twishort.com,Proxy +DOMAIN-SUFFIX,twistar.cc,Proxy +DOMAIN-SUFFIX,twisterio.com,Proxy +DOMAIN-SUFFIX,twister.net.co,Proxy +DOMAIN-SUFFIX,twisternow.com,Proxy +DOMAIN-SUFFIX,twistory.net,Proxy +DOMAIN-SUFFIX,twit2d.com,Proxy +DOMAIN-SUFFIX,twitbrowser.net,Proxy +DOMAIN-SUFFIX,twitcause.com,Proxy +DOMAIN-SUFFIX,twitch.tv,Proxy +DOMAIN-SUFFIX,twitgether.com,Proxy +DOMAIN-SUFFIX,twitgoo.com,Proxy +DOMAIN-SUFFIX,twitiq.com,Proxy +DOMAIN-SUFFIX,twitlonger.com,Proxy +DOMAIN-SUFFIX,twitoaster.com,Proxy +DOMAIN-SUFFIX,twitonmsn.com,Proxy +DOMAIN-SUFFIX,twitpic.com,Proxy +DOMAIN-SUFFIX,twitreferral.com,Proxy +DOMAIN-SUFFIX,twitstat.com,Proxy +DOMAIN-SUFFIX,twittbot.net,Proxy +DOMAIN-SUFFIX,twitter4j.org,Proxy +DOMAIN-SUFFIX,twitter.com,Proxy +DOMAIN-SUFFIX,twittercounter.com,Proxy +DOMAIN-SUFFIX,twitterfeed.com,Proxy +DOMAIN-SUFFIX,twittergadget.com,Proxy +DOMAIN-SUFFIX,twitter.jp,Proxy +DOMAIN-SUFFIX,twitterkr.com,Proxy +DOMAIN-SUFFIX,twittermail.com,Proxy +DOMAIN-SUFFIX,twittertim.es,Proxy +DOMAIN-SUFFIX,twitthat.com,Proxy +DOMAIN-SUFFIX,twitturk.com,Proxy +DOMAIN-SUFFIX,twitturly.com,Proxy +DOMAIN-SUFFIX,twitvid.com,Proxy +DOMAIN-SUFFIX,twitzap.com,Proxy +DOMAIN-SUFFIX,twiyia.com,Proxy +DOMAIN-SUFFIX,tw.jiepang.com,Proxy +DOMAIN-SUFFIX,tw.knowledge.yahoo.com,Proxy +DOMAIN-SUFFIX,tw.myblog.yahoo.com,Proxy +DOMAIN-SUFFIX,tw.news.yahoo.com,Proxy +DOMAIN-SUFFIX,tw-npo.org,Proxy +DOMAIN-SUFFIX,twreg.info,Proxy +DOMAIN-SUFFIX,twstar.net,Proxy +DOMAIN-SUFFIX,tw.streetvoice.com,Proxy +DOMAIN-SUFFIX,twt.fm,Proxy +DOMAIN-SUFFIX,twtkr.com,Proxy +DOMAIN-SUFFIX,twtr2src.ogaoga.org,Proxy +DOMAIN-SUFFIX,twtrland.com,Proxy +DOMAIN-SUFFIX,twt.tl,Proxy +DOMAIN-SUFFIX,twttr.com,Proxy +DOMAIN-SUFFIX,twurl.nl,Proxy +DOMAIN-SUFFIX,tw.voa.mobi,Proxy +DOMAIN-SUFFIX,twyac.org,Proxy +DOMAIN-SUFFIX,tw.yahoo.com,Proxy +DOMAIN-SUFFIX,tycool.com,Proxy +DOMAIN-SUFFIX,tynsoe.org,Proxy +DOMAIN-SUFFIX,typekit.net,Proxy +DOMAIN-SUFFIX,typepad.com,Proxy +DOMAIN-SUFFIX,tzangms.com,Proxy +DOMAIN-SUFFIX,ub0.cc,Proxy +DOMAIN-SUFFIX,uberproxy.net,Proxy +DOMAIN-SUFFIX,ubnt.com,Proxy +DOMAIN-SUFFIX,ubuntu.com,Proxy +DOMAIN-SUFFIX,ucdc1998.org,Proxy +DOMAIN-SUFFIX,uderzo.it,Proxy +DOMAIN-SUFFIX,udn.com,Proxy +DOMAIN-SUFFIX,uforadio.com.tw,Proxy +DOMAIN-SUFFIX,ufreevpn.com,Proxy +DOMAIN-SUFFIX,ugo.com,Proxy +DOMAIN-SUFFIX,uhrp.org,Proxy +DOMAIN-SUFFIX,uighurbiz.net,Proxy +DOMAIN-SUFFIX,uighur.nl,Proxy +DOMAIN-SUFFIX,ukchinese.com,Proxy +DOMAIN-SUFFIX,ukliferadio.co.uk,Proxy +DOMAIN-SUFFIX,ulike.net,Proxy +DOMAIN-SUFFIX,ultravpn.fr,Proxy +DOMAIN-SUFFIX,ultraxs.com,Proxy +DOMAIN-SUFFIX,umich.edu,Proxy +DOMAIN-SUFFIX,unblock.cn.com,Proxy +DOMAIN-SUFFIX,unblocksit.es,Proxy +DOMAIN-SUFFIX,uncyclomedia.org,Proxy +DOMAIN-SUFFIX,uncyclopedia.info,Proxy +DOMAIN-SUFFIX,uncyclopedia.tw,Proxy +DOMAIN-SUFFIX,unholyknight.com,Proxy +DOMAIN-SUFFIX,uni.cc,Proxy +DOMAIN-SUFFIX,unicode.org,Proxy +DOMAIN-SUFFIX,uni-due.de,Proxy +DOMAIN-SUFFIX,unification.org.tw,Proxy +DOMAIN-SUFFIX,uninstallapp.org,Proxy +DOMAIN-SUFFIX,uniteddaily.com.my,Proxy +DOMAIN-SUFFIX,unix100.com,Proxy +DOMAIN-SUFFIX,unknownspace.org,Proxy +DOMAIN-SUFFIX,unpo.org,Proxy +DOMAIN-SUFFIX,uocn.org,Proxy +DOMAIN-SUFFIX,upcoming.yahoo.com,Proxy +DOMAIN-SUFFIX,upholdjustice.org,Proxy +DOMAIN-SUFFIX,upload4u.info,Proxy +DOMAIN-SUFFIX,uploaded.net,Proxy +DOMAIN-SUFFIX,uploaded.to,Proxy +DOMAIN-SUFFIX,uploadstation.com,Proxy +DOMAIN-SUFFIX,upload.wikimedia.org,Proxy +DOMAIN-SUFFIX,uproxy.org,Proxy +DOMAIN-SUFFIX,upwill.org,Proxy +DOMAIN-SUFFIX,urbanoutfitters.com,Proxy +DOMAIN-SUFFIX,urlborg.com,Proxy +DOMAIN-SUFFIX,urlparser.com,Proxy +DOMAIN-SUFFIX,usacn.com,Proxy +DOMAIN-SUFFIX,users.skynet.be,Proxy +DOMAIN-SUFFIX,usfk.mil,Proxy +DOMAIN-SUFFIX,usinfo.state.gov,Proxy +DOMAIN-SUFFIX,usma.edu,Proxy +DOMAIN-SUFFIX,usmc.mil,Proxy +DOMAIN-SUFFIX,usmgtcg.ning.com,Proxy +DOMAIN-SUFFIX,us.to,Proxy +DOMAIN-SUFFIX,ustream.tv,Proxy +DOMAIN-SUFFIX,ustwrap.info,Proxy +DOMAIN-SUFFIX,usus.cc,Proxy +DOMAIN-SUFFIX,uushare.com,Proxy +DOMAIN-SUFFIX,uwants.com,Proxy +DOMAIN-SUFFIX,uwants.net,Proxy +DOMAIN-SUFFIX,uyghuramerican.org,Proxy +DOMAIN-SUFFIX,uyghurcanadiansociety.org,Proxy +DOMAIN-SUFFIX,uyghurcongress.org,Proxy +DOMAIN-SUFFIX,uyghurensemble.co.uk,Proxy +DOMAIN-SUFFIX,uyghur-j.org,Proxy +DOMAIN-SUFFIX,uyghurpen.org,Proxy +DOMAIN-SUFFIX,uyghurpress.com,Proxy +DOMAIN-SUFFIX,uygur.fc2web.com,Proxy +DOMAIN-SUFFIX,uygur.org,Proxy +DOMAIN-SUFFIX,uymaarip.com,Proxy +DOMAIN-SUFFIX,v2ex.com,Proxy +DOMAIN-SUFFIX,v70.us,Proxy +DOMAIN-SUFFIX,v7976888.info,Proxy +DOMAIN-SUFFIX,vaayoo.com,Proxy +DOMAIN-SUFFIX,value-domain.com,Proxy +DOMAIN-SUFFIX,van698.com,Proxy +DOMAIN-SUFFIX,vanemu.cn,Proxy +DOMAIN-SUFFIX,vanilla-jp.com,Proxy +DOMAIN-SUFFIX,vansky.com,Proxy +DOMAIN-SUFFIX,vapurl.com,Proxy +DOMAIN-SUFFIX,varnish-cache.org,Proxy +DOMAIN-SUFFIX,vatn.org,Proxy +DOMAIN-SUFFIX,vcfbuilder.org,Proxy +DOMAIN-SUFFIX,vcf-online.org,Proxy +DOMAIN-SUFFIX,vds.rightster.com,Proxy +DOMAIN-SUFFIX,veempiire.com,Proxy +DOMAIN-SUFFIX,vegorpedersen.com,Proxy +DOMAIN-SUFFIX,velkaepocha.sk,Proxy +DOMAIN-SUFFIX,venbbs.com,Proxy +DOMAIN-SUFFIX,venchina.com,Proxy +DOMAIN-SUFFIX,ventureswell.com,Proxy +DOMAIN-SUFFIX,veoh.com,Proxy +DOMAIN-SUFFIX,verizon.net,Proxy +DOMAIN-SUFFIX,verybs.com,Proxy +DOMAIN-SUFFIX,vevo.com,Proxy +DOMAIN-SUFFIX,vft.com.tw,Proxy +DOMAIN-SUFFIX,viber.com,Proxy +DOMAIN-SUFFIX,video.aol.ca,Proxy +DOMAIN-SUFFIX,video.aol.com,Proxy +DOMAIN-SUFFIX,video.aol.co.uk,Proxy +DOMAIN-SUFFIX,video.ap.org,Proxy +DOMAIN-SUFFIX,videobam.com,Proxy +DOMAIN-SUFFIX,video.fdbox.com,Proxy +DOMAIN-SUFFIX,video.foxbusiness.com,Proxy +DOMAIN-SUFFIX,videomega.tv,Proxy +DOMAIN-SUFFIX,videomo.com,Proxy +DOMAIN-SUFFIX,videopediaworld.com,Proxy +DOMAIN-SUFFIX,video.tiscali.it,Proxy +DOMAIN-SUFFIX,video.yahoo.com,Proxy +DOMAIN-SUFFIX,vidoemo.com,Proxy +DOMAIN-SUFFIX,views.fm,Proxy +DOMAIN-SUFFIX,viki.com,Proxy +DOMAIN-SUFFIX,vimeocdn.com,Proxy +DOMAIN-SUFFIX,vimeo.com,Proxy +DOMAIN-SUFFIX,vimgolf.com,Proxy +DOMAIN-SUFFIX,vimperator.org,Proxy +DOMAIN-SUFFIX,vincnd.com,Proxy +DOMAIN-SUFFIX,vineapp.com,Proxy +DOMAIN-SUFFIX,vine.co,Proxy +DOMAIN-SUFFIX,vinniev.com,Proxy +DOMAIN-SUFFIX,vivatube.com,Proxy +DOMAIN-SUFFIX,vjmedia.com.hk,Proxy +DOMAIN-SUFFIX,vllcs.org,Proxy +DOMAIN-SUFFIX,vlog.xuite.net,Proxy +DOMAIN-SUFFIX,vmixcore.com,Proxy +DOMAIN-SUFFIX,vn.hao123.com,Proxy +DOMAIN-SUFFIX,voacantonese.com,Proxy +DOMAIN-SUFFIX,voachineseblog.com,Proxy +DOMAIN-SUFFIX,voachinese.com,Proxy +DOMAIN-SUFFIX,voagd.com,Proxy +DOMAIN-SUFFIX,voanews.com,Proxy +DOMAIN-SUFFIX,voatibetan.com,Proxy +DOMAIN-SUFFIX,vocn.tv,Proxy +DOMAIN-SUFFIX,voicetube.tw,Proxy +DOMAIN-SUFFIX,vot.org,Proxy +DOMAIN-SUFFIX,vox-cdn.com,Proxy +DOMAIN-SUFFIX,voy.com,Proxy +DOMAIN-SUFFIX,vpnbook.com,Proxy +DOMAIN-SUFFIX,vpncup.com,Proxy +DOMAIN-SUFFIX,vpnfire.com,Proxy +DOMAIN-SUFFIX,vpngate.jp,Proxy +DOMAIN-SUFFIX,vpngate.net,Proxy +DOMAIN-SUFFIX,vpnpop.com,Proxy +DOMAIN-SUFFIX,vpnpronet.com,Proxy +DOMAIN-SUFFIX,vpnreviewz.com,Proxy +DOMAIN-SUFFIX,vporn.com,Proxy +DOMAIN-SUFFIX,v-state.org,Proxy +DOMAIN-SUFFIX,vtunnel.com,Proxy +DOMAIN-SUFFIX,w3schools.com,Proxy +DOMAIN-SUFFIX,waffle1999.com,Proxy +DOMAIN-SUFFIX,wahas.com,Proxy +DOMAIN-SUFFIX,waigaobu.com,Proxy +DOMAIN-SUFFIX,waikeung.org,Proxy +DOMAIN-SUFFIX,waiwaier.com,Proxy +DOMAIN-SUFFIX,wallornot.org,Proxy +DOMAIN-SUFFIX,wallpapercasa.com,Proxy +DOMAIN-SUFFIX,wanderinghorse.net,Proxy +DOMAIN-SUFFIX,wangafu.net,Proxy +DOMAIN-SUFFIX,wangjinbo.org,Proxy +DOMAIN-SUFFIX,wanglixiong.com,Proxy +DOMAIN-SUFFIX,wangruoshui.net,Proxy +DOMAIN-SUFFIX,wangruowang.org,Proxy +DOMAIN-SUFFIX,wan-press.org,Proxy +DOMAIN-SUFFIX,want-daily.com,Proxy +DOMAIN-SUFFIX,wapedia.mobi,Proxy +DOMAIN-SUFFIX,waselpro.com,Proxy +DOMAIN-SUFFIX,washeng.net,Proxy +DOMAIN-SUFFIX,watchmygf.net,Proxy +DOMAIN-SUFFIX,wattpad.com,Proxy +DOMAIN-SUFFIX,wav.tv,Proxy +DOMAIN-SUFFIX,wdf5.com,Proxy +DOMAIN-SUFFIX,wearn.com,Proxy +DOMAIN-SUFFIX,web2project.net,Proxy +DOMAIN-SUFFIX,webbang.net,Proxy +DOMAIN-SUFFIX,webfee.tk,Proxy +DOMAIN-SUFFIX,weblagu.com,Proxy +DOMAIN-SUFFIX,webmproject.org,Proxy +DOMAIN-SUFFIX,webrtc.org,Proxy +DOMAIN-SUFFIX,webshots.com,Proxy +DOMAIN-SUFFIX,websitepulse.com,Proxy +DOMAIN-SUFFIX,websnapr.com,Proxy +DOMAIN-SUFFIX,webs-tv.net,Proxy +DOMAIN-SUFFIX,webworkerdaily.com,Proxy +DOMAIN-SUFFIX,weeewooo.net,Proxy +DOMAIN-SUFFIX,weekmag.info,Proxy +DOMAIN-SUFFIX,wefightcensorship.org,Proxy +DOMAIN-SUFFIX,wefong.com,Proxy +DOMAIN-SUFFIX,weiboleak.com,Proxy +DOMAIN-SUFFIX,weigegebyc.dreamhosters.com,Proxy +DOMAIN-SUFFIX,weijingsheng.org,Proxy +DOMAIN-SUFFIX,weiming.info,Proxy +DOMAIN-SUFFIX,weiquanwang.org,Proxy +DOMAIN-SUFFIX,weisuo.ws,Proxy +DOMAIN-SUFFIX,wellplacedpixels.com,Proxy +DOMAIN-SUFFIX,wemigrate.org,Proxy +DOMAIN-SUFFIX,wengewang.com,Proxy +DOMAIN-SUFFIX,wengewang.org,Proxy +DOMAIN-SUFFIX,wenhui.ch,Proxy +DOMAIN-SUFFIX,wenku.com,Proxy +DOMAIN-SUFFIX,wenxuecity.com,Proxy +DOMAIN-SUFFIX,wenyunchao.com,Proxy +DOMAIN-SUFFIX,wepn.info,Proxy +DOMAIN-SUFFIX,westca.com,Proxy +DOMAIN-SUFFIX,westernshugdensociety.org,Proxy +DOMAIN-SUFFIX,westernwolves.com,Proxy +DOMAIN-SUFFIX,westkit.net,Proxy +DOMAIN-SUFFIX,westpoint.edu,Proxy +DOMAIN-SUFFIX,wet123.com,Proxy +DOMAIN-SUFFIX,wetplace.com,Proxy +DOMAIN-SUFFIX,wetpussygames.com,Proxy +DOMAIN-SUFFIX,wexiaobo.org,Proxy +DOMAIN-SUFFIX,wezhiyong.org,Proxy +DOMAIN-SUFFIX,wezone.net,Proxy +DOMAIN-SUFFIX,wforum.com,Proxy +DOMAIN-SUFFIX,whatblocked.com,Proxy +DOMAIN-SUFFIX,whereiswerner.com,Proxy +DOMAIN-SUFFIX,wheretowatch.com,Proxy +DOMAIN-SUFFIX,whippedass.com,Proxy +DOMAIN-SUFFIX,whitebear.freebearblog.org,Proxy +DOMAIN-SUFFIX,who.is,Proxy +DOMAIN-SUFFIX,whydidyoubuymethat.com,Proxy +DOMAIN-SUFFIX,whylover.com,Proxy +DOMAIN-SUFFIX,whyx.org,Proxy +DOMAIN-SUFFIX,w.idaiwan.com,Proxy +DOMAIN-SUFFIX,wiki.cnitter.com,Proxy +DOMAIN-SUFFIX,wiki.gamerp.jp,Proxy +DOMAIN-SUFFIX,wiki.jqueryui.com,Proxy +DOMAIN-SUFFIX,wiki.keso.cn,Proxy +DOMAIN-SUFFIX,wikileaks.ch,Proxy +DOMAIN-SUFFIX,wikileaks.de,Proxy +DOMAIN-SUFFIX,wikileaks.eu,Proxy +DOMAIN-SUFFIX,wikileaks.lu,Proxy +DOMAIN-SUFFIX,wikileaks.org,Proxy +DOMAIN-SUFFIX,wikileaks.pl,Proxy +DOMAIN-SUFFIX,wikilivres.info,Proxy +DOMAIN-SUFFIX,wikimapia.org,Proxy +DOMAIN-SUFFIX,wikimedia.org,Proxy +DOMAIN-SUFFIX,wikimedia.org.mo,Proxy +DOMAIN-SUFFIX,wiki.moegirl.org,Proxy +DOMAIN-SUFFIX,wiki.oauth.net,Proxy +DOMAIN-SUFFIX,wikipedia.com,Proxy +DOMAIN-SUFFIX,wikipedia.org,Proxy +DOMAIN-SUFFIX,wiki.phonegap.com,Proxy +DOMAIN-SUFFIX,wikiwiki.jp,Proxy +DOMAIN-SUFFIX,willw.net,Proxy +DOMAIN-SUFFIX,windowsphoneme.com,Proxy +DOMAIN-SUFFIX,wingamestore.com,Proxy +DOMAIN-SUFFIX,winwhispers.info,Proxy +DOMAIN-SUFFIX,wiredbytes.com,Proxy +DOMAIN-SUFFIX,wiredpen.com,Proxy +DOMAIN-SUFFIX,wireshark.org,Proxy +DOMAIN-SUFFIX,wisdompubs.org,Proxy +DOMAIN-SUFFIX,wisevid.com,Proxy +DOMAIN-SUFFIX,wistia.com,Proxy +DOMAIN-SUFFIX,wistia.net,Proxy +DOMAIN-SUFFIX,witnessleeteaching.com,Proxy +DOMAIN-SUFFIX,witopia.net,Proxy +DOMAIN-SUFFIX,wlx.sowiki.net,Proxy +DOMAIN-SUFFIX,wnacg.com,Proxy +DOMAIN-SUFFIX,wn.com,Proxy +DOMAIN-SUFFIX,woeser.com,Proxy +DOMAIN-SUFFIX,woesermiddle-way.net,Proxy +DOMAIN-SUFFIX,wolfax.com,Proxy +DOMAIN-SUFFIX,womensrightsofchina.org,Proxy +DOMAIN-SUFFIX,woopie.jp,Proxy +DOMAIN-SUFFIX,woopie.tv,Proxy +DOMAIN-SUFFIX,wordboner.com,Proxy +DOMAIN-SUFFIX,wordpress.com,Proxy +DOMAIN-SUFFIX,wordsandturds.com,Proxy +DOMAIN-SUFFIX,w.org,Proxy +DOMAIN-SUFFIX,workatruna.com,Proxy +DOMAIN-SUFFIX,workersthebig.net,Proxy +DOMAIN-SUFFIX,worldcat.org,Proxy +DOMAIN-SUFFIX,worldjournal.com,Proxy +DOMAIN-SUFFIX,worldnews01.com,Proxy +DOMAIN-SUFFIX,worstthingieverate.com,Proxy +DOMAIN-SUFFIX,wo.tc,Proxy +DOMAIN-SUFFIX,wowlegacy.ml,Proxy +DOMAIN-SUFFIX,wow-life.net,Proxy +DOMAIN-SUFFIX,woxinghuiguo.com,Proxy +DOMAIN-SUFFIX,wozy.in,Proxy +DOMAIN-SUFFIX,wp.com,Proxy +DOMAIN-SUFFIX,wpoforum.com,Proxy +DOMAIN-SUFFIX,wqlhw.com,Proxy +DOMAIN-SUFFIX,wqyd.org,Proxy +DOMAIN-SUFFIX,wrangl.com,Proxy +DOMAIN-SUFFIX,wrchina.org,Proxy +DOMAIN-SUFFIX,wretch.cc,Proxy +DOMAIN-SUFFIX,writer.zoho.com,Proxy +DOMAIN-SUFFIX,wsgzao.github.io,Proxy +DOMAIN-SUFFIX,wsj.com,Proxy +DOMAIN-SUFFIX,wsjemail.com,Proxy +DOMAIN-SUFFIX,wsj.net,Proxy +DOMAIN-SUFFIX,wtfpeople.com,Proxy +DOMAIN-SUFFIX,wuala.com,Proxy +DOMAIN-SUFFIX,wuerkaixi.com,Proxy +DOMAIN-SUFFIX,wufi.org.tw,Proxy +DOMAIN-SUFFIX,wufoo.com,Proxy +DOMAIN-SUFFIX,wuguoguang.com,Proxy +DOMAIN-SUFFIX,wujieliulan.com,Proxy +DOMAIN-SUFFIX,wujie.net,Proxy +DOMAIN-SUFFIX,wukangrui.net,Proxy +DOMAIN-SUFFIX,wwitv.com,Proxy +DOMAIN-SUFFIX,www2.ohchr.org,Proxy +DOMAIN-SUFFIX,www2.rocketbbs.com,Proxy +DOMAIN-SUFFIX,wzyboy.im,Proxy +DOMAIN-SUFFIX,x1949x.com,Proxy +DOMAIN-SUFFIX,x365x.com,Proxy +DOMAIN-SUFFIX,xanga.com,Proxy +DOMAIN-SUFFIX,x-art.com,Proxy +DOMAIN-SUFFIX,xa.yimg.com,Proxy +DOMAIN-SUFFIX,xbabe.com,Proxy +DOMAIN-SUFFIX,x-berry.com,Proxy +DOMAIN-SUFFIX,xbookcn.com,Proxy +DOMAIN-SUFFIX,xcafe.in,Proxy +DOMAIN-SUFFIX,xcritic.com,Proxy +DOMAIN-SUFFIX,xfm.pp.ru,Proxy +DOMAIN-SUFFIX,xgmyd.com,Proxy +DOMAIN-SUFFIX,xh4n.cn,Proxy +DOMAIN-SUFFIX,xhamster.com,Proxy +DOMAIN-SUFFIX,xianqiao.net,Proxy +DOMAIN-SUFFIX,xiaochuncnjp.com,Proxy +DOMAIN-SUFFIX,xiaohexie.com,Proxy +DOMAIN-SUFFIX,xiaolan.me,Proxy +DOMAIN-SUFFIX,xiaoma.org,Proxy +DOMAIN-SUFFIX,xiezhua.com,Proxy +DOMAIN-SUFFIX,xing.com,Proxy +DOMAIN-SUFFIX,xinhuanet.org,Proxy +DOMAIN-SUFFIX,xinmiao.com.hk,Proxy +DOMAIN-SUFFIX,xinqimeng.over-blog.com,Proxy +DOMAIN-SUFFIX,xinsheng.net,Proxy +DOMAIN-SUFFIX,xinshijue.com,Proxy +DOMAIN-SUFFIX,xinyubbs.net,Proxy +DOMAIN-SUFFIX,xiongpian.com,Proxy +DOMAIN-SUFFIX,xizang-zhiye.org,Proxy +DOMAIN-SUFFIX,xjp.cc,Proxy +DOMAIN-SUFFIX,xlfmwz.info,Proxy +DOMAIN-SUFFIX,xml-training-guide.com,Proxy +DOMAIN-SUFFIX,xmovies.com,Proxy +DOMAIN-SUFFIX,xmusic.fm,Proxy +DOMAIN-SUFFIX,xnxx.com,Proxy +DOMAIN-SUFFIX,xpdo.net,Proxy +DOMAIN-SUFFIX,xpud.org,Proxy +DOMAIN-SUFFIX,xskywalker.com,Proxy +DOMAIN-SUFFIX,xtube.com,Proxy +DOMAIN-SUFFIX,xuchao.net,Proxy +DOMAIN-SUFFIX,xuchao.org,Proxy +DOMAIN-SUFFIX,xuzhiyong.net,Proxy +DOMAIN-SUFFIX,xuzhuoer.com,Proxy +DOMAIN-SUFFIX,xvedios.com,Proxy +DOMAIN-SUFFIX,xvideos.com,Proxy +DOMAIN-SUFFIX,x-wall.org,Proxy +DOMAIN-SUFFIX,xxbbx.com,Proxy +DOMAIN-SUFFIX,x.xcity.jp,Proxy +DOMAIN-SUFFIX,xxxx.com.au,Proxy +DOMAIN-SUFFIX,xysblogs.org,Proxy +DOMAIN-SUFFIX,xys.dxiong.com,Proxy +DOMAIN-SUFFIX,xys.org,Proxy +DOMAIN-SUFFIX,xyy69.com,Proxy +DOMAIN-SUFFIX,xyy69.info,Proxy +DOMAIN-SUFFIX,yahoo.com.hk,Proxy +DOMAIN-SUFFIX,yakbutterblues.com,Proxy +DOMAIN-SUFFIX,yam.com,Proxy +DOMAIN-SUFFIX,yangjianli.com,Proxy +DOMAIN-SUFFIX,yasni.co.uk,Proxy +DOMAIN-SUFFIX,yasukuni.or.jp,Proxy +DOMAIN-SUFFIX,ydy.com,Proxy +DOMAIN-SUFFIX,yeelou.com,Proxy +DOMAIN-SUFFIX,yeeyan.org,Proxy +DOMAIN-SUFFIX,yeeyi.com,Proxy +DOMAIN-SUFFIX,yegle.net,Proxy +DOMAIN-SUFFIX,yes123.com.tw,Proxy +DOMAIN-SUFFIX,yesasia.com,Proxy +DOMAIN-SUFFIX,yesasia.com.hk,Proxy +DOMAIN-SUFFIX,yfrog.com,Proxy +DOMAIN-SUFFIX,yhcw.net,Proxy +DOMAIN-SUFFIX,yibada.com,Proxy +DOMAIN-SUFFIX,yibaochina.com,Proxy +DOMAIN-SUFFIX,yidio.com,Proxy +DOMAIN-SUFFIX,yilubbs.com,Proxy +DOMAIN-SUFFIX,yi.org,Proxy +DOMAIN-SUFFIX,yipub.com,Proxy +DOMAIN-SUFFIX,yogichen.org,Proxy +DOMAIN-SUFFIX,yong.hu,Proxy +DOMAIN-SUFFIX,yorkbbs.ca,Proxy +DOMAIN-SUFFIX,youjizz.com,Proxy +DOMAIN-SUFFIX,youmaker.com,Proxy +DOMAIN-SUFFIX,youpai.org,Proxy +DOMAIN-SUFFIX,youporn.com,Proxy +DOMAIN-SUFFIX,youporngay.com,Proxy +DOMAIN-SUFFIX,yourepeat.com,Proxy +DOMAIN-SUFFIX,your-freedom.net,Proxy +DOMAIN-SUFFIX,yousendit.com,Proxy +DOMAIN-SUFFIX,youthbao.com,Proxy +DOMAIN-SUFFIX,youthnetradio.org,Proxy +DOMAIN-SUFFIX,youtu.be,Proxy +DOMAIN-SUFFIX,youtubecn.com,Proxy +DOMAIN-SUFFIX,youtube.com,Proxy +DOMAIN-SUFFIX,youtube-nocookie.com,Proxy +DOMAIN-SUFFIX,youversion.com,Proxy +DOMAIN-SUFFIX,youxu.info,Proxy +DOMAIN-SUFFIX,ytht.net,Proxy +DOMAIN-SUFFIX,ytimg.com,Proxy +DOMAIN-SUFFIX,yuanming.net,Proxy +DOMAIN-SUFFIX,yuming.flnet.org,Proxy +DOMAIN-SUFFIX,yunchao.net,Proxy +DOMAIN-SUFFIX,yvesgeleyn.com,Proxy +DOMAIN-SUFFIX,yx51.net,Proxy +DOMAIN-SUFFIX,yyets.com,Proxy +DOMAIN-SUFFIX,yyii.org,Proxy +DOMAIN-SUFFIX,yymaya.com,Proxy +DOMAIN-SUFFIX,yzzk.com,Proxy +DOMAIN-SUFFIX,zacebook.com,Proxy +DOMAIN-SUFFIX,zannel.com,Proxy +DOMAIN-SUFFIX,zaobao.com,Proxy +DOMAIN-SUFFIX,zaobao.com.sg,Proxy +DOMAIN-SUFFIX,zaozon.com,Proxy +DOMAIN-SUFFIX,zarias.com,Proxy +DOMAIN-SUFFIX,zattoo.com,Proxy +DOMAIN-SUFFIX,zaurus.org.uk,Proxy +DOMAIN-SUFFIX,zdassets.com,Proxy +DOMAIN-SUFFIX,zdnet.com.tw,Proxy +DOMAIN-SUFFIX,zengjinyan.org,Proxy +DOMAIN-SUFFIX,zensur.freerk.com,Proxy +DOMAIN-SUFFIX,zeutch.com,Proxy +DOMAIN-SUFFIX,zfreet.com,Proxy +DOMAIN-SUFFIX,zgzcjj.net,Proxy +DOMAIN-SUFFIX,zhanbin.net,Proxy +DOMAIN-SUFFIX,zhangboli.net,Proxy +DOMAIN-SUFFIX,zhangtianliang.com,Proxy +DOMAIN-SUFFIX,zhao.jinhai.de,Proxy +DOMAIN-SUFFIX,zhenghui.org,Proxy +DOMAIN-SUFFIX,zhengwunet.org,Proxy +DOMAIN-SUFFIX,zhenlibu.info,Proxy +DOMAIN-SUFFIX,zhenxiang.biz,Proxy +DOMAIN-SUFFIX,zhinengluyou.com,Proxy +DOMAIN-SUFFIX,zh.m.wikipedia.org,Proxy +DOMAIN-SUFFIX,zh.netlog.com,Proxy +DOMAIN-SUFFIX,zhongguorenquan.org,Proxy +DOMAIN-SUFFIX,zhongguotese.net,Proxy +DOMAIN-SUFFIX,zhongmeng.org,Proxy +DOMAIN-SUFFIX,zh.pokerstrategy.com,Proxy +DOMAIN-SUFFIX,zhreader.com,Proxy +DOMAIN-SUFFIX,zh-tw.justin.tv,Proxy +DOMAIN-SUFFIX,zhufeng.me,Proxy +DOMAIN-SUFFIX,zhuichaguoji.org,Proxy +DOMAIN-SUFFIX,zh.uncyclopedia.wikia.com,Proxy +DOMAIN-SUFFIX,zh.wikibooks.org,Proxy +DOMAIN-SUFFIX,zh.wikinews.org,Proxy +DOMAIN-SUFFIX,zh.wikipedia.org,Proxy +DOMAIN-SUFFIX,zh.wikisource.org,Proxy +DOMAIN-SUFFIX,zh-yue.wikipedia.org,Proxy +DOMAIN-SUFFIX,ziddu.com,Proxy +DOMAIN-SUFFIX,zillionk.com,Proxy +DOMAIN-SUFFIX,zinio.com,Proxy +DOMAIN-SUFFIX,ziplib.com,Proxy +DOMAIN-SUFFIX,zkaip.com,Proxy +DOMAIN-SUFFIX,zlib.net,Proxy +DOMAIN-SUFFIX,zmw.cn,Proxy +DOMAIN-SUFFIX,zomobo.net,Proxy +DOMAIN-SUFFIX,zonaeuropa.com,Proxy +DOMAIN-SUFFIX,zootool.com,Proxy +DOMAIN-SUFFIX,zoozle.net,Proxy +DOMAIN-SUFFIX,zozotown.com,Proxy +DOMAIN-SUFFIX,zshare.net,Proxy +DOMAIN-SUFFIX,zsrhao.com,Proxy +DOMAIN-SUFFIX,zuobiao.me,Proxy +DOMAIN-SUFFIX,zuo.la,Proxy +DOMAIN-SUFFIX,zuola.com,Proxy +DOMAIN-SUFFIX,zvereff.com,Proxy +DOMAIN-SUFFIX,zyzc9.com,Proxy + +// Telegram +IP-CIDR,91.108.56.0/22,Proxy,no-resolve +IP-CIDR,91.108.4.0/22,Proxy,no-resolve +IP-CIDR,109.239.140.0/24,Proxy,no-resolve +IP-CIDR,149.154.160.0/20,Proxy,no-resolve + +// LAN +IP-CIDR,192.168.0.0/16,DIRECT +IP-CIDR,10.0.0.0/8,DIRECT +IP-CIDR,172.16.0.0/12,DIRECT +IP-CIDR,127.0.0.0/8,DIRECT + +GEOIP,CN,DIRECT +FINAL,Proxy diff --git a/Surf-Mac/zh-Hans.lproj/InfoPlist.strings b/Surf-Mac/zh-Hans.lproj/InfoPlist.strings new file mode 100644 index 0000000..8202f43 --- /dev/null +++ b/Surf-Mac/zh-Hans.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* + InfoPlist.strings + Surf + + Created by 孔祥波 on 16/12/2016. + Copyright © 2016 abigt. All rights reserved. +*/ +"CFBundleDisplayName" = "A.BIG.T"; +"CFBundleName" = "A.BIG.T"; diff --git a/Surf-Mac/zh-Hans.lproj/Main.strings b/Surf-Mac/zh-Hans.lproj/Main.strings new file mode 100644 index 0000000..18fabad --- /dev/null +++ b/Surf-Mac/zh-Hans.lproj/Main.strings @@ -0,0 +1,405 @@ + +/* Class = "NSMenuItem"; title = "Customize Toolbar…"; ObjectID = "1UK-8n-QPP"; */ +"1UK-8n-QPP.title" = "Customize Toolbar…"; + +/* Class = "NSMenuItem"; title = "Surf-Mac"; ObjectID = "1Xt-HY-uBw"; */ +"1Xt-HY-uBw.title" = "Surf-Mac"; + +/* Class = "NSMenu"; title = "Find"; ObjectID = "1b7-l0-nxx"; */ +"1b7-l0-nxx.title" = "Find"; + +/* Class = "NSMenuItem"; title = "Lower"; ObjectID = "1tx-W0-xDw"; */ +"1tx-W0-xDw.title" = "Lower"; + +/* Class = "NSMenuItem"; title = "Raise"; ObjectID = "2h7-ER-AoG"; */ +"2h7-ER-AoG.title" = "Raise"; + +/* Class = "NSMenuItem"; title = "Transformations"; ObjectID = "2oI-Rn-ZJC"; */ +"2oI-Rn-ZJC.title" = "Transformations"; + +/* Class = "NSMenu"; title = "Spelling"; ObjectID = "3IN-sU-3Bg"; */ +"3IN-sU-3Bg.title" = "Spelling"; + +/* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "3Om-Ey-2VK"; */ +"3Om-Ey-2VK.title" = "Use Default"; + +/* Class = "NSMenu"; title = "Speech"; ObjectID = "3rS-ZA-NoH"; */ +"3rS-ZA-NoH.title" = "Speech"; + +/* Class = "NSMenuItem"; title = "Tighten"; ObjectID = "46P-cB-AYj"; */ +"46P-cB-AYj.title" = "Tighten"; + +/* Class = "NSMenuItem"; title = "Find"; ObjectID = "4EN-yA-p0u"; */ +"4EN-yA-p0u.title" = "Find"; + +/* Class = "NSMenuItem"; title = "Quit Surf-Mac"; ObjectID = "4sb-4s-VLi"; */ +"4sb-4s-VLi.title" = "Quit Surf-Mac"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "5QF-Oa-p0T"; */ +"5QF-Oa-p0T.title" = "Edit"; + +/* Class = "NSMenuItem"; title = "Copy Style"; ObjectID = "5Vv-lz-BsD"; */ +"5Vv-lz-BsD.title" = "Copy Style"; + +/* Class = "NSMenuItem"; title = "About Surf-Mac"; ObjectID = "5kV-Vb-QxS"; */ +"5kV-Vb-QxS.title" = "About Surf-Mac"; + +/* Class = "NSMenuItem"; title = "Redo"; ObjectID = "6dh-zS-Vam"; */ +"6dh-zS-Vam.title" = "Redo"; + +/* Class = "NSMenuItem"; title = "Correct Spelling Automatically"; ObjectID = "78Y-hA-62v"; */ +"78Y-hA-62v.title" = "Correct Spelling Automatically"; + +/* Class = "NSMenu"; title = "Writing Direction"; ObjectID = "8mr-sm-Yjd"; */ +"8mr-sm-Yjd.title" = "Writing Direction"; + +/* Class = "NSButtonCell"; title = "Connect"; ObjectID = "9e0-uv-m2H"; */ +"9e0-uv-m2H.title" = "Connect"; + +/* Class = "NSMenuItem"; title = "Substitutions"; ObjectID = "9ic-FL-obx"; */ +"9ic-FL-obx.title" = "Substitutions"; + +/* Class = "NSMenuItem"; title = "Smart Copy/Paste"; ObjectID = "9yt-4B-nSM"; */ +"9yt-4B-nSM.title" = "Smart Copy/Paste"; + +/* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */ +"AYu-sK-qS6.title" = "Main Menu"; + +/* Class = "NSMenuItem"; title = "Preferences…"; ObjectID = "BOF-NM-1cW"; */ +"BOF-NM-1cW.title" = "Preferences…"; + +/* Class = "NSMenuItem"; title = "\tLeft to Right"; ObjectID = "BgM-ve-c93"; */ +"BgM-ve-c93.title" = "\tLeft to Right"; + +/* Class = "NSMenuItem"; title = "Save As…"; ObjectID = "Bw7-FT-i3A"; */ +"Bw7-FT-i3A.title" = "Save As…"; + +/* Class = "NSMenuItem"; title = "Close"; ObjectID = "DVo-aG-piG"; */ +"DVo-aG-piG.title" = "Close"; + +/* Class = "NSMenuItem"; title = "Spelling and Grammar"; ObjectID = "Dv1-io-Yv7"; */ +"Dv1-io-Yv7.title" = "Spelling and Grammar"; + +/* Class = "NSMenu"; title = "Help"; ObjectID = "F2S-fz-NVQ"; */ +"F2S-fz-NVQ.title" = "Help"; + +/* Class = "NSMenuItem"; title = "Surf-Mac Help"; ObjectID = "FKE-Sm-Kum"; */ +"FKE-Sm-Kum.title" = "Surf-Mac Help"; + +/* Class = "NSMenuItem"; title = "Text"; ObjectID = "Fal-I4-PZk"; */ +"Fal-I4-PZk.title" = "Text"; + +/* Class = "NSMenu"; title = "Substitutions"; ObjectID = "FeM-D8-WVr"; */ +"FeM-D8-WVr.title" = "Substitutions"; + +/* Class = "NSMenuItem"; title = "Bold"; ObjectID = "GB9-OM-e27"; */ +"GB9-OM-e27.title" = "Bold"; + +/* Class = "NSMenu"; title = "Format"; ObjectID = "GEO-Iw-cKr"; */ +"GEO-Iw-cKr.title" = "Format"; + +/* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "GUa-eO-cwY"; */ +"GUa-eO-cwY.title" = "Use Default"; + +/* Class = "NSMenuItem"; title = "Font"; ObjectID = "Gi5-1S-RQB"; */ +"Gi5-1S-RQB.title" = "Font"; + +/* Class = "NSMenuItem"; title = "Writing Direction"; ObjectID = "H1b-Si-o9J"; */ +"H1b-Si-o9J.title" = "Writing Direction"; + +/* Class = "NSMenuItem"; title = "View"; ObjectID = "H8h-7b-M4v"; */ +"H8h-7b-M4v.title" = "View"; + +/* Class = "NSMenuItem"; title = "Text Replacement"; ObjectID = "HFQ-gK-NFA"; */ +"HFQ-gK-NFA.title" = "Text Replacement"; + +/* Class = "NSMenuItem"; title = "Show Spelling and Grammar"; ObjectID = "HFo-cy-zxI"; */ +"HFo-cy-zxI.title" = "Show Spelling and Grammar"; + +/* Class = "NSMenu"; title = "View"; ObjectID = "HyV-fh-RgO"; */ +"HyV-fh-RgO.title" = "View"; + +/* Class = "NSMenuItem"; title = "Subscript"; ObjectID = "I0S-gh-46l"; */ +"I0S-gh-46l.title" = "Subscript"; + +/* Class = "NSMenuItem"; title = "Open…"; ObjectID = "IAo-SY-fd9"; */ +"IAo-SY-fd9.title" = "Open…"; + +/* Class = "NSWindow"; title = "Window"; ObjectID = "IQv-IB-iLA"; */ +"IQv-IB-iLA.title" = "Window"; + +/* Class = "NSMenuItem"; title = "Justify"; ObjectID = "J5U-5w-g23"; */ +"J5U-5w-g23.title" = "Justify"; + +/* Class = "NSMenuItem"; title = "Use None"; ObjectID = "J7y-lM-qPV"; */ +"J7y-lM-qPV.title" = "Use None"; + +/* Class = "NSMenuItem"; title = "Revert to Saved"; ObjectID = "KaW-ft-85H"; */ +"KaW-ft-85H.title" = "Revert to Saved"; + +/* Class = "NSMenuItem"; title = "Show All"; ObjectID = "Kd2-mp-pUS"; */ +"Kd2-mp-pUS.title" = "Show All"; + +/* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "LE2-aR-0XJ"; */ +"LE2-aR-0XJ.title" = "Bring All to Front"; + +/* Class = "NSMenuItem"; title = "Paste Ruler"; ObjectID = "LVM-kO-fVI"; */ +"LVM-kO-fVI.title" = "Paste Ruler"; + +/* Class = "NSMenuItem"; title = "\tLeft to Right"; ObjectID = "Lbh-J2-qVU"; */ +"Lbh-J2-qVU.title" = "\tLeft to Right"; + +/* Class = "NSMenuItem"; title = "Copy Ruler"; ObjectID = "MkV-Pr-PK5"; */ +"MkV-Pr-PK5.title" = "Copy Ruler"; + +/* Class = "NSMenuItem"; title = "Services"; ObjectID = "NMo-om-nkz"; */ +"NMo-om-nkz.title" = "Services"; + +/* Class = "NSMenuItem"; title = "\tDefault"; ObjectID = "Nop-cj-93Q"; */ +"Nop-cj-93Q.title" = "\tDefault"; + +/* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "OY7-WF-poV"; */ +"OY7-WF-poV.title" = "Minimize"; + +/* Class = "NSMenuItem"; title = "Baseline"; ObjectID = "OaQ-X3-Vso"; */ +"OaQ-X3-Vso.title" = "Baseline"; + +/* Class = "NSMenuItem"; title = "Hide Surf-Mac"; ObjectID = "Olw-nP-bQN"; */ +"Olw-nP-bQN.title" = "Hide Surf-Mac"; + +/* Class = "NSMenuItem"; title = "Find Previous"; ObjectID = "OwM-mh-QMV"; */ +"OwM-mh-QMV.title" = "Find Previous"; + +/* Class = "NSMenuItem"; title = "Stop Speaking"; ObjectID = "Oyz-dy-DGm"; */ +"Oyz-dy-DGm.title" = "Stop Speaking"; + +/* Class = "NSMenuItem"; title = "Bigger"; ObjectID = "Ptp-SP-VEL"; */ +"Ptp-SP-VEL.title" = "Bigger"; + +/* Class = "NSMenuItem"; title = "Show Fonts"; ObjectID = "Q5e-8K-NDq"; */ +"Q5e-8K-NDq.title" = "Show Fonts"; + +/* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "R4o-n2-Eq4"; */ +"R4o-n2-Eq4.title" = "Zoom"; + +/* Class = "NSMenuItem"; title = "\tRight to Left"; ObjectID = "RB4-Sm-HuC"; */ +"RB4-Sm-HuC.title" = "\tRight to Left"; + +/* Class = "NSMenuItem"; title = "Superscript"; ObjectID = "Rqc-34-cIF"; */ +"Rqc-34-cIF.title" = "Superscript"; + +/* Class = "NSMenuItem"; title = "Select All"; ObjectID = "Ruw-6m-B2m"; */ +"Ruw-6m-B2m.title" = "Select All"; + +/* Class = "NSMenuItem"; title = "Jump to Selection"; ObjectID = "S0p-oC-mLd"; */ +"S0p-oC-mLd.title" = "Jump to Selection"; + +/* Class = "NSMenu"; title = "Window"; ObjectID = "Td7-aD-5lo"; */ +"Td7-aD-5lo.title" = "Window"; + +/* Class = "NSMenuItem"; title = "Capitalize"; ObjectID = "UEZ-Bs-lqG"; */ +"UEZ-Bs-lqG.title" = "Capitalize"; + +/* Class = "NSButtonCell"; title = "app dir"; ObjectID = "UtX-t5-mGG"; */ +"UtX-t5-mGG.title" = "app dir"; + +/* Class = "NSMenuItem"; title = "Center"; ObjectID = "VIY-Ag-zcb"; */ +"VIY-Ag-zcb.title" = "Center"; + +/* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "Vdr-fp-XzO"; */ +"Vdr-fp-XzO.title" = "Hide Others"; + +/* Class = "NSMenuItem"; title = "Italic"; ObjectID = "Vjx-xi-njq"; */ +"Vjx-xi-njq.title" = "Italic"; + +/* Class = "NSMenu"; title = "Edit"; ObjectID = "W48-6f-4Dl"; */ +"W48-6f-4Dl.title" = "Edit"; + +/* Class = "NSButtonCell"; title = "save"; ObjectID = "WO2-a0-LWD"; */ +"WO2-a0-LWD.title" = "save"; + +/* Class = "NSMenuItem"; title = "Underline"; ObjectID = "WRG-CD-K1S"; */ +"WRG-CD-K1S.title" = "Underline"; + +/* Class = "NSMenuItem"; title = "New"; ObjectID = "Was-JA-tGl"; */ +"Was-JA-tGl.title" = "New"; + +/* Class = "NSMenuItem"; title = "Paste and Match Style"; ObjectID = "WeT-3V-zwk"; */ +"WeT-3V-zwk.title" = "Paste and Match Style"; + +/* Class = "NSMenuItem"; title = "Find…"; ObjectID = "Xz5-n4-O0W"; */ +"Xz5-n4-O0W.title" = "Find…"; + +/* Class = "NSMenuItem"; title = "Find and Replace…"; ObjectID = "YEy-JH-Tfz"; */ +"YEy-JH-Tfz.title" = "Find and Replace…"; + +/* Class = "NSMenuItem"; title = "\tDefault"; ObjectID = "YGs-j5-SAR"; */ +"YGs-j5-SAR.title" = "\tDefault"; + +/* Class = "NSMenuItem"; title = "Start Speaking"; ObjectID = "Ynk-f8-cLZ"; */ +"Ynk-f8-cLZ.title" = "Start Speaking"; + +/* Class = "NSMenuItem"; title = "Align Left"; ObjectID = "ZM1-6Q-yy1"; */ +"ZM1-6Q-yy1.title" = "Align Left"; + +/* Class = "NSButtonCell"; title = "show log dir"; ObjectID = "ZVw-Aq-heF"; */ +"ZVw-Aq-heF.title" = "show log dir"; + +/* Class = "NSMenuItem"; title = "Paragraph"; ObjectID = "ZvO-Gk-QUH"; */ +"ZvO-Gk-QUH.title" = "Paragraph"; + +/* Class = "NSMenuItem"; title = "Print…"; ObjectID = "aTl-1u-JFS"; */ +"aTl-1u-JFS.title" = "Print…"; + +/* Class = "NSMenuItem"; title = "Window"; ObjectID = "aUF-d1-5bR"; */ +"aUF-d1-5bR.title" = "Window"; + +/* Class = "NSMenu"; title = "Font"; ObjectID = "aXa-aM-Jaq"; */ +"aXa-aM-Jaq.title" = "Font"; + +/* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "agt-UL-0e3"; */ +"agt-UL-0e3.title" = "Use Default"; + +/* Class = "NSMenuItem"; title = "Show Colors"; ObjectID = "bgn-CT-cEk"; */ +"bgn-CT-cEk.title" = "Show Colors"; + +/* Class = "NSMenu"; title = "File"; ObjectID = "bib-Uj-vzu"; */ +"bib-Uj-vzu.title" = "File"; + +/* Class = "NSMenuItem"; title = "Use Selection for Find"; ObjectID = "buJ-ug-pKt"; */ +"buJ-ug-pKt.title" = "Use Selection for Find"; + +/* Class = "NSMenu"; title = "Transformations"; ObjectID = "c8a-y6-VQd"; */ +"c8a-y6-VQd.title" = "Transformations"; + +/* Class = "NSMenuItem"; title = "Use None"; ObjectID = "cDB-IK-hbR"; */ +"cDB-IK-hbR.title" = "Use None"; + +/* Class = "NSMenuItem"; title = "Selection"; ObjectID = "cqv-fj-IhA"; */ +"cqv-fj-IhA.title" = "Selection"; + +/* Class = "NSMenuItem"; title = "Smart Links"; ObjectID = "cwL-P1-jid"; */ +"cwL-P1-jid.title" = "Smart Links"; + +/* Class = "NSMenuItem"; title = "Make Lower Case"; ObjectID = "d9M-CD-aMd"; */ +"d9M-CD-aMd.title" = "Make Lower Case"; + +/* Class = "NSMenu"; title = "Text"; ObjectID = "d9c-me-L2H"; */ +"d9c-me-L2H.title" = "Text"; + +/* Class = "NSMenuItem"; title = "File"; ObjectID = "dMs-cI-mzQ"; */ +"dMs-cI-mzQ.title" = "File"; + +/* Class = "NSMenuItem"; title = "Undo"; ObjectID = "dRJ-4n-Yzg"; */ +"dRJ-4n-Yzg.title" = "Undo"; + +/* Class = "NSMenuItem"; title = "Paste"; ObjectID = "gVA-U4-sdL"; */ +"gVA-U4-sdL.title" = "Paste"; + +/* Class = "NSMenuItem"; title = "Smart Quotes"; ObjectID = "hQb-2v-fYv"; */ +"hQb-2v-fYv.title" = "Smart Quotes"; + +/* Class = "NSMenuItem"; title = "Check Document Now"; ObjectID = "hz2-CU-CR7"; */ +"hz2-CU-CR7.title" = "Check Document Now"; + +/* Class = "NSMenu"; title = "Services"; ObjectID = "hz9-B4-Xy5"; */ +"hz9-B4-Xy5.title" = "Services"; + +/* Class = "NSMenuItem"; title = "Smaller"; ObjectID = "i1d-Er-qST"; */ +"i1d-Er-qST.title" = "Smaller"; + +/* Class = "NSMenu"; title = "Baseline"; ObjectID = "ijk-EB-dga"; */ +"ijk-EB-dga.title" = "Baseline"; + +/* Class = "NSMenuItem"; title = "Kern"; ObjectID = "jBQ-r6-VK2"; */ +"jBQ-r6-VK2.title" = "Kern"; + +/* Class = "NSMenuItem"; title = "\tRight to Left"; ObjectID = "jFq-tB-4Kx"; */ +"jFq-tB-4Kx.title" = "\tRight to Left"; + +/* Class = "NSMenuItem"; title = "Format"; ObjectID = "jxT-CU-nIS"; */ +"jxT-CU-nIS.title" = "Format"; + +/* Class = "NSMenuItem"; title = "Check Grammar With Spelling"; ObjectID = "mK6-2p-4JG"; */ +"mK6-2p-4JG.title" = "Check Grammar With Spelling"; + +/* Class = "NSMenuItem"; title = "Ligatures"; ObjectID = "o6e-r0-MWq"; */ +"o6e-r0-MWq.title" = "Ligatures"; + +/* Class = "NSMenu"; title = "Open Recent"; ObjectID = "oas-Oc-fiZ"; */ +"oas-Oc-fiZ.title" = "Open Recent"; + +/* Class = "NSMenuItem"; title = "Loosen"; ObjectID = "ogc-rX-tC1"; */ +"ogc-rX-tC1.title" = "Loosen"; + +/* Class = "NSButtonCell"; title = "terminal"; ObjectID = "pEm-gS-cVl"; */ +"pEm-gS-cVl.title" = "terminal"; + +/* Class = "NSMenuItem"; title = "Delete"; ObjectID = "pa3-QI-u2k"; */ +"pa3-QI-u2k.title" = "Delete"; + +/* Class = "NSMenuItem"; title = "Save…"; ObjectID = "pxx-59-PXV"; */ +"pxx-59-PXV.title" = "Save…"; + +/* Class = "NSMenuItem"; title = "Find Next"; ObjectID = "q09-fT-Sye"; */ +"q09-fT-Sye.title" = "Find Next"; + +/* Class = "NSMenuItem"; title = "Page Setup…"; ObjectID = "qIS-W8-SiK"; */ +"qIS-W8-SiK.title" = "Page Setup…"; + +/* Class = "NSMenuItem"; title = "Check Spelling While Typing"; ObjectID = "rbD-Rh-wIN"; */ +"rbD-Rh-wIN.title" = "Check Spelling While Typing"; + +/* Class = "NSMenuItem"; title = "Smart Dashes"; ObjectID = "rgM-f4-ycn"; */ +"rgM-f4-ycn.title" = "Smart Dashes"; + +/* Class = "NSMenuItem"; title = "Show Toolbar"; ObjectID = "snW-S8-Cw5"; */ +"snW-S8-Cw5.title" = "Show Toolbar"; + +/* Class = "NSMenuItem"; title = "Data Detectors"; ObjectID = "tRr-pd-1PS"; */ +"tRr-pd-1PS.title" = "Data Detectors"; + +/* Class = "NSMenuItem"; title = "Open Recent"; ObjectID = "tXI-mr-wws"; */ +"tXI-mr-wws.title" = "Open Recent"; + +/* Class = "NSMenu"; title = "Kern"; ObjectID = "tlD-Oa-oAM"; */ +"tlD-Oa-oAM.title" = "Kern"; + +/* Class = "NSMenu"; title = "Surf-Mac"; ObjectID = "uQy-DD-JDr"; */ +"uQy-DD-JDr.title" = "Surf-Mac"; + +/* Class = "NSMenuItem"; title = "Cut"; ObjectID = "uRl-iY-unG"; */ +"uRl-iY-unG.title" = "Cut"; + +/* Class = "NSMenuItem"; title = "Paste Style"; ObjectID = "vKC-jM-MkH"; */ +"vKC-jM-MkH.title" = "Paste Style"; + +/* Class = "NSMenuItem"; title = "Show Ruler"; ObjectID = "vLm-3I-IUL"; */ +"vLm-3I-IUL.title" = "Show Ruler"; + +/* Class = "NSMenuItem"; title = "Clear Menu"; ObjectID = "vNY-rz-j42"; */ +"vNY-rz-j42.title" = "Clear Menu"; + +/* Class = "NSMenuItem"; title = "Make Upper Case"; ObjectID = "vmV-6d-7jI"; */ +"vmV-6d-7jI.title" = "Make Upper Case"; + +/* Class = "NSMenu"; title = "Ligatures"; ObjectID = "w0m-vy-SC9"; */ +"w0m-vy-SC9.title" = "Ligatures"; + +/* Class = "NSMenuItem"; title = "Align Right"; ObjectID = "wb2-vD-lq4"; */ +"wb2-vD-lq4.title" = "Align Right"; + +/* Class = "NSMenuItem"; title = "Help"; ObjectID = "wpr-3q-Mcd"; */ +"wpr-3q-Mcd.title" = "Help"; + +/* Class = "NSMenuItem"; title = "Copy"; ObjectID = "x3v-GG-iWU"; */ +"x3v-GG-iWU.title" = "Copy"; + +/* Class = "NSMenuItem"; title = "Use All"; ObjectID = "xQD-1f-W4t"; */ +"xQD-1f-W4t.title" = "Use All"; + +/* Class = "NSMenuItem"; title = "Speech"; ObjectID = "xrE-MZ-jX0"; */ +"xrE-MZ-jX0.title" = "Speech"; + +/* Class = "NSMenuItem"; title = "Show Substitutions"; ObjectID = "z6F-FW-3nz"; */ +"z6F-FW-3nz.title" = "Show Substitutions"; diff --git a/Surf-Today/Base.lproj/TodayViewController.xib b/Surf-Today/Base.lproj/TodayViewController.xib new file mode 100644 index 0000000..c822860 --- /dev/null +++ b/Surf-Today/Base.lproj/TodayViewController.xib @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Today/Info.plist b/Surf-Today/Info.plist new file mode 100644 index 0000000..a915772 --- /dev/null +++ b/Surf-Today/Info.plist @@ -0,0 +1,46 @@ + + + + + ATSApplicationFontsPath + SFMono-Regular.otf + CFBundleDevelopmentRegion + en + CFBundleDisplayName + Surfing + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 2.0.2 + CFBundleVersion + 100 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSExtension + + NSExtensionAttributes + + NSExtensionPointVersion + 2.0 + + NSExtensionMainNibFile + TodayViewController + NSExtensionPointIdentifier + com.apple.widget-extension + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).TodayViewController + com.apple.notificationcenter.widget.description + A.BIG.T-Today + + NSHumanReadableCopyright + Copyright © 2016年 abigt. All rights reserved. + + diff --git a/Surf-Today/RequestsWindowController.swift b/Surf-Today/RequestsWindowController.swift new file mode 100644 index 0000000..4c09eeb --- /dev/null +++ b/Surf-Today/RequestsWindowController.swift @@ -0,0 +1,283 @@ +// +// RequestsWindowController.swift +// Surf +// +// Created by 孔祥波 on 24/11/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa +import SwiftyJSON +import NetworkExtension +import SFSocket +import XProxy +class RequestsWindowController: NSWindowController,NSTableViewDelegate,NSTableViewDataSource{ + public var results:[SFRequestInfo] = [] + public var dbURL:URL? + @IBOutlet public weak var tableView:NSTableView! + //var vc:RequestsVC! + override func windowDidLoad() { + super.windowDidLoad() + //dbURL = RequestHelper.shared.openForApp() + //recent() + Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(RequestsWindowController.refreshRequest(_:)), userInfo: nil, repeats: true) + // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. +// let st = NSStoryboard.init(name: NSStoryboard.Name(rawValue: "RequestBasic"), bundle: nil) +// let vc = st.instantiateInitialController() as! RequestsVC +// self.window?.contentView = vc.view + } + @objc func refreshRequest(_ t:Timer){ + + // Send a simple IPC message to the provider, handle the response. + //AxLogger.log("send Hello Provider") + var rpc = false + if let m = SFVPNManager.shared.manager { + let date = NSDate() + let me = SFVPNXPSCommand.RECNETREQ.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8), m.connection.status == .connected + { + do { + rpc = true + try session.sendProviderMessage(message) {[weak self] response in + guard let s = self else {return} + if response != nil { + //let responseString = NSString(data: response!, encoding: NSUTF8StringEncoding) + //mylog("Received response from the provider: \(responseString)") + s.processData(data: response!) + //self.registerStatus() + } else { + //s.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + //alertMessageAction("Failed to send a message to the provider",complete: nil) + } + } + } + + } + public func processData(data:Data) { + let oldresults = results + results.removeAll() + + let obj = try! JSON.init(data: data) + if obj.error == nil { + + let count = obj["count"] + + if count.intValue != 0 { + + let result = obj["data"] + if result.type == .array { + for item in result { + + let json = item.1 + let r = SFRequestInfo.init(rID: 0) + r.map(json) + let rr = oldresults.filter({ info -> Bool in + if info.reqID == r.reqID && info.subID == r.subID { + return true + } + return false + }) + + if rr.isEmpty { + results.append(r) + r.speedtraffice = r.traffice + }else { + let old = rr.first! + if r.traffice.rx > old.traffice.rx { + //sub id reset + r.speedtraffice.rx = r.traffice.rx - old.traffice.rx + } + + if r.traffice.tx > old.traffice.tx{ + //? + r.speedtraffice.tx = r.traffice.tx - old.traffice.tx + } + + + results.append(r) + } + + } + } + if results.count > 0 { + results.sort(by: { $0.reqID < $1.reqID }) + + } + + } + + + } + + tableView.reloadData() + + } + public func numberOfRows(in tableView: NSTableView) -> Int { + return results.count + } + public func tableView(_ tableView: NSTableView + , objectValueFor tableColumn: NSTableColumn? + , row: Int) -> Any? { + let result = results[row] + if (tableColumn?.identifier)!.rawValue == "Icon" { + switch result.rule.policy{ + case .Direct: + return NSImage(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + case .Proxy: + return NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + case .Reject: + return NSImage(named:NSImage.Name(rawValue: "NSStatusUnavailable")) + default: + break + } + } + return nil + } + public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + + let iden = tableColumn!.identifier.rawValue + let result = results[row] + + let cell:NSTableCellView = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as! NSTableCellView + if iden == "Index" { + cell.textField?.stringValue = "\(result.reqID) \(result.subID)" + + + }else if iden == "App" { + + cell.textField?.attributedStringValue = result.detailString() + }else if iden == "Url" { + if result.mode == .HTTP { + if let u = URL(string: result.url){ + if let h = u.host { + cell.textField?.stringValue = h + }else { + cell.textField?.stringValue = u.description + } + + }else { + if let req = result.reqHeader{ + cell.textField?.stringValue = req.Host + } + } + + }else { + cell.textField?.stringValue = result.url + } + + }else if iden == "Rule" { + + }else if iden == "Date" { + + cell.textField?.stringValue = result.dataDesc(result.sTime) + }else if iden == "Status" { + + let n = Date() + let a = result.activeTime + let idle = n.timeIntervalSince(a) + if idle > 1 { + cell.textField?.stringValue = "idle \(Int(idle))" + }else { + cell.textField?.stringValue = result.status.description + } + + }else if iden == "Policy" { + let rule = result.rule + cell.textField?.stringValue = rule.policy.description + " (" + rule.type.description + ":" + rule.name + ")" + //(\(rule.type.description):\(rule.name) ProxyName:\(rule.proxyName))" + //cell.textField?.stringValue = "Demo"//result.status.description + }else if iden == "Up" { + let tx = result.speedtraffice.tx + cell.textField?.stringValue = self.toString(x: tx,label:"",speed: true) + }else if iden == "Down" { + let rx = result.speedtraffice.rx + cell.textField?.stringValue = self.toString(x: rx,label:"",speed: true) + + }else if iden == "Method" { + if result.mode == .TCP{ + cell.textField?.stringValue = "TCP" + }else { + if let req = result.reqHeader { + if req.method == .CONNECT { + cell.textField?.stringValue = "HTTPS" + }else { + cell.textField?.stringValue = req.method.rawValue + } + + } + } + + }else if iden == "Icon" { + switch result.rule.policy{ + case .Direct: + cell.imageView?.objectValue = NSImage(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + case .Proxy: + cell.imageView?.objectValue = NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + case .Reject: + cell.imageView?.objectValue = NSImage(named:NSImage.Name(rawValue: "NSStatusUnavailable")) + default: + break + } + }else if iden == "DNS" { + + if !result.rule.ipAddress.isEmpty { + cell.textField?.stringValue = result.rule.ipAddress + }else { + if !result.remoteIPaddress.isEmpty{ + let x = result.remoteIPaddress.components(separatedBy: " ") + if x.count > 1 { + cell.textField?.stringValue = x.last! + }else { + cell.textField?.stringValue = x.first! + } + + }else { + if !result.rule.name.isEmpty { + cell.textField?.stringValue = result.rule.name + }else { + let x = "NONE" + let s = NSMutableAttributedString(string:x ) + let r = NSMakeRange(0, 4); + s.addAttributes([NSAttributedStringKey.foregroundColor:NSColor.red,NSAttributedStringKey.backgroundColor:NSColor.white], range: r) + cell.textField?.attributedStringValue = s + } + + } + + } + + + } + if row % 2 == 0 { + cell.backgroundStyle = .dark + }else { + cell.backgroundStyle = .light + } + return cell + } + public func toString(x:UInt,label:String,speed:Bool) ->String { + + var s = "/s" + if !speed { + s = "" + } + + if x < 1024{ + return label + " \(x) B" + s + }else if x >= 1024 && x < 1024*1024 { + return label + String(format: "%0.2f KB", Float(x)/1024.0) + s + }else if x >= 1024*1024 && x < 1024*1024*1024 { + + return label + String(format: "%0.2f MB", Float(x)/1024/1024) + s + }else { + + return label + String(format: "%0.2f GB", Float(x)/1024/1024/1024) + s + } + + } + +} diff --git a/Surf-Today/RequestsWindowController.xib b/Surf-Today/RequestsWindowController.xib new file mode 100644 index 0000000..3943b82 --- /dev/null +++ b/Surf-Today/RequestsWindowController.xib @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf-Today/StatCell.swift b/Surf-Today/StatCell.swift new file mode 100644 index 0000000..c50415f --- /dev/null +++ b/Surf-Today/StatCell.swift @@ -0,0 +1,78 @@ +// +// StatCell.swift +// Surf +// +// Created by 孔祥波 on 24/11/2016. +// Copyright © 2016 abigt. All rights reserved. +// + +import Cocoa +import NetworkExtension +class StatCell: NSTableCellView { + + //@IBOutlet weak var iconView:NSImageView! + //@IBOutlet weak var titleField:NSTextField! + //@IBOutlet weak var timeField:NSTextField! + @IBOutlet weak var connectButton:NSButton! + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + // Drawing code here. + } + public func secondToString(second:Int) ->String { + + let sec = second % 60 + let min = second % (60*60) / 60 + let hour = second / (60*60) + + return String.init(format: "%02d:%02d:%02d", hour,min,sec) + + + } + func showStatus(_ connection:NEVPNConnection){ + if let m = SFVPNManager.shared.manager, m.connection.status == .connected { + + } + + let status:NEVPNStatus = connection.status + switch status{ + case .disconnected: + imageView?.objectValue = NSImage.init(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + textField?.stringValue = "Disconnected" + connectButton.title = "Connect" + + case .invalid: + imageView?.objectValue = NSImage.init(named: NSImage.Name(rawValue: "NSStatusUnavailable")) + + textField?.stringValue = "Disconnected" + + case .connected: + let start = connection.connectedDate! + let now = Date() + let timeStr = secondToString(second: Int(now.timeIntervalSince(start))) + imageView?.objectValue = NSImage.init(named:NSImage.Name(rawValue: "NSStatusAvailable")) + + textField?.stringValue = "Connected " + timeStr + connectButton.title = "Disconnect" + + case .connecting: + imageView?.objectValue = NSImage.init(named:NSImage.Name(rawValue: "NSStatusAvailable")) + + textField?.stringValue = "Connecting" + case .disconnecting: + imageView?.objectValue = NSImage.init(named:NSImage.Name(rawValue: "NSStatusAvailable")) + + + textField?.stringValue = "Disconnecting" + case .reasserting: + imageView?.objectValue = NSImage.init(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + + + textField?.stringValue = "Reasserting" + + } + + + } + +} diff --git a/Surf-Today/Surf_Today.entitlements b/Surf-Today/Surf_Today.entitlements new file mode 100644 index 0000000..27e4f32 --- /dev/null +++ b/Surf-Today/Surf_Today.entitlements @@ -0,0 +1,33 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.application-identifier + 745WQDK4L7.com.abigt.Surf.mac.Surf-Today + com.apple.developer.networking.networkextension + + packet-tunnel-provider + app-proxy-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + com.apple.developer.team-identifier + 745WQDK4L7 + com.apple.security.application-groups + + 745WQDK4L7.com.abigt.Surf + + com.apple.security.network.client + + keychain-access-groups + + 745WQDK4L7.* + + + diff --git a/Surf-Today/TodayViewController.swift b/Surf-Today/TodayViewController.swift new file mode 100644 index 0000000..1c17fc3 --- /dev/null +++ b/Surf-Today/TodayViewController.swift @@ -0,0 +1,183 @@ +// +// TodayViewController.swift +// Surf-Today +// +// Created by abigt on 2016/11/22. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Cocoa +import NotificationCenter +import NetworkExtension +import DarwinCore +import SFSocket +import XRuler +class TodayViewController: NSViewController, NCWidgetProviding { + + @IBOutlet weak var iconView:NSImageView! + @IBOutlet weak var titleField:NSTextField! + @IBOutlet weak var timeField:NSTextField! + @IBOutlet weak var connectButton:NSButton! + var timer:Timer? + override var nibName: NSNib.Name { + return NSNib.Name.init("TodayViewController") + } + + @IBAction func startStopToggled(_ sender:AnyObject) { + + do { + let selectConf = ProxyGroupSettings.share.config + let result = try SFVPNManager.shared.startStopToggled(selectConf) + if !result { + + } + + } catch let error { + SFVPNManager.shared.xpc() + + } + + } + public func secondToString(second:Int) ->String { + + let sec = second % 60 + let min = second % (60*60) / 60 + let hour = second / (60*60) + + return String.init(format: "%02d:%02d:%02d", hour,min,sec) + + + } + func reloadStatus(){ + //Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #, userInfo: <#T##Any?#>, repeats: <#T##Bool#>) + timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(TodayViewController.trafficReport(_:)), userInfo: nil, repeats: true) + + } + public func toString(x:UInt,label:String,speed:Bool) ->String { + + var s = "/s" + if !speed { + s = "" + } + + if x < 1024{ + return label + " \(x) B" + s + }else if x >= 1024 && x < 1024*1024 { + return label + String(format: "%d KB", Int(Float(x)/1024.0)) + s + }else if x >= 1024*1024 && x < 1024*1024*1024 { + //return label + "\(x/1024/1024) MB" + s + return label + String(format: "%.2f MB", Float(x)/1024/1024) + s + }else { + //return label + "\(x/1024/1024/1024) GB" + s + return label + String(format: "%.2f GB", Float(x)/1024/1024/1024) + s + } + + } + @objc func trafficReport(_ t:Timer) { + updateTime() + } + func updateTime(){ + if let m = SFVPNManager.shared.manager, m.connection.status == .connected { + let start = m.connection.connectedDate! + let now = Date() + let count = DataCounters("240.7.1.9") + let down = toString(x: count!.tunReceived, label: "RX:", speed: false) + let up = toString(x: count!.tunSent, label: "TX:", speed: false) + timeField.stringValue = secondToString(second: Int(now.timeIntervalSince(start))) + " " + down + " " + up + + } + } + func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) { + // Update your data and prepare for a snapshot. Call completion handler when you are done + // with NoData if nothing has changed or NewData if there is new data since the last + // time we called you + completionHandler(.noData) + } + + override func viewDidLoad(){ + super.viewDidLoad() + loadManager() + reloadStatus() + } + + + func loadManager() { + //print("loadManager") + let vpnmanager = SFVPNManager.shared + if !vpnmanager.loading { + vpnmanager.loadManager() { + [weak self] (manager, error) -> Void in + if let m = manager { + self!.showStatus(m.connection) + self!.registerStatus() + vpnmanager.xpc() + } + } + }else { + print("vpnmanager loading") + } + + } + func showStatus(_ connection:NEVPNConnection){ + let status:NEVPNStatus = connection.status + switch status{ + case .disconnected: + iconView.image = NSImage.init(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + titleField.stringValue = "Disconnected" + connectButton.title = "Connect" + timeField.isHidden = true + case .invalid: + iconView.image = NSImage.init(named: NSImage.Name(rawValue: "NSStatusUnavailable")) + + titleField.stringValue = "Disconnected" + timeField.isHidden = true + case .connected: + iconView.image = NSImage.init(named:NSImage.Name(rawValue: "NSStatusAvailable")) + timeField.isHidden = false + titleField.stringValue = "Connected" + connectButton.title = "Disconnect" + + case .connecting: + iconView.image = NSImage.init(named:NSImage.Name(rawValue: "NSStatusAvailable")) + timeField.isHidden = true + titleField.stringValue = "Connecting" + case .disconnecting: + iconView.image = NSImage.init(named:NSImage.Name(rawValue: "NSStatusAvailable")) + + timeField.isHidden = true + titleField.stringValue = "NSStatusAvailable" + case .reasserting: + iconView.image = NSImage.init(named:NSImage.Name(rawValue: "RedDot")) + + timeField.isHidden = true + titleField.stringValue = "NSStatusPartiallyAvailable" + + } + + + } + func registerStatus(){ + if let m = SFVPNManager.shared.manager { + // Register to be notified of changes in the status. + NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: m.connection, queue: OperationQueue.main, using: { [weak self] notification in + + if let o = notification.object { + if let c = o as? NEVPNConnection{ + //self!.autoRedail = false + print(c) + //try! SFVPNManager.shared.startStopToggled("") + if let strong = self { + strong.showStatus(c) + } + } + + } + + + }) + }else { + + } + + } +} diff --git a/Surf-Today/en.lproj/InfoPlist.strings b/Surf-Today/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..b0a58d2 --- /dev/null +++ b/Surf-Today/en.lproj/InfoPlist.strings @@ -0,0 +1,4 @@ +/* Display name and description for this extension. */ +"CFBundleDisplayName" = "A.BIG.T"; +"com.apple.notificationcenter.widget.description" = "A.BIG.T"; + diff --git a/Surf-Today/zh-Hans.lproj/InfoPlist.strings b/Surf-Today/zh-Hans.lproj/InfoPlist.strings new file mode 100644 index 0000000..b0a58d2 --- /dev/null +++ b/Surf-Today/zh-Hans.lproj/InfoPlist.strings @@ -0,0 +1,4 @@ +/* Display name and description for this extension. */ +"CFBundleDisplayName" = "A.BIG.T"; +"com.apple.notificationcenter.widget.description" = "A.BIG.T"; + diff --git a/Surf-Today/zh-Hans.lproj/TodayViewController.strings b/Surf-Today/zh-Hans.lproj/TodayViewController.strings new file mode 100644 index 0000000..b5e91c1 --- /dev/null +++ b/Surf-Today/zh-Hans.lproj/TodayViewController.strings @@ -0,0 +1,12 @@ + +/* Class = "NSButtonCell"; title = "Button"; ObjectID = "3h3-5z-pJy"; */ +"3h3-5z-pJy.title" = "Button"; + +/* Class = "NSTextFieldCell"; placeholderString = "00:00:00"; ObjectID = "NO5-qL-UId"; */ +"NO5-qL-UId.placeholderString" = "00:00:00"; + +/* Class = "NSTextFieldCell"; title = "Connected Time"; ObjectID = "NO5-qL-UId"; */ +"NO5-qL-UId.title" = "Connected Time"; + +/* Class = "NSTextFieldCell"; title = "Status"; ObjectID = "aFW-rf-X1A"; */ +"aFW-rf-X1A.title" = "Status"; diff --git a/Surf.xcodeproj/project.pbxproj b/Surf.xcodeproj/project.pbxproj new file mode 100644 index 0000000..13ea02a --- /dev/null +++ b/Surf.xcodeproj/project.pbxproj @@ -0,0 +1,3098 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5756A9591BFF1DA4006C08BB /* AddEditProxyController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5756A9581BFF1DA4006C08BB /* AddEditProxyController.swift */; }; + 5756A95B1C02C321006C08BB /* TextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5756A95A1C02C321006C08BB /* TextFieldCell.swift */; }; + 578ED92E1C03181300913B2F /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 578ED92D1C03181300913B2F /* PacketTunnelProvider.swift */; }; + 6903CDD620159D1200642B68 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6903CDD520159D1100642B68 /* Crashlytics.framework */; }; + 6903CDD720159D2100642B68 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6903CDD520159D1100642B68 /* Crashlytics.framework */; }; + 6903CDD820159D2400642B68 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6903CDD520159D1100642B68 /* Crashlytics.framework */; }; + 6904E8161CAE197000179E81 /* ProxyGroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6904E8151CAE197000179E81 /* ProxyGroupViewController.swift */; }; + 6904E8181CAE653E00179E81 /* ProxyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6904E8171CAE653E00179E81 /* ProxyCell.swift */; }; + 6906B75C1EF2728200CA66CA /* SFSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 693B74491ED9FA69004C6E87 /* SFSocket.framework */; }; + 6906B75D1EF2728200CA66CA /* SFSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 693B74491ED9FA69004C6E87 /* SFSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 6906B7611EF280B400CA66CA /* SFVerify.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6906B7601EF280B400CA66CA /* SFVerify.swift */; }; + 6906B7661EF36B5B00CA66CA /* SwiftyStoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B7651EF36B5B00CA66CA /* SwiftyStoreKit.framework */; }; + 6906B7681EF36B6700CA66CA /* Charts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B7671EF36B6700CA66CA /* Charts.framework */; }; + 6906B76A1EF36B9C00CA66CA /* Charts.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B7671EF36B6700CA66CA /* Charts.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 6906B76E1EF36BA600CA66CA /* SwiftyStoreKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B7651EF36B5B00CA66CA /* SwiftyStoreKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 6906B9011DE1954700A60B66 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B9001DE1954700A60B66 /* NetworkExtension.framework */; }; + 6906B9031DE1955400A60B66 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B9001DE1954700A60B66 /* NetworkExtension.framework */; }; + 6906B90C1DE29D8F00A60B66 /* Config.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6906B90B1DE29D8F00A60B66 /* Config.storyboard */; }; + 6906B90E1DE29F8300A60B66 /* ConfigWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6906B90D1DE29F8300A60B66 /* ConfigWindowController.swift */; }; + 6906B9151DE2A36C00A60B66 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6906B9131DE2A2D600A60B66 /* MainMenu.xib */; }; + 6906B9171DE2A6E300A60B66 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6906B9161DE2A6E300A60B66 /* PreferencesWindowController.swift */; }; + 6906B9191DE2A6EC00A60B66 /* PreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6906B9181DE2A6EC00A60B66 /* PreferencesWindowController.xib */; }; + 6906B91B1DE2B8BA00A60B66 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6906B91A1DE2B8BA00A60B66 /* StatusView.swift */; }; + 6906B91C1DE2BD8500A60B66 /* ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 69A9FE4B1CC5C0CF00D5DB41 /* ionicons.ttf */; }; + 6906B91D1DE2C5E700A60B66 /* SFInterfaceTraffic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69B3D9801D2DFFFC00E1626C /* SFInterfaceTraffic.swift */; }; + 6906B93E1DE3E62F00A60B66 /* thanks.txt in Resources */ = {isa = PBXBuildFile; fileRef = 693B603C1C479F2A00173D0B /* thanks.txt */; }; + 6906B9401DE410BF00A60B66 /* surf.conf in Resources */ = {isa = PBXBuildFile; fileRef = 6964C0B21CF5931A0021897B /* surf.conf */; }; + 6906B9441DE5412B00A60B66 /* SFCountry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693DBDFE1C96977A0067595C /* SFCountry.swift */; }; + 6906B9451DE5456900A60B66 /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 693DBE011C969C610067595C /* data.json */; }; + 69075CC71D3D157E008D1770 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 691B366C1C0F4BAE001C815D /* libresolv.tbd */; }; + 6907E9C120102B1900E7B1FE /* HelpWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6907E9C020102B1900E7B1FE /* HelpWindow.xib */; }; + 6907E9C320102BC400E7B1FE /* HelpWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6907E9C220102BC400E7B1FE /* HelpWindowController.swift */; }; + 6907E9C720104ECC00E7B1FE /* RequestDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6907E9C620104ECC00E7B1FE /* RequestDetailView.swift */; }; + 6907E9C92010508900E7B1FE /* RequestTabVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6907E9C82010508900E7B1FE /* RequestTabVC.swift */; }; + 6907E9CB201178A900E7B1FE /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6907E9CA201178A900E7B1FE /* Sparkle.framework */; }; + 6907E9CC20117FE600E7B1FE /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6907E9CA201178A900E7B1FE /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 6907E9CF201180DB00E7B1FE /* UpdateWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6907E9CD201180DB00E7B1FE /* UpdateWindowController.swift */; }; + 6907E9D22011815100E7B1FE /* SUUpdateSettingsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6907E9D12011815100E7B1FE /* SUUpdateSettingsWindowController.xib */; }; + 6907E9D42011959E00E7B1FE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6907E9D32011959E00E7B1FE /* Assets.xcassets */; }; + 6907E9D52011AE6100E7B1FE /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A52007A96A0044FA53 /* Fabric.framework */; }; + 690AB8761E9764A9001A6C3A /* MMDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 697B7C3D1DDF41F400584179 /* MMDB.framework */; }; + 690AB87E1E9764F1001A6C3A /* AxLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E5E1DD97B640047112C /* AxLogger.framework */; }; + 690AB87F1E9764F1001A6C3A /* AxLogger.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E5E1DD97B640047112C /* AxLogger.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 690AB8811E9764F6001A6C3A /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E5C1DD97B5D0047112C /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 690AB8851E97652F001A6C3A /* ObjectMapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 690AB8841E97652F001A6C3A /* ObjectMapper.framework */; }; + 690AB8861E97652F001A6C3A /* ObjectMapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 690AB8841E97652F001A6C3A /* ObjectMapper.framework */; }; + 690AB8881E976534001A6C3A /* ObjectMapper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 690AB8841E97652F001A6C3A /* ObjectMapper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 690C64D01D66BB9F00FB9BA7 /* SFactivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690C64CF1D66BB9F00FB9BA7 /* SFactivity.swift */; }; + 690C64D31D67670B00FB9BA7 /* SFConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690C64D21D67670B00FB9BA7 /* SFConfigManager.swift */; }; + 690C77C11CF42FF100EB1610 /* Default.conf in Resources */ = {isa = PBXBuildFile; fileRef = 690C77C01CF42FF100EB1610 /* Default.conf */; }; + 690FF0001C64546B005F1095 /* SFDocumentPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690FEFFF1C64546B005F1095 /* SFDocumentPickerViewController.swift */; }; + 69100F621CB5F7B00023F88F /* SFTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E136821C705107002BFBF2 /* SFTableViewController.swift */; }; + 69100F641CB5FFD10023F88F /* image.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69100F631CB5FFD10023F88F /* image.xcassets */; }; + 691462AF1D6D3C44007992F2 /* SFMethodViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 691462AE1D6D3C44007992F2 /* SFMethodViewController.swift */; }; + 691462B11D6D3C5D007992F2 /* SSMethod.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 691462B01D6D3C5D007992F2 /* SSMethod.storyboard */; }; + 6916AB591CDB9DB200C2FC48 /* rules_public.conf in Resources */ = {isa = PBXBuildFile; fileRef = 6916AB581CDB9DB200C2FC48 /* rules_public.conf */; }; + 6916AB941CDE600100C2FC48 /* SFRuleWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6916AB931CDE600100C2FC48 /* SFRuleWriter.swift */; }; + 691883501DDDA03C0051DAAE /* lwip.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6918834E1DDDA0280051DAAE /* lwip.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 691B366D1C0F4BAE001C815D /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 691B366C1C0F4BAE001C815D /* libresolv.tbd */; }; + 692075871CE6DE83000F1ED9 /* SFVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695BBDD81C64823900879ABB /* SFVPNManager.swift */; }; + 6920758B1CE77C12000F1ED9 /* HostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920758A1CE77C12000F1ED9 /* HostsTableViewController.swift */; }; + 6920758D1CE77C29000F1ED9 /* HostEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920758C1CE77C29000F1ED9 /* HostEditTableViewController.swift */; }; + 692128521E9C7AC500560DEC /* PacketTunnel-iOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 578ED9291C03181200913B2F /* PacketTunnel-iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 69263EF21EE504BA005F0C76 /* snappy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EEB1EE50491005F0C76 /* snappy.framework */; }; + 69263EF31EE504BA005F0C76 /* snappy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EEB1EE50491005F0C76 /* snappy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69263F021EE511A3005F0C76 /* snappy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EEB1EE50491005F0C76 /* snappy.framework */; }; + 69263F031EE511AA005F0C76 /* SFSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EF81EE50C5B005F0C76 /* SFSocket.framework */; }; + 692806351EFA7E7C007FCF6A /* SFSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EF81EE50C5B005F0C76 /* SFSocket.framework */; }; + 692806361EFA7E7C007FCF6A /* SFSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EF81EE50C5B005F0C76 /* SFSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69290F8420302F9600780915 /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 69290F8320302F9500780915 /* icon.icns */; }; + 692B4FFA1C71646200BB793B /* RequestDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692B4FF91C71646200BB793B /* RequestDetailViewController.swift */; }; + 692B4FFC1C71A0E600BB793B /* SFAppIden.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692B4FFB1C71A0E600BB793B /* SFAppIden.swift */; }; + 692B4FFE1C71A11300BB793B /* useragents.plist in Resources */ = {isa = PBXBuildFile; fileRef = 692B4FFD1C71A11300BB793B /* useragents.plist */; }; + 692B4FFF1C71A11800BB793B /* useragents.plist in Resources */ = {isa = PBXBuildFile; fileRef = 692B4FFD1C71A11300BB793B /* useragents.plist */; }; + 692D8CFA1C6A250400C07B3A /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692D8CF91C6A250400C07B3A /* NotificationCenter.framework */; }; + 692D8D001C6A250400C07B3A /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 692D8CFE1C6A250400C07B3A /* MainInterface.storyboard */; }; + 692D8D091C6A27FE00C07B3A /* today.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 692D8D081C6A27FE00C07B3A /* today.entitlements */; }; + 692D8D0A1C6A2AC900C07B3A /* SFVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695BBDD81C64823900879ABB /* SFVPNManager.swift */; }; + 69303FC31ECA99620089AFFA /* snappy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69303FC21ECA99610089AFFA /* snappy.framework */; }; + 69303FCB1ECA99940089AFFA /* snappy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69303FC21ECA99610089AFFA /* snappy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69303FCD1ECA9A8E0089AFFA /* KcpTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69303FCC1ECA9A8E0089AFFA /* KcpTableViewController.swift */; }; + 69348F2B1FFB653D007C841C /* LoglevelTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6965AA781C56070600F38B8D /* LoglevelTableViewController.swift */; }; + 69348F2C1FFB6BBE007C841C /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692D8CFC1C6A250400C07B3A /* TodayViewController.swift */; }; + 69348F331FFB713F007C841C /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F311FFB713E007C841C /* Fabric.framework */; }; + 69348F351FFB7150007C841C /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F311FFB713E007C841C /* Fabric.framework */; }; + 69348F3A1FFB7214007C841C /* XProxy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F361FFB7211007C841C /* XProxy.framework */; }; + 69348F3D1FFB7214007C841C /* XSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F391FFB7213007C841C /* XSocket.framework */; }; + 69348F3E1FFB7234007C841C /* Xcon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F371FFB7212007C841C /* Xcon.framework */; }; + 69348F3F1FFB7234007C841C /* Xcon.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F371FFB7212007C841C /* Xcon.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69348F411FFB7234007C841C /* XProxy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F361FFB7211007C841C /* XProxy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69348F421FFB7234007C841C /* XRuler.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F381FFB7213007C841C /* XRuler.framework */; }; + 69348F431FFB7234007C841C /* XRuler.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F381FFB7213007C841C /* XRuler.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69348F451FFB7234007C841C /* XSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F391FFB7213007C841C /* XSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69366E5A1BFECBE700AE123D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69366E591BFECBE700AE123D /* AppDelegate.swift */; }; + 69366E5C1BFECBE700AE123D /* SFConfigViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69366E5B1BFECBE700AE123D /* SFConfigViewController.swift */; }; + 69366E5E1BFECBE700AE123D /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69366E5D1BFECBE700AE123D /* SecondViewController.swift */; }; + 69366E611BFECBE700AE123D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 69366E5F1BFECBE700AE123D /* Main.storyboard */; }; + 69366E631BFECBE700AE123D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69366E621BFECBE700AE123D /* Assets.xcassets */; }; + 6936B4D71C4D304C000EBF70 /* ISO_3166.txt in Resources */ = {isa = PBXBuildFile; fileRef = 6936B4D61C4D304C000EBF70 /* ISO_3166.txt */; }; + 693766BA1DFE8F7C0015C549 /* QRView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693766B91DFE8F7C0015C549 /* QRView.swift */; }; + 6938E6531D388A9200671B96 /* SFInterfaceTraffic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69B3D9801D2DFFFC00E1626C /* SFInterfaceTraffic.swift */; }; + 693AAE11200EDA4E009E481E /* KwaziiAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693AAE10200EDA4E009E481E /* KwaziiAppDelegate.swift */; }; + 693AAE13200EDA4F009E481E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693AAE12200EDA4F009E481E /* ViewController.swift */; }; + 693AAE18200EDA4F009E481E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 693AAE16200EDA4F009E481E /* Main.storyboard */; }; + 693AAE1F200EDF1A009E481E /* RequestsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693AAE1E200EDF1A009E481E /* RequestsVC.swift */; }; + 693AAE29200EDF82009E481E /* XDataService.h in Headers */ = {isa = PBXBuildFile; fileRef = 693AAE27200EDF82009E481E /* XDataService.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 693AAE2C200EDF82009E481E /* XDataService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 693AAE25200EDF82009E481E /* XDataService.framework */; }; + 693AAE2D200EDF82009E481E /* XDataService.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 693AAE25200EDF82009E481E /* XDataService.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE32200EDFA5009E481E /* RequestsBasic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693AAE31200EDFA5009E481E /* RequestsBasic.swift */; }; + 693AAE33200EE1D7009E481E /* SFAppExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696847771D504E87005E17C2 /* SFAppExtension.swift */; }; + 693AAE34200EE1F5009E481E /* SFAppIden.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692B4FFB1C71A0E600BB793B /* SFAppIden.swift */; }; + 693AAE35200EE204009E481E /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 693AAE36200EE215009E481E /* SFConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690C64D21D67670B00FB9BA7 /* SFConfigManager.swift */; }; + 693AAE3A200EE646009E481E /* XDataService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 693AAE25200EDF82009E481E /* XDataService.framework */; }; + 693AAE3B200EE646009E481E /* XDataService.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 693AAE25200EDF82009E481E /* XDataService.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE40200EE6B3009E481E /* Reachability.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26C62007ACDE0044FA53 /* Reachability.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE42200EE6B6009E481E /* XProxy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26BD2007AC2B0044FA53 /* XProxy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE44200EE6B9009E481E /* XFoundation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B92007AC190044FA53 /* XFoundation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE46200EE6BB009E481E /* XSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B52007AC0E0044FA53 /* XSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE48200EE6BF009E481E /* XRuler.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26AD2007ABFB0044FA53 /* XRuler.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE49200EE6CE009E481E /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A42007A96A0044FA53 /* Crashlytics.framework */; }; + 693AAE4A200EE6D6009E481E /* SFSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EF81EE50C5B005F0C76 /* SFSocket.framework */; }; + 693AAE52200EE710009E481E /* Xcon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B12007AC060044FA53 /* Xcon.framework */; }; + 693AAE53200EE710009E481E /* Xcon.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B12007AC060044FA53 /* Xcon.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE57200EE71A009E481E /* SFSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EF81EE50C5B005F0C76 /* SFSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE59200EE71E009E481E /* snappy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69263EEB1EE50491005F0C76 /* snappy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE5B200EE723009E481E /* ObjectMapper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69BCD77D1EE469D100A8A19C /* ObjectMapper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE5D200EE727009E481E /* GRDB.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 694397B71E5C37FE0009AD0E /* GRDB.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE5F200EE729009E481E /* kcp.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69639C231EE1C34400893D18 /* kcp.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE61200EE72D009E481E /* AxLogger.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3B1DE0A467007E32C2 /* AxLogger.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE63200EE730009E481E /* CocoaAsyncSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3C1DE0A467007E32C2 /* CocoaAsyncSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE65200EE733009E481E /* CommonCrypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3D1DE0A467007E32C2 /* CommonCrypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE67200EE736009E481E /* Crypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3E1DE0A467007E32C2 /* Crypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE69200EE739009E481E /* DarwinCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE6B200EE73B009E481E /* lwip.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D411DE0A467007E32C2 /* lwip.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE6D200EE742009E481E /* MMDB.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D421DE0A467007E32C2 /* MMDB.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE6F200EE744009E481E /* Sodium.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D441DE0A467007E32C2 /* Sodium.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE71200EE747009E481E /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE73200EE749009E481E /* SystemKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D461DE0A467007E32C2 /* SystemKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693AAE77200EEA3C009E481E /* MainWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693AAE76200EEA3C009E481E /* MainWindow.swift */; }; + 693AAE79200EED15009E481E /* RequestBasic.xib in Resources */ = {isa = PBXBuildFile; fileRef = 693AAE78200EED15009E481E /* RequestBasic.xib */; }; + 693AAE7A200EF24F009E481E /* RequestBasic.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 693AAE38200EE3D3009E481E /* RequestBasic.storyboard */; }; + 693AAE7C200EF7F3009E481E /* abigt.conf in Resources */ = {isa = PBXBuildFile; fileRef = 693AAE7B200EF7F3009E481E /* abigt.conf */; }; + 693AAE7D200F0F7A009E481E /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6906B9161DE2A6E300A60B66 /* PreferencesWindowController.swift */; }; + 693AAE7F200F0F81009E481E /* PreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6906B9181DE2A6EC00A60B66 /* PreferencesWindowController.xib */; }; + 693AAE82200F1742009E481E /* SFCountry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693DBDFE1C96977A0067595C /* SFCountry.swift */; }; + 693AAE83200F1A94009E481E /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 693DBE011C969C610067595C /* data.json */; }; + 693AAE85200F2A84009E481E /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 693AAE86200F2FB6009E481E /* RequestsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693AAE1E200EDF1A009E481E /* RequestsVC.swift */; }; + 693AAE87200F2FBD009E481E /* RequestBasic.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 693AAE38200EE3D3009E481E /* RequestBasic.storyboard */; }; + 693B603D1C479F2A00173D0B /* thanks.txt in Resources */ = {isa = PBXBuildFile; fileRef = 693B603C1C479F2A00173D0B /* thanks.txt */; }; + 693B603F1C48867500173D0B /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 693B744B1ED9FA69004C6E87 /* SFSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 693B74491ED9FA69004C6E87 /* SFSocket.framework */; }; + 693B744C1ED9FA69004C6E87 /* SFSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 693B74491ED9FA69004C6E87 /* SFSocket.framework */; }; + 693DBDFF1C96977A0067595C /* SFCountry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693DBDFE1C96977A0067595C /* SFCountry.swift */; }; + 693DBE021C969C610067595C /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 693DBE011C969C610067595C /* data.json */; }; + 69421BE01C4CD90300021649 /* ConfigTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69421BDF1C4CD90300021649 /* ConfigTableViewController.swift */; }; + 69421BE21C4CE6B100021649 /* iTunesFileTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69421BE11C4CE6B100021649 /* iTunesFileTableViewController.swift */; }; + 694397B41E5C10B10009AD0E /* SFNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694397B31E5C10B10009AD0E /* SFNavigationController.swift */; }; + 694397B61E5C16470009AD0E /* SFTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694397B51E5C16470009AD0E /* SFTableViewCell.swift */; }; + 694397B91E5C37FE0009AD0E /* GRDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 694397B71E5C37FE0009AD0E /* GRDB.framework */; }; + 694397BA1E5C38170009AD0E /* GRDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 694397B71E5C37FE0009AD0E /* GRDB.framework */; }; + 694397BB1E5C38170009AD0E /* GRDB.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 694397B71E5C37FE0009AD0E /* GRDB.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 694492311C568E4F00DD75CA /* RulesTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694492301C568E4F00DD75CA /* RulesTableViewController.swift */; }; + 694536B91C730DFE00C4595D /* PolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694536B81C730DFE00C4595D /* PolicyViewController.swift */; }; + 6946FAF21CB6330C00A8586E /* .adblock in Resources */ = {isa = PBXBuildFile; fileRef = 6946FAF11CB6330C00A8586E /* .adblock */; }; + 6947D76D1CE4CC340020BBCB /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 691B366C1C0F4BAE001C815D /* libresolv.tbd */; }; + 694CFA7D200BBF9B009FA3C3 /* ENV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BE2E681FFC704C0078845A /* ENV.swift */; }; + 695234331E35A4350049EB94 /* DarwinCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */; }; + 69524B031D2E08F100FA4DC7 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696702131CFBE6A8008D36C8 /* SystemConfiguration.framework */; }; + 69524B051D2E091C00FA4DC7 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69524B041D2E091C00FA4DC7 /* CFNetwork.framework */; }; + 6952BAEA1DF92F9D00DAD397 /* QrWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6952BAE81DF92F9D00DAD397 /* QrWindowController.swift */; }; + 6952BAEC1DF9314500DAD397 /* QRCodeWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 69BFCCDB1DE34D1200469B8C /* QRCodeWindow.xib */; }; + 6952BAF11DF9529700DAD397 /* QrController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6952BAF01DF9529700DAD397 /* QrController.swift */; }; + 69558F731E002832008D5F3D /* SFMono-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 69D18ED61DE9C0FB006264F9 /* SFMono-Regular.otf */; }; + 6957A2D51F04D27700B54B90 /* ChartsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6957A2D41F04D27700B54B90 /* ChartsView.swift */; }; + 695987961C15894C003E1DDC /* LogFileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695987951C15894C003E1DDC /* LogFileViewController.swift */; }; + 695B20311C6195500063F794 /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 695B20321C6195510063F794 /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 695BBDD91C64823900879ABB /* SFVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695BBDD81C64823900879ABB /* SFVPNManager.swift */; }; + 695EA9AE1E81069000D594CC /* HistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695EA9AD1E81069000D594CC /* HistoryViewController.swift */; }; + 69639BC71EE1636700893D18 /* DarwinCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69639BC61EE1636700893D18 /* DarwinCore.framework */; }; + 69639BC91EE1637100893D18 /* DarwinCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69639BC61EE1636700893D18 /* DarwinCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69639BCE1EE179B400893D18 /* kcp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 693B744D1ED9FA7A004C6E87 /* kcp.framework */; }; + 69639BCF1EE179B400893D18 /* kcp.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 693B744D1ED9FA7A004C6E87 /* kcp.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69639C241EE1C34400893D18 /* kcp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69639C231EE1C34400893D18 /* kcp.framework */; }; + 6964C0B31CF5931A0021897B /* surf.conf in Resources */ = {isa = PBXBuildFile; fileRef = 6964C0B21CF5931A0021897B /* surf.conf */; }; + 6964C0B51CF5AC130021897B /* TitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6964C0B41CF5AC130021897B /* TitleView.swift */; }; + 696573D21DE48EBF00D95D59 /* AdvancedWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696573D01DE48EBF00D95D59 /* AdvancedWindowController.swift */; }; + 696573D31DE48EBF00D95D59 /* AdvancedWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 696573D11DE48EBF00D95D59 /* AdvancedWindowController.xib */; }; + 696573ED1DE4959B00D95D59 /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692D8CF91C6A250400C07B3A /* NotificationCenter.framework */; }; + 696573F21DE4959B00D95D59 /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696573F11DE4959B00D95D59 /* TodayViewController.swift */; }; + 696573F51DE4959B00D95D59 /* TodayViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 696573F31DE4959B00D95D59 /* TodayViewController.xib */; }; + 696573F91DE4959B00D95D59 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 696573F71DE4959B00D95D59 /* InfoPlist.strings */; }; + 696574001DE497B100D95D59 /* SFVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695BBDD81C64823900879ABB /* SFVPNManager.swift */; }; + 696574021DE4984D00D95D59 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */; }; + 696574031DE4985D00D95D59 /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 696574081DE49FEA00D95D59 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69366E621BFECBE700AE123D /* Assets.xcassets */; }; + 6965AA761C56056C00F38B8D /* TwoLableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6965AA751C56056C00F38B8D /* TwoLableCell.swift */; }; + 696702141CFBE6A8008D36C8 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696702131CFBE6A8008D36C8 /* SystemConfiguration.framework */; }; + 69673C471F32D41E0003AB6C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69673C4A1F32D41E0003AB6C /* Localizable.strings */; }; + 69673C481F32D41E0003AB6C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69673C4A1F32D41E0003AB6C /* Localizable.strings */; }; + 69673C4C1F32D6A00003AB6C /* help.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 69673C4E1F32D6A00003AB6C /* help.storyboard */; }; + 696847791D504E8A005E17C2 /* SFAppExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696847771D504E87005E17C2 /* SFAppExtension.swift */; }; + 696DD2DA1C7B132E00C34416 /* OndemandController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696DD2D91C7B132E00C34416 /* OndemandController.swift */; }; + 696E73B51C44CEEA00DF9A39 /* DataShare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696E73B31C44CEEA00DF9A39 /* DataShare.swift */; }; + 696E73B61C44CEEA00DF9A39 /* Socks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696E73B41C44CEEA00DF9A39 /* Socks.swift */; }; + 696E73B91C44E59D00DF9A39 /* LogListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696E73B81C44E59D00DF9A39 /* LogListTableViewController.swift */; }; + 69707AF01EF37F2C00C7BD9D /* NetworkActivityIndicatorManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69707AEE1EF37F2C00C7BD9D /* NetworkActivityIndicatorManager.swift */; }; + 69707AF11EF37F2C00C7BD9D /* BuyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69707AEF1EF37F2C00C7BD9D /* BuyViewController.swift */; }; + 69707AF31EF37F5D00C7BD9D /* buy.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 69707AF21EF37F5D00C7BD9D /* buy.storyboard */; }; + 6970CDDA1CE46701009850DE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6970CDD91CE46701009850DE /* Security.framework */; }; + 6970CDDB1CE46710009850DE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6970CDD91CE46701009850DE /* Security.framework */; }; + 6971C0DD1D51E83A00CC75BF /* FlyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6971C0DC1D51E83A00CC75BF /* FlyViewController.swift */; }; + 6971C0DF1D51E87000CC75BF /* PlaneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6971C0DE1D51E87000CC75BF /* PlaneView.swift */; }; + 69743A0B202C96E2003A0CE6 /* Charts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6906B7671EF36B6700CA66CA /* Charts.framework */; }; + 69746FCF1C1A80E500CA44BE /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 69746FCD1C1A80E500CA44BE /* LaunchScreen.xib */; }; + 6975F1391F32D17D00F7674C /* ana.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6975F13B1F32D17D00F7674C /* ana.storyboard */; }; + 6975F1431F32D2F100F7674C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6975F1461F32D2F100F7674C /* InfoPlist.strings */; }; + 6975F1441F32D2F100F7674C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6975F1461F32D2F100F7674C /* InfoPlist.strings */; }; + 697770481C7ADBE700C552BF /* CountrySelectController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 697770471C7ADBE700C552BF /* CountrySelectController.swift */; }; + 69784D471DE0A467007E32C2 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3A1DE0A467007E32C2 /* Alamofire.framework */; }; + 69784D491DE0A467007E32C2 /* CocoaAsyncSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3C1DE0A467007E32C2 /* CocoaAsyncSocket.framework */; }; + 69784D4A1DE0A467007E32C2 /* CommonCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3D1DE0A467007E32C2 /* CommonCrypto.framework */; }; + 69784D4B1DE0A467007E32C2 /* Crypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3E1DE0A467007E32C2 /* Crypto.framework */; }; + 69784D4C1DE0A467007E32C2 /* DarwinCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */; }; + 69784D4E1DE0A467007E32C2 /* lwip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D411DE0A467007E32C2 /* lwip.framework */; }; + 69784D4F1DE0A467007E32C2 /* MMDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D421DE0A467007E32C2 /* MMDB.framework */; }; + 69784D511DE0A467007E32C2 /* Sodium.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D441DE0A467007E32C2 /* Sodium.framework */; }; + 69784D521DE0A467007E32C2 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */; }; + 69784D541DE0A7F6007E32C2 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3A1DE0A467007E32C2 /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D561DE0A7FB007E32C2 /* CocoaAsyncSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3C1DE0A467007E32C2 /* CocoaAsyncSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D571DE0A7FD007E32C2 /* CommonCrypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3D1DE0A467007E32C2 /* CommonCrypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D581DE0A808007E32C2 /* Crypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3E1DE0A467007E32C2 /* Crypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D591DE0A80A007E32C2 /* DarwinCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D5B1DE0A80F007E32C2 /* lwip.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D411DE0A467007E32C2 /* lwip.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D5C1DE0A811007E32C2 /* MMDB.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D421DE0A467007E32C2 /* MMDB.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D5E1DE0A818007E32C2 /* Sodium.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D441DE0A467007E32C2 /* Sodium.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D5F1DE0A81A007E32C2 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69784D641DE0A8DE007E32C2 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3A1DE0A467007E32C2 /* Alamofire.framework */; }; + 69784D651DE0A8DE007E32C2 /* AxLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3B1DE0A467007E32C2 /* AxLogger.framework */; }; + 69784D661DE0A8DE007E32C2 /* CocoaAsyncSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3C1DE0A467007E32C2 /* CocoaAsyncSocket.framework */; }; + 69784D671DE0A8DE007E32C2 /* CommonCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3D1DE0A467007E32C2 /* CommonCrypto.framework */; }; + 69784D681DE0A8DE007E32C2 /* Crypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3E1DE0A467007E32C2 /* Crypto.framework */; }; + 69784D691DE0A8DE007E32C2 /* DarwinCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */; }; + 69784D6B1DE0A8DE007E32C2 /* lwip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D411DE0A467007E32C2 /* lwip.framework */; }; + 69784D6C1DE0A8DE007E32C2 /* MMDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D421DE0A467007E32C2 /* MMDB.framework */; }; + 69784D6E1DE0A8DE007E32C2 /* Sodium.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D441DE0A467007E32C2 /* Sodium.framework */; }; + 69784D6F1DE0A8DE007E32C2 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */; }; + 69784D701DE0A8DE007E32C2 /* SystemKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D461DE0A467007E32C2 /* SystemKit.framework */; }; + 697B7C3F1DDF41F400584179 /* MMDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 697B7C3D1DDF41F400584179 /* MMDB.framework */; }; + 697DF0801FFE0C8A00C6A64C /* SurfToday.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 692D8CF71C6A250400C07B3A /* SurfToday.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 697DF0821FFE0D0500C6A64C /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69348F311FFB713E007C841C /* Fabric.framework */; }; + 69801C96200D947400A214D6 /* BarChatsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69801C95200D947400A214D6 /* BarChatsCell.swift */; }; + 6983C0C41DF4F5B600100E70 /* About.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6983C0C31DF4F5B600100E70 /* About.xib */; }; + 6983C0C61DF4F61500100E70 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6983C0C51DF4F61500100E70 /* AboutWindowController.swift */; }; + 69852BE81F33010A00EBFC92 /* IoniconsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6929C3301F32FCE0007C1FA3 /* IoniconsSwift.framework */; }; + 69852BE91F33010A00EBFC92 /* IoniconsSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6929C3301F32FCE0007C1FA3 /* IoniconsSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69852BEA1F3313FE00EBFC92 /* SystemKitiOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DD43541DDC4DD500080CF1 /* SystemKitiOS.framework */; }; + 69852BEB1F3313FE00EBFC92 /* SystemKitiOS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DD43541DDC4DD500080CF1 /* SystemKitiOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 698705791C0FD46500783358 /* BarcodeScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 698705781C0FD46500783358 /* BarcodeScanViewController.swift */; }; + 6987057E1C0FE8A200783358 /* HelpTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6987057D1C0FE8A200783358 /* HelpTableViewController.swift */; }; + 698705801C0FE8F300783358 /* AcknowledgeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6987057F1C0FE8F300783358 /* AcknowledgeViewController.swift */; }; + 6987A6441F31ACCA006FD800 /* ChartsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6957A2D41F04D27700B54B90 /* ChartsView.swift */; }; + 6989ACED1C312A3400DD1435 /* StackHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6989AC021C312A3400DD1435 /* StackHelper.m */; }; + 698BFE221C3A206300CED9EC /* PacketTunnel_Mac.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 698BFE211C3A206300CED9EC /* PacketTunnel_Mac.entitlements */; }; + 6994E01F1DEFCA37009394F9 /* MMDB.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 697B7C3D1DDF41F400584179 /* MMDB.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 699C8F561D79B2D300064802 /* SFViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 699C8F551D79B2D300064802 /* SFViewController.swift */; }; + 69A090081C4C83650064D361 /* SampleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A090071C4C83650064D361 /* SampleCell.swift */; }; + 69A0900B1C4C851C0064D361 /* SFWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A0900A1C4C851C0064D361 /* SFWebViewController.swift */; }; + 69A0900D1C4C8CCC0064D361 /* config.html in Resources */ = {isa = PBXBuildFile; fileRef = 69A0900C1C4C8CCC0064D361 /* config.html */; }; + 69A4ACE41D2E37C7008963FB /* WidgetSelectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A4ACE31D2E37C7008963FB /* WidgetSelectViewController.swift */; }; + 69A99E491C6A2DBF009EC4C5 /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 69A99E4C1C6A2E96009EC4C5 /* SFLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A99E4B1C6A2E96009EC4C5 /* SFLog.swift */; }; + 69A99E4D1C6A2E96009EC4C5 /* SFLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A99E4B1C6A2E96009EC4C5 /* SFLog.swift */; }; + 69A9FE4D1CC5C0CF00D5DB41 /* ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 69A9FE4B1CC5C0CF00D5DB41 /* ionicons.ttf */; }; + 69AD9CC8200354A100C01011 /* XFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69AD9CC7200354A100C01011 /* XFoundation.framework */; }; + 69AD9CC9200354B400C01011 /* XFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69AD9CC7200354A100C01011 /* XFoundation.framework */; }; + 69AD9CCA200354B400C01011 /* XFoundation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69AD9CC7200354A100C01011 /* XFoundation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69B5413E1F207931007D4A4E /* PacketTunnel-Mac.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 69C4EE3C1C29193D0020FBF8 /* PacketTunnel-Mac.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 69B5413F1F207939007D4A4E /* A.BIG.T-Today.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 696573EC1DE4959B00D95D59 /* A.BIG.T-Today.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 69BCD7771EE1CA3400A8A19C /* kcp.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69639C231EE1C34400893D18 /* kcp.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69BCD7781EE1CA5300A8A19C /* SystemKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D461DE0A467007E32C2 /* SystemKit.framework */; }; + 69BCD7791EE1CA5300A8A19C /* SystemKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D461DE0A467007E32C2 /* SystemKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69BCD77B1EE1CA7700A8A19C /* AxLogger.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69784D3B1DE0A467007E32C2 /* AxLogger.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69BCD77F1EE469FB00A8A19C /* ObjectMapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BCD77D1EE469D100A8A19C /* ObjectMapper.framework */; }; + 69BCD7801EE469FB00A8A19C /* ObjectMapper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69BCD77D1EE469D100A8A19C /* ObjectMapper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69BD54C51E975C88008F10DC /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BD54C41E975C88008F10DC /* Reachability.framework */; }; + 69BD54C61E975C88008F10DC /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BD54C41E975C88008F10DC /* Reachability.framework */; }; + 69BD736D1DB4B3740078EB02 /* imageView.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 69BD736B1DB4B3740078EB02 /* imageView.storyboard */; }; + 69BD736E1DB4B3740078EB02 /* ImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BD736C1DB4B3740078EB02 /* ImageViewController.swift */; }; + 69BE2E691FFC704C0078845A /* ENV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BE2E681FFC704C0078845A /* ENV.swift */; }; + 69BE2E6A1FFC706F0078845A /* ENV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BE2E681FFC704C0078845A /* ENV.swift */; }; + 69BEFA2B1C7D84240066118E /* SwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BEFA2A1C7D84240066118E /* SwitchCell.swift */; }; + 69BF6C6B1DE68985000ABF09 /* StatCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BF6C6A1DE68985000ABF09 /* StatCell.swift */; }; + 69BF6C6E1DE6D742000ABF09 /* RequestsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BF6C6C1DE6D742000ABF09 /* RequestsWindowController.swift */; }; + 69BF6C6F1DE6D742000ABF09 /* RequestsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 69BF6C6D1DE6D742000ABF09 /* RequestsWindowController.xib */; }; + 69BF6C701DE6E1E0000ABF09 /* SFAppExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 696847771D504E87005E17C2 /* SFAppExtension.swift */; }; + 69BF6C711DE6E230000ABF09 /* SFAppIden.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692B4FFB1C71A0E600BB793B /* SFAppIden.swift */; }; + 69BF6C741DE6E3C8000ABF09 /* SFConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690C64D21D67670B00FB9BA7 /* SFConfigManager.swift */; }; + 69BF6C751DE6E3F9000ABF09 /* useragents.plist in Resources */ = {isa = PBXBuildFile; fileRef = 692B4FFD1C71A11300BB793B /* useragents.plist */; }; + 69C4EE2C1C2919010020FBF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69C4EE2B1C2919010020FBF8 /* AppDelegate.swift */; }; + 69C4EE2E1C2919010020FBF8 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69C4EE2D1C2919010020FBF8 /* ViewController.swift */; }; + 69C4EE301C2919010020FBF8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69C4EE2F1C2919010020FBF8 /* Assets.xcassets */; }; + 69C9B0D91D3F50490089BC82 /* ConfigEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69C9B0D81D3F50490089BC82 /* ConfigEditViewController.swift */; }; + 69D18ED31DE7E35F006264F9 /* SFApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69D18ED21DE7E35F006264F9 /* SFApplication.swift */; }; + 69D411AD1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69D411AC1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework */; }; + 69D411AE1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69D411AC1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework */; }; + 69D411AF1E975D760095E683 /* IDZSwiftCommonCrypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69D411AC1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69D411B01E975DC30095E683 /* Reachability.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69BD54C41E975C88008F10DC /* Reachability.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69D9C6811C52037E009453AF /* const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693B603E1C48867500173D0B /* const.swift */; }; + 69DA26A62007A96B0044FA53 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A42007A96A0044FA53 /* Crashlytics.framework */; }; + 69DA26A72007A96B0044FA53 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A42007A96A0044FA53 /* Crashlytics.framework */; }; + 69DA26A82007A96B0044FA53 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A42007A96A0044FA53 /* Crashlytics.framework */; }; + 69DA26A92007A96B0044FA53 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A52007A96A0044FA53 /* Fabric.framework */; }; + 69DA26AA2007A96B0044FA53 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A52007A96A0044FA53 /* Fabric.framework */; }; + 69DA26AB2007A96B0044FA53 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26A52007A96A0044FA53 /* Fabric.framework */; }; + 69DA26AC2007AA0C0044FA53 /* ENV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BE2E681FFC704C0078845A /* ENV.swift */; }; + 69DA26AE2007ABFB0044FA53 /* XRuler.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26AD2007ABFB0044FA53 /* XRuler.framework */; }; + 69DA26AF2007ABFB0044FA53 /* XRuler.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26AD2007ABFB0044FA53 /* XRuler.framework */; }; + 69DA26B02007ABFB0044FA53 /* XRuler.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26AD2007ABFB0044FA53 /* XRuler.framework */; }; + 69DA26B22007AC070044FA53 /* Xcon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B12007AC060044FA53 /* Xcon.framework */; }; + 69DA26B32007AC070044FA53 /* Xcon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B12007AC060044FA53 /* Xcon.framework */; }; + 69DA26B42007AC070044FA53 /* Xcon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B12007AC060044FA53 /* Xcon.framework */; }; + 69DA26B62007AC0F0044FA53 /* XSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B52007AC0E0044FA53 /* XSocket.framework */; }; + 69DA26B72007AC0F0044FA53 /* XSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B52007AC0E0044FA53 /* XSocket.framework */; }; + 69DA26B82007AC0F0044FA53 /* XSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B52007AC0E0044FA53 /* XSocket.framework */; }; + 69DA26BA2007AC190044FA53 /* XFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B92007AC190044FA53 /* XFoundation.framework */; }; + 69DA26BB2007AC190044FA53 /* XFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B92007AC190044FA53 /* XFoundation.framework */; }; + 69DA26BC2007AC190044FA53 /* XFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B92007AC190044FA53 /* XFoundation.framework */; }; + 69DA26BE2007AC2B0044FA53 /* XProxy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26BD2007AC2B0044FA53 /* XProxy.framework */; }; + 69DA26BF2007AC2B0044FA53 /* XProxy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26BD2007AC2B0044FA53 /* XProxy.framework */; }; + 69DA26C02007AC2B0044FA53 /* XProxy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26BD2007AC2B0044FA53 /* XProxy.framework */; }; + 69DA26C12007AC800044FA53 /* XProxy.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26BD2007AC2B0044FA53 /* XProxy.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DA26C22007AC820044FA53 /* XFoundation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B92007AC190044FA53 /* XFoundation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DA26C32007AC840044FA53 /* XSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B52007AC0E0044FA53 /* XSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DA26C42007AC870044FA53 /* Xcon.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26B12007AC060044FA53 /* Xcon.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DA26C52007AC890044FA53 /* XRuler.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26AD2007ABFB0044FA53 /* XRuler.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DA26C72007ACE20044FA53 /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26C62007ACDE0044FA53 /* Reachability.framework */; }; + 69DA26C82007AD2F0044FA53 /* Reachability.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69DA26C62007ACDE0044FA53 /* Reachability.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DA64E71C2920FE00DC174C /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 578ED92D1C03181300913B2F /* PacketTunnelProvider.swift */; }; + 69DD43271DDC2D4800080CF1 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E6C1DD97BA50047112C /* SwiftyJSON.framework */; }; + 69DD43621DDC53A500080CF1 /* GRDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69ED92B61DD9AF9500D51369 /* GRDB.framework */; }; + 69DD43631DDC53A500080CF1 /* GRDB.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69ED92B61DD9AF9500D51369 /* GRDB.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DD43641DDC53AD00080CF1 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E5C1DD97B5D0047112C /* Alamofire.framework */; }; + 69DD43661DDC53C000080CF1 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E6C1DD97BA50047112C /* SwiftyJSON.framework */; }; + 69DD43671DDC53C000080CF1 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E6C1DD97BA50047112C /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DD436A1DDC540800080CF1 /* CocoaAsyncSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E601DD97B6F0047112C /* CocoaAsyncSocket.framework */; }; + 69DD436B1DDC540800080CF1 /* CocoaAsyncSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E601DD97B6F0047112C /* CocoaAsyncSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DD436C1DDC540A00080CF1 /* Crypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E641DD97B820047112C /* Crypto.framework */; }; + 69DD436D1DDC540A00080CF1 /* Crypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E641DD97B820047112C /* Crypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DD436E1DDC540C00080CF1 /* CommonCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E621DD97B780047112C /* CommonCrypto.framework */; }; + 69DD436F1DDC540C00080CF1 /* CommonCrypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E621DD97B780047112C /* CommonCrypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69DD43701DDC540E00080CF1 /* Sodium.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E6A1DD97BA00047112C /* Sodium.framework */; }; + 69DD43711DDC540E00080CF1 /* Sodium.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 69803E6A1DD97BA00047112C /* Sodium.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 69E1367F1C7047ED002BFBF2 /* StatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E1367E1C7047ED002BFBF2 /* StatViewController.swift */; }; + 69E136811C704C03002BFBF2 /* AnalyzeTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E136801C704C03002BFBF2 /* AnalyzeTableViewController.swift */; }; + 69E136831C705107002BFBF2 /* SFTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E136821C705107002BFBF2 /* SFTableViewController.swift */; }; + 69E96BCE2009ADBB0060659A /* CheckTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69E96BCD2009ADBB0060659A /* CheckTableViewController.swift */; }; + 69F1005B1E855F77008AA81D /* iCloudViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69F1005A1E855F77008AA81D /* iCloudViewController.swift */; }; + 69F5C356203045AB0075B8E0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69F5C358203045AB0075B8E0 /* InfoPlist.strings */; }; + 69F8B0E11F6222FD00CA85CE /* RuleTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694536B61C72E74800C4595D /* RuleTableViewController.swift */; }; + 69F8B0E21F62231700CA85CE /* DNSViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6964C0A81CF544570021897B /* DNSViewController.swift */; }; + 69FDC2401ED5B2D100A19081 /* RecentReqViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69FDC23F1ED5B2D100A19081 /* RecentReqViewController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 693AAE2A200EDF82009E481E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 69366E4E1BFECBE700AE123D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 693AAE24200EDF82009E481E; + remoteInfo = XDataService; + }; + 693AAE3C200EE646009E481E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 69366E4E1BFECBE700AE123D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 693AAE24200EDF82009E481E; + remoteInfo = XDataService; + }; + 696573FA1DE4959B00D95D59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 69366E4E1BFECBE700AE123D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 696573EB1DE4959B00D95D59; + remoteInfo = "Surf-Today"; + }; + 69784D621DE0A8B1007E32C2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 69366E4E1BFECBE700AE123D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 69C4EE3B1C29193D0020FBF8; + remoteInfo = "PacketTunnel-Mac"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 691883481DDD8D310051DAAE /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 697DF0801FFE0C8A00C6A64C /* SurfToday.appex in Embed App Extensions */, + 692128521E9C7AC500560DEC /* PacketTunnel-iOS.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE3E200EE646009E481E /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 693AAE48200EE6BF009E481E /* XRuler.framework in Embed Frameworks */, + 693AAE5B200EE723009E481E /* ObjectMapper.framework in Embed Frameworks */, + 693AAE46200EE6BB009E481E /* XSocket.framework in Embed Frameworks */, + 693AAE67200EE736009E481E /* Crypto.framework in Embed Frameworks */, + 6907E9CC20117FE600E7B1FE /* Sparkle.framework in Embed Frameworks */, + 693AAE44200EE6B9009E481E /* XFoundation.framework in Embed Frameworks */, + 693AAE3B200EE646009E481E /* XDataService.framework in Embed Frameworks */, + 693AAE71200EE747009E481E /* SwiftyJSON.framework in Embed Frameworks */, + 693AAE42200EE6B6009E481E /* XProxy.framework in Embed Frameworks */, + 693AAE59200EE71E009E481E /* snappy.framework in Embed Frameworks */, + 693AAE5F200EE729009E481E /* kcp.framework in Embed Frameworks */, + 693AAE40200EE6B3009E481E /* Reachability.framework in Embed Frameworks */, + 693AAE6F200EE744009E481E /* Sodium.framework in Embed Frameworks */, + 693AAE6D200EE742009E481E /* MMDB.framework in Embed Frameworks */, + 693AAE6B200EE73B009E481E /* lwip.framework in Embed Frameworks */, + 693AAE5D200EE727009E481E /* GRDB.framework in Embed Frameworks */, + 693AAE61200EE72D009E481E /* AxLogger.framework in Embed Frameworks */, + 693AAE65200EE733009E481E /* CommonCrypto.framework in Embed Frameworks */, + 693AAE73200EE749009E481E /* SystemKit.framework in Embed Frameworks */, + 693AAE63200EE730009E481E /* CocoaAsyncSocket.framework in Embed Frameworks */, + 693AAE57200EE71A009E481E /* SFSocket.framework in Embed Frameworks */, + 693AAE69200EE739009E481E /* DarwinCore.framework in Embed Frameworks */, + 693AAE53200EE710009E481E /* Xcon.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 69AFBA571DDC23BD00409CD4 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 69DD436D1DDC540A00080CF1 /* Crypto.framework in Embed Frameworks */, + 690AB8811E9764F6001A6C3A /* Alamofire.framework in Embed Frameworks */, + 69DD43631DDC53A500080CF1 /* GRDB.framework in Embed Frameworks */, + 6906B76A1EF36B9C00CA66CA /* Charts.framework in Embed Frameworks */, + 690AB87F1E9764F1001A6C3A /* AxLogger.framework in Embed Frameworks */, + 69348F451FFB7234007C841C /* XSocket.framework in Embed Frameworks */, + 69DD436B1DDC540800080CF1 /* CocoaAsyncSocket.framework in Embed Frameworks */, + 69348F431FFB7234007C841C /* XRuler.framework in Embed Frameworks */, + 69348F3F1FFB7234007C841C /* Xcon.framework in Embed Frameworks */, + 69852BE91F33010A00EBFC92 /* IoniconsSwift.framework in Embed Frameworks */, + 69DD43671DDC53C000080CF1 /* SwiftyJSON.framework in Embed Frameworks */, + 6906B76E1EF36BA600CA66CA /* SwiftyStoreKit.framework in Embed Frameworks */, + 69639BCF1EE179B400893D18 /* kcp.framework in Embed Frameworks */, + 69D411B01E975DC30095E683 /* Reachability.framework in Embed Frameworks */, + 69AD9CCA200354B400C01011 /* XFoundation.framework in Embed Frameworks */, + 69852BEB1F3313FE00EBFC92 /* SystemKitiOS.framework in Embed Frameworks */, + 69348F411FFB7234007C841C /* XProxy.framework in Embed Frameworks */, + 691883501DDDA03C0051DAAE /* lwip.framework in Embed Frameworks */, + 690AB8881E976534001A6C3A /* ObjectMapper.framework in Embed Frameworks */, + 6906B75D1EF2728200CA66CA /* SFSocket.framework in Embed Frameworks */, + 69303FCB1ECA99940089AFFA /* snappy.framework in Embed Frameworks */, + 69DD43711DDC540E00080CF1 /* Sodium.framework in Embed Frameworks */, + 69D411AF1E975D760095E683 /* IDZSwiftCommonCrypto.framework in Embed Frameworks */, + 69DD436F1DDC540C00080CF1 /* CommonCrypto.framework in Embed Frameworks */, + 6994E01F1DEFCA37009394F9 /* MMDB.framework in Embed Frameworks */, + 69639BC91EE1637100893D18 /* DarwinCore.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE491C29193D0020FBF8 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 69B5413F1F207939007D4A4E /* A.BIG.T-Today.appex in Embed App Extensions */, + 69B5413E1F207931007D4A4E /* PacketTunnel-Mac.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 69DA64DE1C291FD300DC174C /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 692806361EFA7E7C007FCF6A /* SFSocket.framework in Embed Frameworks */, + 69784D541DE0A7F6007E32C2 /* Alamofire.framework in Embed Frameworks */, + 69BCD7771EE1CA3400A8A19C /* kcp.framework in Embed Frameworks */, + 69784D591DE0A80A007E32C2 /* DarwinCore.framework in Embed Frameworks */, + 69784D5E1DE0A818007E32C2 /* Sodium.framework in Embed Frameworks */, + 69DA26C32007AC840044FA53 /* XSocket.framework in Embed Frameworks */, + 69BCD7791EE1CA5300A8A19C /* SystemKit.framework in Embed Frameworks */, + 69DA26C12007AC800044FA53 /* XProxy.framework in Embed Frameworks */, + 69DA26C52007AC890044FA53 /* XRuler.framework in Embed Frameworks */, + 69DA26C42007AC870044FA53 /* Xcon.framework in Embed Frameworks */, + 69DA26C22007AC820044FA53 /* XFoundation.framework in Embed Frameworks */, + 69784D581DE0A808007E32C2 /* Crypto.framework in Embed Frameworks */, + 69DA26C82007AD2F0044FA53 /* Reachability.framework in Embed Frameworks */, + 69BCD77B1EE1CA7700A8A19C /* AxLogger.framework in Embed Frameworks */, + 694397BB1E5C38170009AD0E /* GRDB.framework in Embed Frameworks */, + 69784D5F1DE0A81A007E32C2 /* SwiftyJSON.framework in Embed Frameworks */, + 69263EF31EE504BA005F0C76 /* snappy.framework in Embed Frameworks */, + 69784D5C1DE0A811007E32C2 /* MMDB.framework in Embed Frameworks */, + 69784D5B1DE0A80F007E32C2 /* lwip.framework in Embed Frameworks */, + 693AAE2D200EDF82009E481E /* XDataService.framework in Embed Frameworks */, + 69784D571DE0A7FD007E32C2 /* CommonCrypto.framework in Embed Frameworks */, + 69BCD7801EE469FB00A8A19C /* ObjectMapper.framework in Embed Frameworks */, + 69784D561DE0A7FB007E32C2 /* CocoaAsyncSocket.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 5756A9581BFF1DA4006C08BB /* AddEditProxyController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AddEditProxyController.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 5756A95A1C02C321006C08BB /* TextFieldCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldCell.swift; sourceTree = ""; }; + 578ED9291C03181200913B2F /* PacketTunnel-iOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "PacketTunnel-iOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 578ED92D1C03181300913B2F /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = PacketTunnelProvider.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 6903CDD520159D1100642B68 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = iosLib/Crashlytics.framework; sourceTree = ""; }; + 6904E8151CAE197000179E81 /* ProxyGroupViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxyGroupViewController.swift; sourceTree = ""; }; + 6904E8171CAE653E00179E81 /* ProxyCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxyCell.swift; sourceTree = ""; }; + 6906B7601EF280B400CA66CA /* SFVerify.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFVerify.swift; sourceTree = ""; }; + 6906B7651EF36B5B00CA66CA /* SwiftyStoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyStoreKit.framework; path = Carthage/Build/iOS/SwiftyStoreKit.framework; sourceTree = ""; }; + 6906B7671EF36B6700CA66CA /* Charts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Charts.framework; path = Carthage/Build/iOS/Charts.framework; sourceTree = ""; }; + 6906B9001DE1954700A60B66 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/NetworkExtension.framework; sourceTree = DEVELOPER_DIR; }; + 6906B90B1DE29D8F00A60B66 /* Config.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Config.storyboard; sourceTree = ""; }; + 6906B90D1DE29F8300A60B66 /* ConfigWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigWindowController.swift; sourceTree = ""; }; + 6906B9131DE2A2D600A60B66 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + 6906B9161DE2A6E300A60B66 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = ""; }; + 6906B9181DE2A6EC00A60B66 /* PreferencesWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreferencesWindowController.xib; sourceTree = ""; }; + 6906B91A1DE2B8BA00A60B66 /* StatusView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = ""; }; + 69075CAF1D3D0F68008D1770 /* DebugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugViewController.swift; sourceTree = ""; }; + 6907E9C020102B1900E7B1FE /* HelpWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HelpWindow.xib; sourceTree = ""; }; + 6907E9C220102BC400E7B1FE /* HelpWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpWindowController.swift; sourceTree = ""; }; + 6907E9C620104ECC00E7B1FE /* RequestDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestDetailView.swift; sourceTree = ""; }; + 6907E9C82010508900E7B1FE /* RequestTabVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestTabVC.swift; sourceTree = ""; }; + 6907E9CA201178A900E7B1FE /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = maclab/Sparkle.framework; sourceTree = SOURCE_ROOT; }; + 6907E9CD201180DB00E7B1FE /* UpdateWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateWindowController.swift; sourceTree = ""; }; + 6907E9D12011815100E7B1FE /* SUUpdateSettingsWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SUUpdateSettingsWindowController.xib; sourceTree = ""; }; + 6907E9D32011959E00E7B1FE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 690AB8841E97652F001A6C3A /* ObjectMapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectMapper.framework; path = Carthage/Build/iOS/ObjectMapper.framework; sourceTree = ""; }; + 690C64CF1D66BB9F00FB9BA7 /* SFactivity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFactivity.swift; sourceTree = ""; }; + 690C64D21D67670B00FB9BA7 /* SFConfigManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFConfigManager.swift; sourceTree = ""; }; + 690C77C01CF42FF100EB1610 /* Default.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Default.conf; sourceTree = ""; }; + 690FEFFF1C64546B005F1095 /* SFDocumentPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFDocumentPickerViewController.swift; sourceTree = ""; }; + 69100F631CB5FFD10023F88F /* image.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = image.xcassets; sourceTree = ""; }; + 691462AE1D6D3C44007992F2 /* SFMethodViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFMethodViewController.swift; sourceTree = ""; }; + 691462B01D6D3C5D007992F2 /* SSMethod.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SSMethod.storyboard; sourceTree = ""; }; + 6916AB581CDB9DB200C2FC48 /* rules_public.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules_public.conf; sourceTree = ""; }; + 6916AB931CDE600100C2FC48 /* SFRuleWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFRuleWriter.swift; sourceTree = ""; }; + 6918834E1DDDA0280051DAAE /* lwip.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = lwip.framework; path = Carthage/Build/iOS/lwip.framework; sourceTree = ""; }; + 691B366C1C0F4BAE001C815D /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; + 6920758A1CE77C12000F1ED9 /* HostsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HostsTableViewController.swift; sourceTree = ""; }; + 6920758C1CE77C29000F1ED9 /* HostEditTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HostEditTableViewController.swift; sourceTree = ""; }; + 69263EEB1EE50491005F0C76 /* snappy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = snappy.framework; path = Carthage/Build/Mac/snappy.framework; sourceTree = ""; }; + 69263EF81EE50C5B005F0C76 /* SFSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SFSocket.framework; path = Carthage/Build/Mac/SFSocket.framework; sourceTree = ""; }; + 6927ADA51DE0B6010027EF7A /* PacketTunnel_Mac-Swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PacketTunnel_Mac-Swift.h"; path = "Mac/PacketTunnel_Mac-Swift.h"; sourceTree = ""; }; + 69290F8320302F9500780915 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = ""; }; + 6929C32F1F32EBCB007C1FA3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; + 6929C3301F32FCE0007C1FA3 /* IoniconsSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IoniconsSwift.framework; path = Carthage/Build/iOS/IoniconsSwift.framework; sourceTree = ""; }; + 692B4FF91C71646200BB793B /* RequestDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestDetailViewController.swift; sourceTree = ""; }; + 692B4FFB1C71A0E600BB793B /* SFAppIden.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFAppIden.swift; sourceTree = ""; }; + 692B4FFD1C71A11300BB793B /* useragents.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = useragents.plist; sourceTree = ""; }; + 692D8CF71C6A250400C07B3A /* SurfToday.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SurfToday.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 692D8CF91C6A250400C07B3A /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; }; + 692D8CFC1C6A250400C07B3A /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = ""; }; + 692D8CFF1C6A250400C07B3A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; + 692D8D011C6A250400C07B3A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 692D8D081C6A27FE00C07B3A /* today.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = today.entitlements; sourceTree = ""; }; + 692EF8FC1CABF05C00C9936A /* socks5.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = socks5.js; sourceTree = ""; }; + 69303FC21ECA99610089AFFA /* snappy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = snappy.framework; path = Carthage/Build/iOS/snappy.framework; sourceTree = ""; }; + 69303FCC1ECA9A8E0089AFFA /* KcpTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KcpTableViewController.swift; sourceTree = ""; }; + 69348F311FFB713E007C841C /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = iosLib/Fabric.framework; sourceTree = ""; }; + 69348F361FFB7211007C841C /* XProxy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XProxy.framework; path = Carthage/Build/iOS/XProxy.framework; sourceTree = ""; }; + 69348F371FFB7212007C841C /* Xcon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Xcon.framework; path = Carthage/Build/iOS/Xcon.framework; sourceTree = ""; }; + 69348F381FFB7213007C841C /* XRuler.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XRuler.framework; path = Carthage/Build/iOS/XRuler.framework; sourceTree = ""; }; + 69348F391FFB7213007C841C /* XSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XSocket.framework; path = Carthage/Build/iOS/XSocket.framework; sourceTree = ""; }; + 69366E561BFECBE700AE123D /* Surf.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Surf.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 69366E591BFECBE700AE123D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 69366E5B1BFECBE700AE123D /* SFConfigViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SFConfigViewController.swift; sourceTree = ""; }; + 69366E5D1BFECBE700AE123D /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = ""; }; + 69366E601BFECBE700AE123D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 69366E621BFECBE700AE123D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 69366E671BFECBE700AE123D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6936B4D61C4D304C000EBF70 /* ISO_3166.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ISO_3166.txt; sourceTree = ""; }; + 693766B91DFE8F7C0015C549 /* QRView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRView.swift; sourceTree = ""; }; + 693AAE0E200EDA4E009E481E /* Kwazii.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Kwazii.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 693AAE10200EDA4E009E481E /* KwaziiAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KwaziiAppDelegate.swift; sourceTree = ""; }; + 693AAE12200EDA4F009E481E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 693AAE17200EDA4F009E481E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 693AAE19200EDA4F009E481E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 693AAE1A200EDA4F009E481E /* Kwazii.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Kwazii.entitlements; sourceTree = ""; }; + 693AAE1E200EDF1A009E481E /* RequestsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestsVC.swift; sourceTree = ""; }; + 693AAE25200EDF82009E481E /* XDataService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XDataService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 693AAE27200EDF82009E481E /* XDataService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XDataService.h; sourceTree = ""; }; + 693AAE28200EDF82009E481E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 693AAE31200EDFA5009E481E /* RequestsBasic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestsBasic.swift; sourceTree = ""; }; + 693AAE37200EE255009E481E /* xdatamac.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = xdatamac.xcconfig; sourceTree = ""; }; + 693AAE38200EE3D3009E481E /* RequestBasic.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = RequestBasic.storyboard; sourceTree = ""; }; + 693AAE75200EE9A0009E481E /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = NetworkExtension.framework; sourceTree = ""; }; + 693AAE76200EEA3C009E481E /* MainWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindow.swift; sourceTree = ""; }; + 693AAE78200EED15009E481E /* RequestBasic.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RequestBasic.xib; sourceTree = ""; }; + 693AAE7B200EF7F3009E481E /* abigt.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = abigt.conf; sourceTree = ""; }; + 693B603C1C479F2A00173D0B /* thanks.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = thanks.txt; sourceTree = ""; }; + 693B603E1C48867500173D0B /* const.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = const.swift; sourceTree = ""; }; + 693B74491ED9FA69004C6E87 /* SFSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SFSocket.framework; path = Carthage/Build/iOS/SFSocket.framework; sourceTree = ""; }; + 693B744D1ED9FA7A004C6E87 /* kcp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = kcp.framework; path = Carthage/Build/iOS/kcp.framework; sourceTree = ""; }; + 693DBDFC1C9690F30067595C /* config.pac.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = config.pac.js; sourceTree = ""; }; + 693DBDFE1C96977A0067595C /* SFCountry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFCountry.swift; sourceTree = ""; }; + 693DBE011C969C610067595C /* data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = data.json; sourceTree = ""; }; + 69421BDF1C4CD90300021649 /* ConfigTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigTableViewController.swift; sourceTree = ""; }; + 69421BE11C4CE6B100021649 /* iTunesFileTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iTunesFileTableViewController.swift; sourceTree = ""; }; + 694397B31E5C10B10009AD0E /* SFNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFNavigationController.swift; sourceTree = ""; }; + 694397B51E5C16470009AD0E /* SFTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFTableViewCell.swift; sourceTree = ""; }; + 694397B71E5C37FE0009AD0E /* GRDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GRDB.framework; path = Carthage/Build/Mac/GRDB.framework; sourceTree = ""; }; + 694492301C568E4F00DD75CA /* RulesTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RulesTableViewController.swift; sourceTree = ""; }; + 694536B61C72E74800C4595D /* RuleTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuleTableViewController.swift; sourceTree = ""; }; + 694536B81C730DFE00C4595D /* PolicyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PolicyViewController.swift; sourceTree = ""; }; + 6946FAF11CB6330C00A8586E /* .adblock */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .adblock; path = iOS/.adblock; sourceTree = ""; }; + 6947D7711CE4CE5E0020BBCB /* Surf-Mac.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Surf-Mac.xcconfig"; sourceTree = ""; }; + 6947D7731CE4D0050020BBCB /* A_BIG_T-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "A_BIG_T-Bridging-Header.h"; sourceTree = ""; }; + 6948C96E1C59C3B50057774A /* Surf-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Surf-iOS.xcconfig"; sourceTree = ""; }; + 69524B041D2E091C00FA4DC7 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 69524B071D2E0AD900FA4DC7 /* SurfToday-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SurfToday-Bridging-Header.h"; sourceTree = ""; }; + 6952BAE81DF92F9D00DAD397 /* QrWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QrWindowController.swift; sourceTree = ""; }; + 6952BAF01DF9529700DAD397 /* QrController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QrController.swift; sourceTree = ""; }; + 6957A2D41F04D27700B54B90 /* ChartsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartsView.swift; sourceTree = ""; }; + 695987951C15894C003E1DDC /* LogFileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogFileViewController.swift; sourceTree = ""; }; + 6959879A1C159480003E1DDC /* Surf-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Surf-Bridging-Header.h"; sourceTree = ""; }; + 695BBDD81C64823900879ABB /* SFVPNManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFVPNManager.swift; sourceTree = ""; }; + 695EA9AD1E81069000D594CC /* HistoryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryViewController.swift; sourceTree = ""; }; + 69639BC61EE1636700893D18 /* DarwinCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarwinCore.framework; path = Carthage/Build/iOS/DarwinCore.framework; sourceTree = ""; }; + 69639C231EE1C34400893D18 /* kcp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = kcp.framework; path = Carthage/Build/Mac/kcp.framework; sourceTree = ""; }; + 6964C0A81CF544570021897B /* DNSViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DNSViewController.swift; sourceTree = ""; }; + 6964C0B21CF5931A0021897B /* surf.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = surf.conf; sourceTree = ""; }; + 6964C0B41CF5AC130021897B /* TitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleView.swift; sourceTree = ""; }; + 696573D01DE48EBF00D95D59 /* AdvancedWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedWindowController.swift; sourceTree = ""; }; + 696573D11DE48EBF00D95D59 /* AdvancedWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AdvancedWindowController.xib; sourceTree = ""; }; + 696573EC1DE4959B00D95D59 /* A.BIG.T-Today.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "A.BIG.T-Today.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 696573F01DE4959B00D95D59 /* Surf_Today.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Surf_Today.entitlements; sourceTree = ""; }; + 696573F11DE4959B00D95D59 /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = ""; }; + 696573F41DE4959B00D95D59 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TodayViewController.xib; sourceTree = ""; }; + 696573F61DE4959B00D95D59 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 696573F81DE4959B00D95D59 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 696574051DE499FC00D95D59 /* Surf_Today.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Surf_Today.entitlements; sourceTree = ""; }; + 6965AA751C56056C00F38B8D /* TwoLableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoLableCell.swift; sourceTree = ""; }; + 6965AA781C56070600F38B8D /* LoglevelTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoglevelTableViewController.swift; sourceTree = ""; }; + 696702131CFBE6A8008D36C8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 69673C491F32D41E0003AB6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + 69673C4B1F32D4210003AB6C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 69673C4D1F32D6A00003AB6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/help.storyboard; sourceTree = ""; }; + 69673C501F32D6A30003AB6C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/help.strings"; sourceTree = ""; }; + 696847771D504E87005E17C2 /* SFAppExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFAppExtension.swift; sourceTree = ""; }; + 696DD2D91C7B132E00C34416 /* OndemandController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OndemandController.swift; sourceTree = ""; }; + 696E33991C99479C0075B635 /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = share/lib/libcrypto.a; sourceTree = ""; }; + 696E339A1C99479C0075B635 /* libsodium.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsodium.a; path = share/lib/libsodium.a; sourceTree = ""; }; + 696E73AB1C44982400DF9A39 /* PacketTunnel-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "PacketTunnel-iOS.xcconfig"; path = "iOS/PacketTunnel-iOS.xcconfig"; sourceTree = ""; }; + 696E73B31C44CEEA00DF9A39 /* DataShare.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataShare.swift; sourceTree = ""; }; + 696E73B41C44CEEA00DF9A39 /* Socks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Socks.swift; sourceTree = ""; }; + 696E73B81C44E59D00DF9A39 /* LogListTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogListTableViewController.swift; sourceTree = ""; }; + 696E73BC1C463F9500DF9A39 /* Surf.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Surf.entitlements; sourceTree = ""; }; + 69707AEE1EF37F2C00C7BD9D /* NetworkActivityIndicatorManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkActivityIndicatorManager.swift; sourceTree = ""; }; + 69707AEF1EF37F2C00C7BD9D /* BuyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BuyViewController.swift; sourceTree = ""; }; + 69707AF21EF37F5D00C7BD9D /* buy.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = buy.storyboard; sourceTree = ""; }; + 6970CDD91CE46701009850DE /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 697165FE1F395BEE002B13A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Main.strings; sourceTree = ""; }; + 6971C0DC1D51E83A00CC75BF /* FlyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlyViewController.swift; sourceTree = ""; }; + 6971C0DE1D51E87000CC75BF /* PlaneView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaneView.swift; sourceTree = ""; }; + 69746FCE1C1A80E500CA44BE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6975F1311F32CFBF00F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + 6975F1321F32CFBF00F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; + 6975F1331F32CFBF00F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + 6975F1351F32CFBF00F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainInterface.strings"; sourceTree = ""; }; + 6975F1371F32CFC000F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/TodayViewController.strings"; sourceTree = ""; }; + 6975F1381F32CFC000F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; + 6975F13C1F32D18300F7674C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/ana.storyboard; sourceTree = ""; }; + 6975F13E1F32D19400F7674C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ana.strings; sourceTree = ""; }; + 6975F13F1F32D1A200F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/ana.strings"; sourceTree = ""; }; + 6975F1451F32D2F100F7674C /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = ""; }; + 6975F1471F32D2F500F7674C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; + 697770471C7ADBE700C552BF /* CountrySelectController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountrySelectController.swift; sourceTree = ""; }; + 69784D3A1DE0A467007E32C2 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/Mac/Alamofire.framework; sourceTree = ""; }; + 69784D3B1DE0A467007E32C2 /* AxLogger.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AxLogger.framework; path = Carthage/Build/Mac/AxLogger.framework; sourceTree = ""; }; + 69784D3C1DE0A467007E32C2 /* CocoaAsyncSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaAsyncSocket.framework; path = Carthage/Build/Mac/CocoaAsyncSocket.framework; sourceTree = ""; }; + 69784D3D1DE0A467007E32C2 /* CommonCrypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CommonCrypto.framework; path = Carthage/Build/Mac/CommonCrypto.framework; sourceTree = ""; }; + 69784D3E1DE0A467007E32C2 /* Crypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crypto.framework; path = Carthage/Build/Mac/Crypto.framework; sourceTree = ""; }; + 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarwinCore.framework; path = Carthage/Build/Mac/DarwinCore.framework; sourceTree = ""; }; + 69784D411DE0A467007E32C2 /* lwip.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = lwip.framework; path = Carthage/Build/Mac/lwip.framework; sourceTree = ""; }; + 69784D421DE0A467007E32C2 /* MMDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MMDB.framework; path = Carthage/Build/Mac/MMDB.framework; sourceTree = ""; }; + 69784D441DE0A467007E32C2 /* Sodium.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sodium.framework; path = Carthage/Build/Mac/Sodium.framework; sourceTree = ""; }; + 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/Mac/SwiftyJSON.framework; sourceTree = ""; }; + 69784D461DE0A467007E32C2 /* SystemKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemKit.framework; path = Carthage/Build/Mac/SystemKit.framework; sourceTree = ""; }; + 697B7C3D1DDF41F400584179 /* MMDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MMDB.framework; path = Carthage/Build/iOS/MMDB.framework; sourceTree = ""; }; + 69801C95200D947400A214D6 /* BarChatsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarChatsCell.swift; sourceTree = ""; }; + 69803E5C1DD97B5D0047112C /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; }; + 69803E5E1DD97B640047112C /* AxLogger.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AxLogger.framework; path = Carthage/Build/iOS/AxLogger.framework; sourceTree = ""; }; + 69803E601DD97B6F0047112C /* CocoaAsyncSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaAsyncSocket.framework; path = Carthage/Build/iOS/CocoaAsyncSocket.framework; sourceTree = ""; }; + 69803E621DD97B780047112C /* CommonCrypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CommonCrypto.framework; path = Carthage/Build/iOS/CommonCrypto.framework; sourceTree = ""; }; + 69803E641DD97B820047112C /* Crypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crypto.framework; path = Carthage/Build/iOS/Crypto.framework; sourceTree = ""; }; + 69803E6A1DD97BA00047112C /* Sodium.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sodium.framework; path = Carthage/Build/iOS/Sodium.framework; sourceTree = ""; }; + 69803E6C1DD97BA50047112C /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/iOS/SwiftyJSON.framework; sourceTree = ""; }; + 6983C0C31DF4F5B600100E70 /* About.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = About.xib; sourceTree = ""; }; + 6983C0C51DF4F61500100E70 /* AboutWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutWindowController.swift; sourceTree = ""; }; + 6983C0E41DF4FED300100E70 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; + 698705781C0FD46500783358 /* BarcodeScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarcodeScanViewController.swift; sourceTree = ""; }; + 6987057D1C0FE8A200783358 /* HelpTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelpTableViewController.swift; sourceTree = ""; }; + 6987057F1C0FE8F300783358 /* AcknowledgeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AcknowledgeViewController.swift; sourceTree = ""; }; + 6989AC011C312A3400DD1435 /* StackHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackHelper.h; sourceTree = ""; }; + 6989AC021C312A3400DD1435 /* StackHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StackHelper.m; sourceTree = ""; }; + 698BFE201C3A205A00CED9EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Mac/Info.plist; sourceTree = ""; }; + 698BFE211C3A206300CED9EC /* PacketTunnel_Mac.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = PacketTunnel_Mac.entitlements; path = Mac/PacketTunnel_Mac.entitlements; sourceTree = ""; }; + 698BFE231C3A209700CED9EC /* PacketTunnel-Mac-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PacketTunnel-Mac-Bridging-Header.h"; path = "Mac/PacketTunnel-Mac-Bridging-Header.h"; sourceTree = ""; }; + 698BFE251C3A20FC00CED9EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = ""; }; + 698BFE261C3A20FC00CED9EC /* PacketTunnel-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PacketTunnel-Bridging-Header.h"; path = "iOS/PacketTunnel-Bridging-Header.h"; sourceTree = ""; }; + 698BFE271C3A20FC00CED9EC /* PacketTunnel-Swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PacketTunnel-Swift.h"; path = "iOS/PacketTunnel-Swift.h"; sourceTree = ""; }; + 698BFE281C3A20FC00CED9EC /* PacketTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = PacketTunnel.entitlements; path = iOS/PacketTunnel.entitlements; sourceTree = ""; }; + 698BFE291C3A218000CED9EC /* PacketTunnel-Mac.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "PacketTunnel-Mac.xcconfig"; sourceTree = ""; }; + 699C8F551D79B2D300064802 /* SFViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFViewController.swift; sourceTree = ""; }; + 69A090071C4C83650064D361 /* SampleCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleCell.swift; sourceTree = ""; }; + 69A0900A1C4C851C0064D361 /* SFWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFWebViewController.swift; sourceTree = ""; }; + 69A0900C1C4C8CCC0064D361 /* config.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = config.html; sourceTree = ""; }; + 69A4ACE31D2E37C7008963FB /* WidgetSelectViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WidgetSelectViewController.swift; sourceTree = ""; }; + 69A742DA1CA15CA90000ABA1 /* libmbedcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedcrypto.a; path = share/lib/libmbedcrypto.a; sourceTree = ""; }; + 69A99E4B1C6A2E96009EC4C5 /* SFLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFLog.swift; sourceTree = ""; }; + 69A9FE4B1CC5C0CF00D5DB41 /* ionicons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ionicons.ttf; sourceTree = ""; }; + 69AD9CC7200354A100C01011 /* XFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XFoundation.framework; path = Carthage/Build/iOS/XFoundation.framework; sourceTree = ""; }; + 69B3D9801D2DFFFC00E1626C /* SFInterfaceTraffic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SFInterfaceTraffic.swift; path = ../Surf/SFInterfaceTraffic.swift; sourceTree = ""; }; + 69BBD6421CD9C8A500DB8CBC /* SFRuleHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFRuleHelper.swift; sourceTree = ""; }; + 69BCD77D1EE469D100A8A19C /* ObjectMapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectMapper.framework; path = Carthage/Build/Mac/ObjectMapper.framework; sourceTree = ""; }; + 69BD54C41E975C88008F10DC /* Reachability.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reachability.framework; path = Carthage/Build/iOS/Reachability.framework; sourceTree = ""; }; + 69BD736B1DB4B3740078EB02 /* imageView.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = imageView.storyboard; sourceTree = ""; }; + 69BD736C1DB4B3740078EB02 /* ImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageViewController.swift; sourceTree = ""; }; + 69BE2E681FFC704C0078845A /* ENV.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENV.swift; sourceTree = ""; }; + 69BEFA2A1C7D84240066118E /* SwitchCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchCell.swift; sourceTree = ""; }; + 69BF6C6A1DE68985000ABF09 /* StatCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatCell.swift; sourceTree = ""; }; + 69BF6C6C1DE6D742000ABF09 /* RequestsWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RequestsWindowController.swift; path = "../Surf-Today/RequestsWindowController.swift"; sourceTree = ""; }; + 69BF6C6D1DE6D742000ABF09 /* RequestsWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = RequestsWindowController.xib; path = "../Surf-Today/RequestsWindowController.xib"; sourceTree = ""; }; + 69BFCCD71DE34C8A00469B8C /* SWBQRCodeWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SWBQRCodeWindowController.swift; sourceTree = ""; }; + 69BFCCDB1DE34D1200469B8C /* QRCodeWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = QRCodeWindow.xib; sourceTree = ""; }; + 69BFCCE11DE34D7800469B8C /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; }; + 69BFCCE31DE3543200469B8C /* libswiftCoreImage.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftCoreImage.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/PrivateFrameworks/Swift/libswiftCoreImage.tbd; sourceTree = DEVELOPER_DIR; }; + 69C4EE291C2919010020FBF8 /* A.BIG.T.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = A.BIG.T.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 69C4EE2B1C2919010020FBF8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 69C4EE2D1C2919010020FBF8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 69C4EE2F1C2919010020FBF8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 69C4EE321C2919010020FBF8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 69C4EE341C2919010020FBF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 69C4EE3C1C29193D0020FBF8 /* PacketTunnel-Mac.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "PacketTunnel-Mac.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 69C9B0D81D3F50490089BC82 /* ConfigEditViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigEditViewController.swift; sourceTree = ""; }; + 69D18ED21DE7E35F006264F9 /* SFApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFApplication.swift; sourceTree = ""; }; + 69D18ED61DE9C0FB006264F9 /* SFMono-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SFMono-Regular.otf"; sourceTree = ""; }; + 69D411AC1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDZSwiftCommonCrypto.framework; path = Carthage/Build/iOS/IDZSwiftCommonCrypto.framework; sourceTree = ""; }; + 69DA26A42007A96A0044FA53 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = maclab/Crashlytics.framework; sourceTree = ""; }; + 69DA26A52007A96A0044FA53 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = maclab/Fabric.framework; sourceTree = ""; }; + 69DA26AD2007ABFB0044FA53 /* XRuler.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XRuler.framework; path = Carthage/Build/Mac/XRuler.framework; sourceTree = ""; }; + 69DA26B12007AC060044FA53 /* Xcon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Xcon.framework; path = Carthage/Build/Mac/Xcon.framework; sourceTree = ""; }; + 69DA26B52007AC0E0044FA53 /* XSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XSocket.framework; path = Carthage/Build/Mac/XSocket.framework; sourceTree = ""; }; + 69DA26B92007AC190044FA53 /* XFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XFoundation.framework; path = Carthage/Build/Mac/XFoundation.framework; sourceTree = ""; }; + 69DA26BD2007AC2B0044FA53 /* XProxy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XProxy.framework; path = Carthage/Build/Mac/XProxy.framework; sourceTree = ""; }; + 69DA26C62007ACDE0044FA53 /* Reachability.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reachability.framework; path = Carthage/Build/Mac/Reachability.framework; sourceTree = ""; }; + 69DA64C71C291E1B00DC174C /* Surf-Mac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Surf-Mac.entitlements"; sourceTree = ""; }; + 69DD43541DDC4DD500080CF1 /* SystemKitiOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemKitiOS.framework; path = Carthage/Build/iOS/SystemKitiOS.framework; sourceTree = ""; }; + 69E1367C1C704773002BFBF2 /* RuleResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RuleResultsViewController.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 69E1367E1C7047ED002BFBF2 /* StatViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatViewController.swift; sourceTree = ""; }; + 69E136801C704C03002BFBF2 /* AnalyzeTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyzeTableViewController.swift; sourceTree = ""; }; + 69E136821C705107002BFBF2 /* SFTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SFTableViewController.swift; sourceTree = ""; }; + 69E96BCD2009ADBB0060659A /* CheckTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckTableViewController.swift; sourceTree = ""; }; + 69ED92B61DD9AF9500D51369 /* GRDB.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GRDB.framework; path = Carthage/Build/iOS/GRDB.framework; sourceTree = ""; }; + 69F1005A1E855F77008AA81D /* iCloudViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iCloudViewController.swift; sourceTree = ""; }; + 69F5C357203045AB0075B8E0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 69F5C359203045AE0075B8E0 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; + 69F698E91DDC21ED00966272 /* DarwinCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarwinCore.framework; path = Carthage/Build/iOS/DarwinCore.framework; sourceTree = ""; }; + 69FDC23F1ED5B2D100A19081 /* RecentReqViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentReqViewController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 578ED9261C03181200913B2F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 690AB8861E97652F001A6C3A /* ObjectMapper.framework in Frameworks */, + 6903CDD820159D2400642B68 /* Crashlytics.framework in Frameworks */, + 697B7C3F1DDF41F400584179 /* MMDB.framework in Frameworks */, + 693B744B1ED9FA69004C6E87 /* SFSocket.framework in Frameworks */, + 69D411AE1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework in Frameworks */, + 69BD54C61E975C88008F10DC /* Reachability.framework in Frameworks */, + 69348F351FFB7150007C841C /* Fabric.framework in Frameworks */, + 6970CDDB1CE46710009850DE /* Security.framework in Frameworks */, + 691B366D1C0F4BAE001C815D /* libresolv.tbd in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 692D8CF41C6A250400C07B3A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 697DF0821FFE0D0500C6A64C /* Fabric.framework in Frameworks */, + 69743A0B202C96E2003A0CE6 /* Charts.framework in Frameworks */, + 69524B051D2E091C00FA4DC7 /* CFNetwork.framework in Frameworks */, + 69DD43271DDC2D4800080CF1 /* SwiftyJSON.framework in Frameworks */, + 693B744C1ED9FA69004C6E87 /* SFSocket.framework in Frameworks */, + 69524B031D2E08F100FA4DC7 /* SystemConfiguration.framework in Frameworks */, + 692D8CFA1C6A250400C07B3A /* NotificationCenter.framework in Frameworks */, + 6903CDD720159D2100642B68 /* Crashlytics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69366E531BFECBE700AE123D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 69AD9CC9200354B400C01011 /* XFoundation.framework in Frameworks */, + 69348F421FFB7234007C841C /* XRuler.framework in Frameworks */, + 69075CC71D3D157E008D1770 /* libresolv.tbd in Frameworks */, + 69DD43641DDC53AD00080CF1 /* Alamofire.framework in Frameworks */, + 69852BE81F33010A00EBFC92 /* IoniconsSwift.framework in Frameworks */, + 6906B75C1EF2728200CA66CA /* SFSocket.framework in Frameworks */, + 69DD43621DDC53A500080CF1 /* GRDB.framework in Frameworks */, + 69303FC31ECA99620089AFFA /* snappy.framework in Frameworks */, + 6906B7661EF36B5B00CA66CA /* SwiftyStoreKit.framework in Frameworks */, + 696702141CFBE6A8008D36C8 /* SystemConfiguration.framework in Frameworks */, + 690AB8761E9764A9001A6C3A /* MMDB.framework in Frameworks */, + 690AB8851E97652F001A6C3A /* ObjectMapper.framework in Frameworks */, + 69852BEA1F3313FE00EBFC92 /* SystemKitiOS.framework in Frameworks */, + 69639BC71EE1636700893D18 /* DarwinCore.framework in Frameworks */, + 69DD43701DDC540E00080CF1 /* Sodium.framework in Frameworks */, + 69348F3A1FFB7214007C841C /* XProxy.framework in Frameworks */, + 69DD436E1DDC540C00080CF1 /* CommonCrypto.framework in Frameworks */, + 6906B7681EF36B6700CA66CA /* Charts.framework in Frameworks */, + 69AD9CC8200354A100C01011 /* XFoundation.framework in Frameworks */, + 69348F3E1FFB7234007C841C /* Xcon.framework in Frameworks */, + 69DD436C1DDC540A00080CF1 /* Crypto.framework in Frameworks */, + 69DD43661DDC53C000080CF1 /* SwiftyJSON.framework in Frameworks */, + 69348F3D1FFB7214007C841C /* XSocket.framework in Frameworks */, + 69639BCE1EE179B400893D18 /* kcp.framework in Frameworks */, + 69DD436A1DDC540800080CF1 /* CocoaAsyncSocket.framework in Frameworks */, + 6970CDDA1CE46701009850DE /* Security.framework in Frameworks */, + 6903CDD620159D1200642B68 /* Crashlytics.framework in Frameworks */, + 69348F331FFB713F007C841C /* Fabric.framework in Frameworks */, + 69BD54C51E975C88008F10DC /* Reachability.framework in Frameworks */, + 69D411AD1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework in Frameworks */, + 690AB87E1E9764F1001A6C3A /* AxLogger.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE0B200EDA4E009E481E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 693AAE52200EE710009E481E /* Xcon.framework in Frameworks */, + 693AAE4A200EE6D6009E481E /* SFSocket.framework in Frameworks */, + 6907E9D52011AE6100E7B1FE /* Fabric.framework in Frameworks */, + 6907E9CB201178A900E7B1FE /* Sparkle.framework in Frameworks */, + 693AAE49200EE6CE009E481E /* Crashlytics.framework in Frameworks */, + 693AAE3A200EE646009E481E /* XDataService.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE21200EDF82009E481E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 696573E91DE4959B00D95D59 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 69DA26C02007AC2B0044FA53 /* XProxy.framework in Frameworks */, + 69DA26B02007ABFB0044FA53 /* XRuler.framework in Frameworks */, + 696573ED1DE4959B00D95D59 /* NotificationCenter.framework in Frameworks */, + 69DA26AB2007A96B0044FA53 /* Fabric.framework in Frameworks */, + 696574021DE4984D00D95D59 /* SwiftyJSON.framework in Frameworks */, + 69DA26A82007A96B0044FA53 /* Crashlytics.framework in Frameworks */, + 695234331E35A4350049EB94 /* DarwinCore.framework in Frameworks */, + 69DA26B82007AC0F0044FA53 /* XSocket.framework in Frameworks */, + 69DA26BC2007AC190044FA53 /* XFoundation.framework in Frameworks */, + 69DA26B42007AC070044FA53 /* Xcon.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE261C2919010020FBF8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 694397BA1E5C38170009AD0E /* GRDB.framework in Frameworks */, + 69784D521DE0A467007E32C2 /* SwiftyJSON.framework in Frameworks */, + 69DA26B62007AC0F0044FA53 /* XSocket.framework in Frameworks */, + 69DA26AE2007ABFB0044FA53 /* XRuler.framework in Frameworks */, + 69784D4F1DE0A467007E32C2 /* MMDB.framework in Frameworks */, + 69DA26A92007A96B0044FA53 /* Fabric.framework in Frameworks */, + 69784D511DE0A467007E32C2 /* Sodium.framework in Frameworks */, + 69BCD77F1EE469FB00A8A19C /* ObjectMapper.framework in Frameworks */, + 69784D4E1DE0A467007E32C2 /* lwip.framework in Frameworks */, + 69639C241EE1C34400893D18 /* kcp.framework in Frameworks */, + 6947D76D1CE4CC340020BBCB /* libresolv.tbd in Frameworks */, + 69784D491DE0A467007E32C2 /* CocoaAsyncSocket.framework in Frameworks */, + 69784D4B1DE0A467007E32C2 /* Crypto.framework in Frameworks */, + 69DA26A62007A96B0044FA53 /* Crashlytics.framework in Frameworks */, + 69784D4C1DE0A467007E32C2 /* DarwinCore.framework in Frameworks */, + 69263EF21EE504BA005F0C76 /* snappy.framework in Frameworks */, + 69784D4A1DE0A467007E32C2 /* CommonCrypto.framework in Frameworks */, + 6906B9011DE1954700A60B66 /* NetworkExtension.framework in Frameworks */, + 69BCD7781EE1CA5300A8A19C /* SystemKit.framework in Frameworks */, + 692806351EFA7E7C007FCF6A /* SFSocket.framework in Frameworks */, + 69784D471DE0A467007E32C2 /* Alamofire.framework in Frameworks */, + 693AAE2C200EDF82009E481E /* XDataService.framework in Frameworks */, + 69DA26C72007ACE20044FA53 /* Reachability.framework in Frameworks */, + 69DA26B22007AC070044FA53 /* Xcon.framework in Frameworks */, + 69DA26BE2007AC2B0044FA53 /* XProxy.framework in Frameworks */, + 69DA26BA2007AC190044FA53 /* XFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE391C29193D0020FBF8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 694397B91E5C37FE0009AD0E /* GRDB.framework in Frameworks */, + 69784D641DE0A8DE007E32C2 /* Alamofire.framework in Frameworks */, + 69784D651DE0A8DE007E32C2 /* AxLogger.framework in Frameworks */, + 69784D661DE0A8DE007E32C2 /* CocoaAsyncSocket.framework in Frameworks */, + 69263F031EE511AA005F0C76 /* SFSocket.framework in Frameworks */, + 69784D671DE0A8DE007E32C2 /* CommonCrypto.framework in Frameworks */, + 69DA26AF2007ABFB0044FA53 /* XRuler.framework in Frameworks */, + 69784D681DE0A8DE007E32C2 /* Crypto.framework in Frameworks */, + 69784D691DE0A8DE007E32C2 /* DarwinCore.framework in Frameworks */, + 69263F021EE511A3005F0C76 /* snappy.framework in Frameworks */, + 69DA26B72007AC0F0044FA53 /* XSocket.framework in Frameworks */, + 69784D6B1DE0A8DE007E32C2 /* lwip.framework in Frameworks */, + 69DA26A72007A96B0044FA53 /* Crashlytics.framework in Frameworks */, + 69784D6C1DE0A8DE007E32C2 /* MMDB.framework in Frameworks */, + 69784D6E1DE0A8DE007E32C2 /* Sodium.framework in Frameworks */, + 69DA26B32007AC070044FA53 /* Xcon.framework in Frameworks */, + 69DA26BB2007AC190044FA53 /* XFoundation.framework in Frameworks */, + 69784D6F1DE0A8DE007E32C2 /* SwiftyJSON.framework in Frameworks */, + 69DA26BF2007AC2B0044FA53 /* XProxy.framework in Frameworks */, + 6906B9031DE1955400A60B66 /* NetworkExtension.framework in Frameworks */, + 69DA26AA2007A96B0044FA53 /* Fabric.framework in Frameworks */, + 69784D701DE0A8DE007E32C2 /* SystemKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 578ED92A1C03181300913B2F /* PacketTunnel */ = { + isa = PBXGroup; + children = ( + 698BFE241C3A20E900CED9EC /* iOS */, + 698BFE1A1C3A1F1300CED9EC /* mac */, + 578ED92D1C03181300913B2F /* PacketTunnelProvider.swift */, + ); + path = PacketTunnel; + sourceTree = ""; + }; + 6904E8141CAE194F00179E81 /* proxygroup */ = { + isa = PBXGroup; + children = ( + 6904E8151CAE197000179E81 /* ProxyGroupViewController.swift */, + 691462AE1D6D3C44007992F2 /* SFMethodViewController.swift */, + 691462B01D6D3C5D007992F2 /* SSMethod.storyboard */, + 6964C0B41CF5AC130021897B /* TitleView.swift */, + 6904E8171CAE653E00179E81 /* ProxyCell.swift */, + ); + name = proxygroup; + sourceTree = ""; + }; + 690A347C1EF8D12E0063C5C4 /* inapp */ = { + isa = PBXGroup; + children = ( + 6906B7601EF280B400CA66CA /* SFVerify.swift */, + 69707AF21EF37F5D00C7BD9D /* buy.storyboard */, + 69707AEE1EF37F2C00C7BD9D /* NetworkActivityIndicatorManager.swift */, + 69707AEF1EF37F2C00C7BD9D /* BuyViewController.swift */, + ); + name = inapp; + sourceTree = ""; + }; + 691B36631C0F4ADC001C815D /* openssl */ = { + isa = PBXGroup; + children = ( + 69A742DA1CA15CA90000ABA1 /* libmbedcrypto.a */, + 696E33991C99479C0075B635 /* libcrypto.a */, + 696E339A1C99479C0075B635 /* libsodium.a */, + ); + name = openssl; + sourceTree = ""; + }; + 692D8CF81C6A250400C07B3A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 69784D351DE0A423007E32C2 /* MacFrameworks */, + 693AAE74200EE991009E481E /* ios */, + 69BFCCE31DE3543200469B8C /* libswiftCoreImage.tbd */, + 69BFCCE11DE34D7800469B8C /* WebKit.framework */, + 6906B9001DE1954700A60B66 /* NetworkExtension.framework */, + 69524B041D2E091C00FA4DC7 /* CFNetwork.framework */, + 696702131CFBE6A8008D36C8 /* SystemConfiguration.framework */, + 6970CDD91CE46701009850DE /* Security.framework */, + 692D8CF91C6A250400C07B3A /* NotificationCenter.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 692D8CFB1C6A250400C07B3A /* SurfToday */ = { + isa = PBXGroup; + children = ( + 69B3D9801D2DFFFC00E1626C /* SFInterfaceTraffic.swift */, + 692D8CFC1C6A250400C07B3A /* TodayViewController.swift */, + 692D8CFE1C6A250400C07B3A /* MainInterface.storyboard */, + 692D8D011C6A250400C07B3A /* Info.plist */, + 692D8D081C6A27FE00C07B3A /* today.entitlements */, + 69100F631CB5FFD10023F88F /* image.xcassets */, + ); + path = SurfToday; + sourceTree = ""; + }; + 69366E4D1BFECBE700AE123D = { + isa = PBXGroup; + children = ( + 691B366C1C0F4BAE001C815D /* libresolv.tbd */, + 6989AB031C312A3400DD1435 /* Shared */, + 691B36631C0F4ADC001C815D /* openssl */, + 69366E581BFECBE700AE123D /* Surf */, + 578ED92A1C03181300913B2F /* PacketTunnel */, + 69C4EE2A1C2919010020FBF8 /* Surf-Mac */, + 6989A5001C31042D00DD1435 /* TunServerUI */, + 692D8CFB1C6A250400C07B3A /* SurfToday */, + 696573EE1DE4959B00D95D59 /* Surf-Today */, + 693AAE0F200EDA4E009E481E /* Kwazii */, + 693AAE26200EDF82009E481E /* XDataService */, + 692D8CF81C6A250400C07B3A /* Frameworks */, + 69366E571BFECBE700AE123D /* Products */, + 69524B071D2E0AD900FA4DC7 /* SurfToday-Bridging-Header.h */, + ); + sourceTree = ""; + }; + 69366E571BFECBE700AE123D /* Products */ = { + isa = PBXGroup; + children = ( + 69366E561BFECBE700AE123D /* Surf.app */, + 578ED9291C03181200913B2F /* PacketTunnel-iOS.appex */, + 69C4EE291C2919010020FBF8 /* A.BIG.T.app */, + 69C4EE3C1C29193D0020FBF8 /* PacketTunnel-Mac.appex */, + 692D8CF71C6A250400C07B3A /* SurfToday.appex */, + 696573EC1DE4959B00D95D59 /* A.BIG.T-Today.appex */, + 693AAE0E200EDA4E009E481E /* Kwazii.app */, + 693AAE25200EDF82009E481E /* XDataService.framework */, + ); + name = Products; + sourceTree = ""; + }; + 69366E581BFECBE700AE123D /* Surf */ = { + isa = PBXGroup; + children = ( + 69E96BCA2009974B0060659A /* check */, + 690A347C1EF8D12E0063C5C4 /* inapp */, + 69BD736B1DB4B3740078EB02 /* imageView.storyboard */, + 69BD736C1DB4B3740078EB02 /* ImageViewController.swift */, + 69E136791C704708002BFBF2 /* analyze */, + 695BBDD71C6481F500879ABB /* vpnmanage */, + 696E73BC1C463F9500DF9A39 /* Surf.entitlements */, + 6959879A1C159480003E1DDC /* Surf-Bridging-Header.h */, + 698705811C0FFBE900783358 /* config */, + 693B603E1C48867500173D0B /* const.swift */, + 690C77C01CF42FF100EB1610 /* Default.conf */, + 6964C0B21CF5931A0021897B /* surf.conf */, + 6987057C1C0FE87A00783358 /* help */, + 69366E5F1BFECBE700AE123D /* Main.storyboard */, + 6971C0DC1D51E83A00CC75BF /* FlyViewController.swift */, + 6971C0DE1D51E87000CC75BF /* PlaneView.swift */, + 69C9B0D81D3F50490089BC82 /* ConfigEditViewController.swift */, + 69075CAF1D3D0F68008D1770 /* DebugViewController.swift */, + 69A9FE4B1CC5C0CF00D5DB41 /* ionicons.ttf */, + 693B603C1C479F2A00173D0B /* thanks.txt */, + 69746FCD1C1A80E500CA44BE /* LaunchScreen.xib */, + 69366E621BFECBE700AE123D /* Assets.xcassets */, + 6948C96E1C59C3B50057774A /* Surf-iOS.xcconfig */, + 690FEFFF1C64546B005F1095 /* SFDocumentPickerViewController.swift */, + 69E136821C705107002BFBF2 /* SFTableViewController.swift */, + 694397B31E5C10B10009AD0E /* SFNavigationController.swift */, + 69A4ACE31D2E37C7008963FB /* WidgetSelectViewController.swift */, + 699C8F551D79B2D300064802 /* SFViewController.swift */, + 69303FCC1ECA9A8E0089AFFA /* KcpTableViewController.swift */, + 69673C4A1F32D41E0003AB6C /* Localizable.strings */, + 6975F1461F32D2F100F7674C /* InfoPlist.strings */, + ); + path = Surf; + sourceTree = ""; + }; + 693AAE0F200EDA4E009E481E /* Kwazii */ = { + isa = PBXGroup; + children = ( + 693AAE7B200EF7F3009E481E /* abigt.conf */, + 693AAE10200EDA4E009E481E /* KwaziiAppDelegate.swift */, + 6907E9CA201178A900E7B1FE /* Sparkle.framework */, + 693AAE76200EEA3C009E481E /* MainWindow.swift */, + 693AAE12200EDA4F009E481E /* ViewController.swift */, + 693AAE16200EDA4F009E481E /* Main.storyboard */, + 6907E9D12011815100E7B1FE /* SUUpdateSettingsWindowController.xib */, + 6907E9CD201180DB00E7B1FE /* UpdateWindowController.swift */, + 6907E9C220102BC400E7B1FE /* HelpWindowController.swift */, + 6907E9C620104ECC00E7B1FE /* RequestDetailView.swift */, + 6907E9D32011959E00E7B1FE /* Assets.xcassets */, + 6907E9C020102B1900E7B1FE /* HelpWindow.xib */, + 693AAE1E200EDF1A009E481E /* RequestsVC.swift */, + 693AAE38200EE3D3009E481E /* RequestBasic.storyboard */, + 6907E9C82010508900E7B1FE /* RequestTabVC.swift */, + 693AAE19200EDA4F009E481E /* Info.plist */, + 693AAE1A200EDA4F009E481E /* Kwazii.entitlements */, + ); + path = Kwazii; + sourceTree = ""; + }; + 693AAE26200EDF82009E481E /* XDataService */ = { + isa = PBXGroup; + children = ( + 693AAE27200EDF82009E481E /* XDataService.h */, + 693AAE28200EDF82009E481E /* Info.plist */, + 693AAE31200EDFA5009E481E /* RequestsBasic.swift */, + 693AAE37200EE255009E481E /* xdatamac.xcconfig */, + 693AAE78200EED15009E481E /* RequestBasic.xib */, + ); + path = XDataService; + sourceTree = ""; + }; + 693AAE74200EE991009E481E /* ios */ = { + isa = PBXGroup; + children = ( + 6903CDD520159D1100642B68 /* Crashlytics.framework */, + 69348F311FFB713E007C841C /* Fabric.framework */, + 697B7C3D1DDF41F400584179 /* MMDB.framework */, + 6918834E1DDDA0280051DAAE /* lwip.framework */, + 69F698E91DDC21ED00966272 /* DarwinCore.framework */, + 69ED92B61DD9AF9500D51369 /* GRDB.framework */, + 69803E6C1DD97BA50047112C /* SwiftyJSON.framework */, + 69803E6A1DD97BA00047112C /* Sodium.framework */, + 69803E641DD97B820047112C /* Crypto.framework */, + 69803E621DD97B780047112C /* CommonCrypto.framework */, + 69803E601DD97B6F0047112C /* CocoaAsyncSocket.framework */, + 69DD43541DDC4DD500080CF1 /* SystemKitiOS.framework */, + 69803E5E1DD97B640047112C /* AxLogger.framework */, + 69803E5C1DD97B5D0047112C /* Alamofire.framework */, + 69AD9CC7200354A100C01011 /* XFoundation.framework */, + 69348F371FFB7212007C841C /* Xcon.framework */, + 69348F361FFB7211007C841C /* XProxy.framework */, + 69348F381FFB7213007C841C /* XRuler.framework */, + 69348F391FFB7213007C841C /* XSocket.framework */, + 6929C3301F32FCE0007C1FA3 /* IoniconsSwift.framework */, + 693AAE75200EE9A0009E481E /* NetworkExtension.framework */, + 6906B7671EF36B6700CA66CA /* Charts.framework */, + 6906B7651EF36B5B00CA66CA /* SwiftyStoreKit.framework */, + 69639BC61EE1636700893D18 /* DarwinCore.framework */, + 693B744D1ED9FA7A004C6E87 /* kcp.framework */, + 693B74491ED9FA69004C6E87 /* SFSocket.framework */, + 69303FC21ECA99610089AFFA /* snappy.framework */, + 690AB8841E97652F001A6C3A /* ObjectMapper.framework */, + 69D411AC1E975D6C0095E683 /* IDZSwiftCommonCrypto.framework */, + 69BD54C41E975C88008F10DC /* Reachability.framework */, + ); + name = ios; + sourceTree = ""; + }; + 695987941C158911003E1DDC /* logger */ = { + isa = PBXGroup; + children = ( + 69FDC23F1ED5B2D100A19081 /* RecentReqViewController.swift */, + 695987951C15894C003E1DDC /* LogFileViewController.swift */, + 696E73B81C44E59D00DF9A39 /* LogListTableViewController.swift */, + 690C64CF1D66BB9F00FB9BA7 /* SFactivity.swift */, + ); + name = logger; + sourceTree = ""; + }; + 695BBDD71C6481F500879ABB /* vpnmanage */ = { + isa = PBXGroup; + children = ( + 695BBDD81C64823900879ABB /* SFVPNManager.swift */, + 69BBD6421CD9C8A500DB8CBC /* SFRuleHelper.swift */, + 6916AB931CDE600100C2FC48 /* SFRuleWriter.swift */, + ); + name = vpnmanage; + sourceTree = ""; + }; + 696573EE1DE4959B00D95D59 /* Surf-Today */ = { + isa = PBXGroup; + children = ( + 696574051DE499FC00D95D59 /* Surf_Today.entitlements */, + 696573F11DE4959B00D95D59 /* TodayViewController.swift */, + 69BF6C6A1DE68985000ABF09 /* StatCell.swift */, + 696573F31DE4959B00D95D59 /* TodayViewController.xib */, + 696573F61DE4959B00D95D59 /* Info.plist */, + 696573F71DE4959B00D95D59 /* InfoPlist.strings */, + 696573EF1DE4959B00D95D59 /* Supporting Files */, + ); + path = "Surf-Today"; + sourceTree = ""; + }; + 696573EF1DE4959B00D95D59 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 696573F01DE4959B00D95D59 /* Surf_Today.entitlements */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6965AA741C56038C00F38B8D /* cells */ = { + isa = PBXGroup; + children = ( + 6965AA751C56056C00F38B8D /* TwoLableCell.swift */, + 69BEFA2A1C7D84240066118E /* SwitchCell.swift */, + ); + name = cells; + sourceTree = ""; + }; + 6965AA771C5606D400F38B8D /* setting */ = { + isa = PBXGroup; + children = ( + 6965AA781C56070600F38B8D /* LoglevelTableViewController.swift */, + 694492301C568E4F00DD75CA /* RulesTableViewController.swift */, + ); + name = setting; + sourceTree = ""; + }; + 69784D351DE0A423007E32C2 /* MacFrameworks */ = { + isa = PBXGroup; + children = ( + 69DA26C62007ACDE0044FA53 /* Reachability.framework */, + 69DA26BD2007AC2B0044FA53 /* XProxy.framework */, + 69DA26B92007AC190044FA53 /* XFoundation.framework */, + 69DA26B52007AC0E0044FA53 /* XSocket.framework */, + 69DA26B12007AC060044FA53 /* Xcon.framework */, + 69DA26AD2007ABFB0044FA53 /* XRuler.framework */, + 69DA26A42007A96A0044FA53 /* Crashlytics.framework */, + 69DA26A52007A96A0044FA53 /* Fabric.framework */, + 69263EF81EE50C5B005F0C76 /* SFSocket.framework */, + 69263EEB1EE50491005F0C76 /* snappy.framework */, + 69BCD77D1EE469D100A8A19C /* ObjectMapper.framework */, + 69639C231EE1C34400893D18 /* kcp.framework */, + 694397B71E5C37FE0009AD0E /* GRDB.framework */, + 69784D3A1DE0A467007E32C2 /* Alamofire.framework */, + 69784D3B1DE0A467007E32C2 /* AxLogger.framework */, + 69784D3C1DE0A467007E32C2 /* CocoaAsyncSocket.framework */, + 69784D3D1DE0A467007E32C2 /* CommonCrypto.framework */, + 69784D3E1DE0A467007E32C2 /* Crypto.framework */, + 69784D3F1DE0A467007E32C2 /* DarwinCore.framework */, + 69784D411DE0A467007E32C2 /* lwip.framework */, + 69784D421DE0A467007E32C2 /* MMDB.framework */, + 69784D441DE0A467007E32C2 /* Sodium.framework */, + 69784D451DE0A467007E32C2 /* SwiftyJSON.framework */, + 69784D461DE0A467007E32C2 /* SystemKit.framework */, + ); + name = MacFrameworks; + sourceTree = ""; + }; + 6987057C1C0FE87A00783358 /* help */ = { + isa = PBXGroup; + children = ( + 6916AB581CDB9DB200C2FC48 /* rules_public.conf */, + 69A0900C1C4C8CCC0064D361 /* config.html */, + 69366E671BFECBE700AE123D /* Info.plist */, + 6987057D1C0FE8A200783358 /* HelpTableViewController.swift */, + 694397B51E5C16470009AD0E /* SFTableViewCell.swift */, + 6987057F1C0FE8F300783358 /* AcknowledgeViewController.swift */, + 69A090071C4C83650064D361 /* SampleCell.swift */, + 69A0900A1C4C851C0064D361 /* SFWebViewController.swift */, + 69673C4E1F32D6A00003AB6C /* help.storyboard */, + 69F1005A1E855F77008AA81D /* iCloudViewController.swift */, + ); + name = help; + sourceTree = ""; + }; + 698705811C0FFBE900783358 /* config */ = { + isa = PBXGroup; + children = ( + 6904E8141CAE194F00179E81 /* proxygroup */, + 69A4F6291C61E90B00FCFE0E /* rules */, + 6965AA771C5606D400F38B8D /* setting */, + 6965AA741C56038C00F38B8D /* cells */, + 696E73B31C44CEEA00DF9A39 /* DataShare.swift */, + 6920758A1CE77C12000F1ED9 /* HostsTableViewController.swift */, + 6964C0A81CF544570021897B /* DNSViewController.swift */, + 6920758C1CE77C29000F1ED9 /* HostEditTableViewController.swift */, + 696E73B41C44CEEA00DF9A39 /* Socks.swift */, + 5756A95A1C02C321006C08BB /* TextFieldCell.swift */, + 5756A9581BFF1DA4006C08BB /* AddEditProxyController.swift */, + 69366E5D1BFECBE700AE123D /* SecondViewController.swift */, + 693DBDFE1C96977A0067595C /* SFCountry.swift */, + 69366E5B1BFECBE700AE123D /* SFConfigViewController.swift */, + 696DD2D91C7B132E00C34416 /* OndemandController.swift */, + 69366E591BFECBE700AE123D /* AppDelegate.swift */, + 698705781C0FD46500783358 /* BarcodeScanViewController.swift */, + 69421BDF1C4CD90300021649 /* ConfigTableViewController.swift */, + 69421BE11C4CE6B100021649 /* iTunesFileTableViewController.swift */, + 69A99E4B1C6A2E96009EC4C5 /* SFLog.swift */, + 693DBE011C969C610067595C /* data.json */, + ); + name = config; + sourceTree = ""; + }; + 6989A5001C31042D00DD1435 /* TunServerUI */ = { + isa = PBXGroup; + children = ( + 6989A50F1C3105B800DD1435 /* server */, + ); + path = TunServerUI; + sourceTree = ""; + }; + 6989A50F1C3105B800DD1435 /* server */ = { + isa = PBXGroup; + children = ( + ); + name = server; + sourceTree = ""; + }; + 6989AB031C312A3400DD1435 /* Shared */ = { + isa = PBXGroup; + children = ( + 6989AB071C312A3400DD1435 /* header */, + 6989ABE51C312A3400DD1435 /* proxy */, + 6989AC031C312A3400DD1435 /* ruler */, + ); + path = Shared; + sourceTree = ""; + }; + 6989AB071C312A3400DD1435 /* header */ = { + isa = PBXGroup; + children = ( + ); + path = header; + sourceTree = ""; + }; + 6989ABE51C312A3400DD1435 /* proxy */ = { + isa = PBXGroup; + children = ( + 6989ABFA1C312A3400DD1435 /* tun */, + ); + path = proxy; + sourceTree = ""; + }; + 6989ABFA1C312A3400DD1435 /* tun */ = { + isa = PBXGroup; + children = ( + 6989AC011C312A3400DD1435 /* StackHelper.h */, + 6989AC021C312A3400DD1435 /* StackHelper.m */, + 692B4FFB1C71A0E600BB793B /* SFAppIden.swift */, + 692B4FFD1C71A11300BB793B /* useragents.plist */, + 696847771D504E87005E17C2 /* SFAppExtension.swift */, + ); + path = tun; + sourceTree = ""; + }; + 6989AC031C312A3400DD1435 /* ruler */ = { + isa = PBXGroup; + children = ( + 6936B4D61C4D304C000EBF70 /* ISO_3166.txt */, + ); + path = ruler; + sourceTree = ""; + }; + 698BFE1A1C3A1F1300CED9EC /* mac */ = { + isa = PBXGroup; + children = ( + 693DBDFC1C9690F30067595C /* config.pac.js */, + 6927ADA51DE0B6010027EF7A /* PacketTunnel_Mac-Swift.h */, + 698BFE291C3A218000CED9EC /* PacketTunnel-Mac.xcconfig */, + 692EF8FC1CABF05C00C9936A /* socks5.js */, + 698BFE211C3A206300CED9EC /* PacketTunnel_Mac.entitlements */, + 698BFE231C3A209700CED9EC /* PacketTunnel-Mac-Bridging-Header.h */, + 698BFE201C3A205A00CED9EC /* Info.plist */, + ); + name = mac; + sourceTree = ""; + }; + 698BFE241C3A20E900CED9EC /* iOS */ = { + isa = PBXGroup; + children = ( + 698BFE251C3A20FC00CED9EC /* Info.plist */, + 698BFE261C3A20FC00CED9EC /* PacketTunnel-Bridging-Header.h */, + 698BFE271C3A20FC00CED9EC /* PacketTunnel-Swift.h */, + 698BFE281C3A20FC00CED9EC /* PacketTunnel.entitlements */, + 696E73AB1C44982400DF9A39 /* PacketTunnel-iOS.xcconfig */, + 6946FAF11CB6330C00A8586E /* .adblock */, + 69BE2E681FFC704C0078845A /* ENV.swift */, + ); + name = iOS; + sourceTree = ""; + }; + 69A4F6291C61E90B00FCFE0E /* rules */ = { + isa = PBXGroup; + children = ( + 694536B61C72E74800C4595D /* RuleTableViewController.swift */, + 690C64D21D67670B00FB9BA7 /* SFConfigManager.swift */, + 697770471C7ADBE700C552BF /* CountrySelectController.swift */, + 694536B81C730DFE00C4595D /* PolicyViewController.swift */, + ); + name = rules; + sourceTree = ""; + }; + 69C4EE2A1C2919010020FBF8 /* Surf-Mac */ = { + isa = PBXGroup; + children = ( + 69290F8320302F9500780915 /* icon.icns */, + 6983C0E41DF4FED300100E70 /* Credits.rtf */, + 6947D7731CE4D0050020BBCB /* A_BIG_T-Bridging-Header.h */, + 69DA64C71C291E1B00DC174C /* Surf-Mac.entitlements */, + 69C4EE2B1C2919010020FBF8 /* AppDelegate.swift */, + 6906B91A1DE2B8BA00A60B66 /* StatusView.swift */, + 69C4EE2D1C2919010020FBF8 /* ViewController.swift */, + 69C4EE2F1C2919010020FBF8 /* Assets.xcassets */, + 69C4EE311C2919010020FBF8 /* Main.storyboard */, + 6906B90B1DE29D8F00A60B66 /* Config.storyboard */, + 69C4EE341C2919010020FBF8 /* Info.plist */, + 6947D7711CE4CE5E0020BBCB /* Surf-Mac.xcconfig */, + 6952BAF01DF9529700DAD397 /* QrController.swift */, + 696573D01DE48EBF00D95D59 /* AdvancedWindowController.swift */, + 696573D11DE48EBF00D95D59 /* AdvancedWindowController.xib */, + 6906B9161DE2A6E300A60B66 /* PreferencesWindowController.swift */, + 6906B9181DE2A6EC00A60B66 /* PreferencesWindowController.xib */, + 6906B90D1DE29F8300A60B66 /* ConfigWindowController.swift */, + 69BFCCDB1DE34D1200469B8C /* QRCodeWindow.xib */, + 6952BAE81DF92F9D00DAD397 /* QrWindowController.swift */, + 693766B91DFE8F7C0015C549 /* QRView.swift */, + 6906B9131DE2A2D600A60B66 /* MainMenu.xib */, + 69BFCCD71DE34C8A00469B8C /* SWBQRCodeWindowController.swift */, + 69BF6C6C1DE6D742000ABF09 /* RequestsWindowController.swift */, + 69BF6C6D1DE6D742000ABF09 /* RequestsWindowController.xib */, + 69D18ED21DE7E35F006264F9 /* SFApplication.swift */, + 69D18ED61DE9C0FB006264F9 /* SFMono-Regular.otf */, + 6983C0C31DF4F5B600100E70 /* About.xib */, + 6983C0C51DF4F61500100E70 /* AboutWindowController.swift */, + 69F5C358203045AB0075B8E0 /* InfoPlist.strings */, + ); + path = "Surf-Mac"; + sourceTree = ""; + }; + 69E136791C704708002BFBF2 /* analyze */ = { + isa = PBXGroup; + children = ( + 6975F13B1F32D17D00F7674C /* ana.storyboard */, + 695987941C158911003E1DDC /* logger */, + 69E1367C1C704773002BFBF2 /* RuleResultsViewController.swift */, + 69E1367E1C7047ED002BFBF2 /* StatViewController.swift */, + 69E136801C704C03002BFBF2 /* AnalyzeTableViewController.swift */, + 692B4FF91C71646200BB793B /* RequestDetailViewController.swift */, + 695EA9AD1E81069000D594CC /* HistoryViewController.swift */, + 6957A2D41F04D27700B54B90 /* ChartsView.swift */, + 69801C95200D947400A214D6 /* BarChatsCell.swift */, + ); + name = analyze; + sourceTree = ""; + }; + 69E96BCA2009974B0060659A /* check */ = { + isa = PBXGroup; + children = ( + 69E96BCD2009ADBB0060659A /* CheckTableViewController.swift */, + ); + name = check; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 693AAE22200EDF82009E481E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 693AAE29200EDF82009E481E /* XDataService.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 578ED9281C03181200913B2F /* PacketTunnel-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 578ED9331C03181300913B2F /* Build configuration list for PBXNativeTarget "PacketTunnel-iOS" */; + buildPhases = ( + 578ED9251C03181200913B2F /* Sources */, + 578ED9261C03181200913B2F /* Frameworks */, + 578ED9271C03181200913B2F /* Resources */, + 696AF49B1F02475A00756E5E /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PacketTunnel-iOS"; + productName = PacketTunnel; + productReference = 578ED9291C03181200913B2F /* PacketTunnel-iOS.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 692D8CF61C6A250400C07B3A /* SurfToday */ = { + isa = PBXNativeTarget; + buildConfigurationList = 692D8D051C6A250400C07B3A /* Build configuration list for PBXNativeTarget "SurfToday" */; + buildPhases = ( + 692D8CF31C6A250400C07B3A /* Sources */, + 692D8CF41C6A250400C07B3A /* Frameworks */, + 692D8CF51C6A250400C07B3A /* Resources */, + 69C2A60B1F147D9000B1B0A6 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SurfToday; + productName = SurfToday; + productReference = 692D8CF71C6A250400C07B3A /* SurfToday.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 69366E551BFECBE700AE123D /* Surf */ = { + isa = PBXNativeTarget; + buildConfigurationList = 69366E6A1BFECBE700AE123D /* Build configuration list for PBXNativeTarget "Surf" */; + buildPhases = ( + 69366E521BFECBE700AE123D /* Sources */, + 69366E531BFECBE700AE123D /* Frameworks */, + 69366E541BFECBE700AE123D /* Resources */, + 69AFBA571DDC23BD00409CD4 /* Embed Frameworks */, + 691883481DDD8D310051DAAE /* Embed App Extensions */, + 692CC9AD1F00A9DB00B00496 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Surf; + productName = Surf; + productReference = 69366E561BFECBE700AE123D /* Surf.app */; + productType = "com.apple.product-type.application"; + }; + 693AAE0D200EDA4E009E481E /* Kwazii */ = { + isa = PBXNativeTarget; + buildConfigurationList = 693AAE1D200EDA4F009E481E /* Build configuration list for PBXNativeTarget "Kwazii" */; + buildPhases = ( + 693AAE0A200EDA4E009E481E /* Sources */, + 693AAE0B200EDA4E009E481E /* Frameworks */, + 693AAE0C200EDA4E009E481E /* Resources */, + 693AAE3E200EE646009E481E /* Embed Frameworks */, + 6907E9D62011AE7D00E7B1FE /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 693AAE3D200EE646009E481E /* PBXTargetDependency */, + ); + name = Kwazii; + productName = Kwazii; + productReference = 693AAE0E200EDA4E009E481E /* Kwazii.app */; + productType = "com.apple.product-type.application"; + }; + 693AAE24200EDF82009E481E /* XDataService */ = { + isa = PBXNativeTarget; + buildConfigurationList = 693AAE2E200EDF82009E481E /* Build configuration list for PBXNativeTarget "XDataService" */; + buildPhases = ( + 693AAE20200EDF82009E481E /* Sources */, + 693AAE21200EDF82009E481E /* Frameworks */, + 693AAE22200EDF82009E481E /* Headers */, + 693AAE23200EDF82009E481E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XDataService; + productName = XDataService; + productReference = 693AAE25200EDF82009E481E /* XDataService.framework */; + productType = "com.apple.product-type.framework"; + }; + 696573EB1DE4959B00D95D59 /* A.BIG.T-Today */ = { + isa = PBXNativeTarget; + buildConfigurationList = 696573FD1DE4959B00D95D59 /* Build configuration list for PBXNativeTarget "A.BIG.T-Today" */; + buildPhases = ( + 696573E81DE4959B00D95D59 /* Sources */, + 696573E91DE4959B00D95D59 /* Frameworks */, + 696573EA1DE4959B00D95D59 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "A.BIG.T-Today"; + productName = "Surf-Today"; + productReference = 696573EC1DE4959B00D95D59 /* A.BIG.T-Today.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 69C4EE281C2919010020FBF8 /* A.BIG.T */ = { + isa = PBXNativeTarget; + buildConfigurationList = 69C4EE351C2919010020FBF8 /* Build configuration list for PBXNativeTarget "A.BIG.T" */; + buildPhases = ( + 69C4EE251C2919010020FBF8 /* Sources */, + 69C4EE261C2919010020FBF8 /* Frameworks */, + 69C4EE271C2919010020FBF8 /* Resources */, + 69C4EE491C29193D0020FBF8 /* Embed App Extensions */, + 69DA64DE1C291FD300DC174C /* Embed Frameworks */, + 69B37CC21F035F03007E64CE /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 69784D631DE0A8B1007E32C2 /* PBXTargetDependency */, + 696573FB1DE4959B00D95D59 /* PBXTargetDependency */, + 693AAE2B200EDF82009E481E /* PBXTargetDependency */, + ); + name = A.BIG.T; + productName = "Surf-Mac"; + productReference = 69C4EE291C2919010020FBF8 /* A.BIG.T.app */; + productType = "com.apple.product-type.application"; + }; + 69C4EE3B1C29193D0020FBF8 /* PacketTunnel-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = 69C4EE461C29193D0020FBF8 /* Build configuration list for PBXNativeTarget "PacketTunnel-Mac" */; + buildPhases = ( + 69C4EE381C29193D0020FBF8 /* Sources */, + 69C4EE391C29193D0020FBF8 /* Frameworks */, + 69C4EE3A1C29193D0020FBF8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PacketTunnel-Mac"; + productName = "PacketTunnel-Mac"; + productReference = 69C4EE3C1C29193D0020FBF8 /* PacketTunnel-Mac.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 69366E4E1BFECBE700AE123D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftMigration = 0730; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = A.BIG.T; + TargetAttributes = { + 578ED9281C03181200913B2F = { + CreatedOnToolsVersion = 7.2; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0910; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.Keychain = { + enabled = 0; + }; + com.apple.NetworkExtensions = { + enabled = 0; + }; + com.apple.SafariKeychain = { + enabled = 0; + }; + com.apple.VPNLite = { + enabled = 1; + }; + }; + }; + 692D8CF61C6A250400C07B3A = { + CreatedOnToolsVersion = 7.3; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0910; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.Keychain = { + enabled = 0; + }; + }; + }; + 69366E551BFECBE700AE123D = { + CreatedOnToolsVersion = 7.1.1; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0910; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.BackgroundModes = { + enabled = 0; + }; + com.apple.Keychain = { + enabled = 1; + }; + com.apple.NetworkExtensions = { + enabled = 1; + }; + com.apple.Push = { + enabled = 1; + }; + com.apple.VPNLite = { + enabled = 1; + }; + com.apple.WAC = { + enabled = 0; + }; + com.apple.iCloud = { + enabled = 1; + }; + }; + }; + 693AAE0D200EDA4E009E481E = { + CreatedOnToolsVersion = 9.2; + DevelopmentTeam = 745WQDK4L7; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.ApplicationGroups.Mac = { + enabled = 1; + }; + com.apple.Sandbox = { + enabled = 0; + }; + }; + }; + 693AAE24200EDF82009E481E = { + CreatedOnToolsVersion = 9.2; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0920; + ProvisioningStyle = Automatic; + }; + 696573EB1DE4959B00D95D59 = { + CreatedOnToolsVersion = 8.2; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0910; + ProvisioningStyle = Manual; + }; + 69C4EE281C2919010020FBF8 = { + CreatedOnToolsVersion = 7.2; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0910; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.ApplicationGroups.Mac = { + enabled = 1; + }; + com.apple.Sandbox = { + enabled = 1; + }; + com.apple.iCloud = { + enabled = 1; + }; + }; + }; + 69C4EE3B1C29193D0020FBF8 = { + CreatedOnToolsVersion = 7.2; + DevelopmentTeam = 745WQDK4L7; + LastSwiftMigration = 0910; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.ApplicationGroups.Mac = { + enabled = 1; + }; + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + }; + }; + buildConfigurationList = 69366E511BFECBE700AE123D /* Build configuration list for PBXProject "Surf" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + "zh-Hans", + ); + mainGroup = 69366E4D1BFECBE700AE123D; + productRefGroup = 69366E571BFECBE700AE123D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 69366E551BFECBE700AE123D /* Surf */, + 578ED9281C03181200913B2F /* PacketTunnel-iOS */, + 69C4EE281C2919010020FBF8 /* A.BIG.T */, + 69C4EE3B1C29193D0020FBF8 /* PacketTunnel-Mac */, + 692D8CF61C6A250400C07B3A /* SurfToday */, + 696573EB1DE4959B00D95D59 /* A.BIG.T-Today */, + 693AAE0D200EDA4E009E481E /* Kwazii */, + 693AAE24200EDF82009E481E /* XDataService */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 578ED9271C03181200913B2F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6946FAF21CB6330C00A8586E /* .adblock in Resources */, + 692B4FFF1C71A11800BB793B /* useragents.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 692D8CF51C6A250400C07B3A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 69100F641CB5FFD10023F88F /* image.xcassets in Resources */, + 69673C481F32D41E0003AB6C /* Localizable.strings in Resources */, + 692D8D001C6A250400C07B3A /* MainInterface.storyboard in Resources */, + 69A9FE4D1CC5C0CF00D5DB41 /* ionicons.ttf in Resources */, + 692D8D091C6A27FE00C07B3A /* today.entitlements in Resources */, + 6975F1441F32D2F100F7674C /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69366E541BFECBE700AE123D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 69673C4C1F32D6A00003AB6C /* help.storyboard in Resources */, + 69366E631BFECBE700AE123D /* Assets.xcassets in Resources */, + 690C77C11CF42FF100EB1610 /* Default.conf in Resources */, + 69673C471F32D41E0003AB6C /* Localizable.strings in Resources */, + 69746FCF1C1A80E500CA44BE /* LaunchScreen.xib in Resources */, + 69A0900D1C4C8CCC0064D361 /* config.html in Resources */, + 6916AB591CDB9DB200C2FC48 /* rules_public.conf in Resources */, + 69290F8420302F9600780915 /* icon.icns in Resources */, + 69366E611BFECBE700AE123D /* Main.storyboard in Resources */, + 69707AF31EF37F5D00C7BD9D /* buy.storyboard in Resources */, + 6975F1431F32D2F100F7674C /* InfoPlist.strings in Resources */, + 69BD736D1DB4B3740078EB02 /* imageView.storyboard in Resources */, + 6964C0B31CF5931A0021897B /* surf.conf in Resources */, + 692B4FFE1C71A11300BB793B /* useragents.plist in Resources */, + 6975F1391F32D17D00F7674C /* ana.storyboard in Resources */, + 693DBE021C969C610067595C /* data.json in Resources */, + 691462B11D6D3C5D007992F2 /* SSMethod.storyboard in Resources */, + 693B603D1C479F2A00173D0B /* thanks.txt in Resources */, + 6936B4D71C4D304C000EBF70 /* ISO_3166.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE0C200EDA4E009E481E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6907E9D22011815100E7B1FE /* SUUpdateSettingsWindowController.xib in Resources */, + 693AAE7A200EF24F009E481E /* RequestBasic.storyboard in Resources */, + 693AAE83200F1A94009E481E /* data.json in Resources */, + 6907E9C120102B1900E7B1FE /* HelpWindow.xib in Resources */, + 693AAE7C200EF7F3009E481E /* abigt.conf in Resources */, + 693AAE7F200F0F81009E481E /* PreferencesWindowController.xib in Resources */, + 6907E9D42011959E00E7B1FE /* Assets.xcassets in Resources */, + 693AAE18200EDA4F009E481E /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE23200EDF82009E481E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 693AAE79200EED15009E481E /* RequestBasic.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 696573EA1DE4959B00D95D59 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 696573F51DE4959B00D95D59 /* TodayViewController.xib in Resources */, + 696574081DE49FEA00D95D59 /* Assets.xcassets in Resources */, + 69558F731E002832008D5F3D /* SFMono-Regular.otf in Resources */, + 696573F91DE4959B00D95D59 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE271C2919010020FBF8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6906B9451DE5456900A60B66 /* data.json in Resources */, + 69F5C356203045AB0075B8E0 /* InfoPlist.strings in Resources */, + 6906B9401DE410BF00A60B66 /* surf.conf in Resources */, + 6983C0C41DF4F5B600100E70 /* About.xib in Resources */, + 6906B90C1DE29D8F00A60B66 /* Config.storyboard in Resources */, + 6906B9191DE2A6EC00A60B66 /* PreferencesWindowController.xib in Resources */, + 693AAE87200F2FBD009E481E /* RequestBasic.storyboard in Resources */, + 6952BAEC1DF9314500DAD397 /* QRCodeWindow.xib in Resources */, + 69C4EE301C2919010020FBF8 /* Assets.xcassets in Resources */, + 69BF6C751DE6E3F9000ABF09 /* useragents.plist in Resources */, + 6906B91C1DE2BD8500A60B66 /* ionicons.ttf in Resources */, + 6906B9151DE2A36C00A60B66 /* MainMenu.xib in Resources */, + 69BF6C6F1DE6D742000ABF09 /* RequestsWindowController.xib in Resources */, + 6906B93E1DE3E62F00A60B66 /* thanks.txt in Resources */, + 696573D31DE48EBF00D95D59 /* AdvancedWindowController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE3A1C29193D0020FBF8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 698BFE221C3A206300CED9EC /* PacketTunnel_Mac.entitlements in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 6907E9D62011AE7D00E7B1FE /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "./maclab/Fabric.framework/run key token"; + }; + 692CC9AD1F00A9DB00B00496 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "./iosLib/Fabric.framework/run key token\n"; + }; + 696AF49B1F02475A00756E5E /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "./iosLib/Fabric.framework/run key token"; + }; + 69B37CC21F035F03007E64CE /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "./maclab/Fabric.framework/run key token"; + }; + 69C2A60B1F147D9000B1B0A6 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "./iosLib/Fabric.framework/run key token"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 578ED9251C03181200913B2F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 578ED92E1C03181300913B2F /* PacketTunnelProvider.swift in Sources */, + 69BE2E6A1FFC706F0078845A /* ENV.swift in Sources */, + 69D9C6811C52037E009453AF /* const.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 692D8CF31C6A250400C07B3A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 69A99E4D1C6A2E96009EC4C5 /* SFLog.swift in Sources */, + 6987A6441F31ACCA006FD800 /* ChartsView.swift in Sources */, + 69348F2C1FFB6BBE007C841C /* TodayViewController.swift in Sources */, + 692D8D0A1C6A2AC900C07B3A /* SFVPNManager.swift in Sources */, + 694CFA7D200BBF9B009FA3C3 /* ENV.swift in Sources */, + 69100F621CB5F7B00023F88F /* SFTableViewController.swift in Sources */, + 69A99E491C6A2DBF009EC4C5 /* const.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69366E521BFECBE700AE123D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 694492311C568E4F00DD75CA /* RulesTableViewController.swift in Sources */, + 695EA9AE1E81069000D594CC /* HistoryViewController.swift in Sources */, + 69F8B0E21F62231700CA85CE /* DNSViewController.swift in Sources */, + 698705791C0FD46500783358 /* BarcodeScanViewController.swift in Sources */, + 691462AF1D6D3C44007992F2 /* SFMethodViewController.swift in Sources */, + 69F1005B1E855F77008AA81D /* iCloudViewController.swift in Sources */, + 697770481C7ADBE700C552BF /* CountrySelectController.swift in Sources */, + 6971C0DD1D51E83A00CC75BF /* FlyViewController.swift in Sources */, + 690C64D31D67670B00FB9BA7 /* SFConfigManager.swift in Sources */, + 694397B41E5C10B10009AD0E /* SFNavigationController.swift in Sources */, + 6957A2D51F04D27700B54B90 /* ChartsView.swift in Sources */, + 692B4FFA1C71646200BB793B /* RequestDetailViewController.swift in Sources */, + 694536B91C730DFE00C4595D /* PolicyViewController.swift in Sources */, + 69BE2E691FFC704C0078845A /* ENV.swift in Sources */, + 695BBDD91C64823900879ABB /* SFVPNManager.swift in Sources */, + 69BEFA2B1C7D84240066118E /* SwitchCell.swift in Sources */, + 695987961C15894C003E1DDC /* LogFileViewController.swift in Sources */, + 6987057E1C0FE8A200783358 /* HelpTableViewController.swift in Sources */, + 6906B7611EF280B400CA66CA /* SFVerify.swift in Sources */, + 69BD736E1DB4B3740078EB02 /* ImageViewController.swift in Sources */, + 69366E5E1BFECBE700AE123D /* SecondViewController.swift in Sources */, + 6964C0B51CF5AC130021897B /* TitleView.swift in Sources */, + 69707AF01EF37F2C00C7BD9D /* NetworkActivityIndicatorManager.swift in Sources */, + 696E73B61C44CEEA00DF9A39 /* Socks.swift in Sources */, + 69A99E4C1C6A2E96009EC4C5 /* SFLog.swift in Sources */, + 5756A9591BFF1DA4006C08BB /* AddEditProxyController.swift in Sources */, + 696847791D504E8A005E17C2 /* SFAppExtension.swift in Sources */, + 69366E5A1BFECBE700AE123D /* AppDelegate.swift in Sources */, + 6916AB941CDE600100C2FC48 /* SFRuleWriter.swift in Sources */, + 698705801C0FE8F300783358 /* AcknowledgeViewController.swift in Sources */, + 69366E5C1BFECBE700AE123D /* SFConfigViewController.swift in Sources */, + 690C64D01D66BB9F00FB9BA7 /* SFactivity.swift in Sources */, + 69E136831C705107002BFBF2 /* SFTableViewController.swift in Sources */, + 69E1367F1C7047ED002BFBF2 /* StatViewController.swift in Sources */, + 693DBDFF1C96977A0067595C /* SFCountry.swift in Sources */, + 69C9B0D91D3F50490089BC82 /* ConfigEditViewController.swift in Sources */, + 69421BE21C4CE6B100021649 /* iTunesFileTableViewController.swift in Sources */, + 694397B61E5C16470009AD0E /* SFTableViewCell.swift in Sources */, + 696E73B91C44E59D00DF9A39 /* LogListTableViewController.swift in Sources */, + 69A0900B1C4C851C0064D361 /* SFWebViewController.swift in Sources */, + 69421BE01C4CD90300021649 /* ConfigTableViewController.swift in Sources */, + 6938E6531D388A9200671B96 /* SFInterfaceTraffic.swift in Sources */, + 696E73B51C44CEEA00DF9A39 /* DataShare.swift in Sources */, + 699C8F561D79B2D300064802 /* SFViewController.swift in Sources */, + 69707AF11EF37F2C00C7BD9D /* BuyViewController.swift in Sources */, + 6920758D1CE77C29000F1ED9 /* HostEditTableViewController.swift in Sources */, + 693B603F1C48867500173D0B /* const.swift in Sources */, + 6971C0DF1D51E87000CC75BF /* PlaneView.swift in Sources */, + 6904E8161CAE197000179E81 /* ProxyGroupViewController.swift in Sources */, + 5756A95B1C02C321006C08BB /* TextFieldCell.swift in Sources */, + 696DD2DA1C7B132E00C34416 /* OndemandController.swift in Sources */, + 6965AA761C56056C00F38B8D /* TwoLableCell.swift in Sources */, + 6920758B1CE77C12000F1ED9 /* HostsTableViewController.swift in Sources */, + 69E136811C704C03002BFBF2 /* AnalyzeTableViewController.swift in Sources */, + 69801C96200D947400A214D6 /* BarChatsCell.swift in Sources */, + 6904E8181CAE653E00179E81 /* ProxyCell.swift in Sources */, + 69A4ACE41D2E37C7008963FB /* WidgetSelectViewController.swift in Sources */, + 69FDC2401ED5B2D100A19081 /* RecentReqViewController.swift in Sources */, + 69303FCD1ECA9A8E0089AFFA /* KcpTableViewController.swift in Sources */, + 690FF0001C64546B005F1095 /* SFDocumentPickerViewController.swift in Sources */, + 692B4FFC1C71A0E600BB793B /* SFAppIden.swift in Sources */, + 69A090081C4C83650064D361 /* SampleCell.swift in Sources */, + 69F8B0E11F6222FD00CA85CE /* RuleTableViewController.swift in Sources */, + 69E96BCE2009ADBB0060659A /* CheckTableViewController.swift in Sources */, + 69348F2B1FFB653D007C841C /* LoglevelTableViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE0A200EDA4E009E481E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 693AAE77200EEA3C009E481E /* MainWindow.swift in Sources */, + 693AAE13200EDA4F009E481E /* ViewController.swift in Sources */, + 6907E9C320102BC400E7B1FE /* HelpWindowController.swift in Sources */, + 693AAE7D200F0F7A009E481E /* PreferencesWindowController.swift in Sources */, + 693AAE11200EDA4E009E481E /* KwaziiAppDelegate.swift in Sources */, + 6907E9CF201180DB00E7B1FE /* UpdateWindowController.swift in Sources */, + 693AAE85200F2A84009E481E /* const.swift in Sources */, + 6907E9C92010508900E7B1FE /* RequestTabVC.swift in Sources */, + 693AAE82200F1742009E481E /* SFCountry.swift in Sources */, + 6907E9C720104ECC00E7B1FE /* RequestDetailView.swift in Sources */, + 693AAE1F200EDF1A009E481E /* RequestsVC.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 693AAE20200EDF82009E481E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 693AAE33200EE1D7009E481E /* SFAppExtension.swift in Sources */, + 693AAE35200EE204009E481E /* const.swift in Sources */, + 693AAE34200EE1F5009E481E /* SFAppIden.swift in Sources */, + 693AAE36200EE215009E481E /* SFConfigManager.swift in Sources */, + 693AAE32200EDFA5009E481E /* RequestsBasic.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 696573E81DE4959B00D95D59 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 696573F21DE4959B00D95D59 /* TodayViewController.swift in Sources */, + 696574031DE4985D00D95D59 /* const.swift in Sources */, + 69BF6C6B1DE68985000ABF09 /* StatCell.swift in Sources */, + 696574001DE497B100D95D59 /* SFVPNManager.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE251C2919010020FBF8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 693AAE86200F2FB6009E481E /* RequestsVC.swift in Sources */, + 6906B91D1DE2C5E700A60B66 /* SFInterfaceTraffic.swift in Sources */, + 69BF6C741DE6E3C8000ABF09 /* SFConfigManager.swift in Sources */, + 6983C0C61DF4F61500100E70 /* AboutWindowController.swift in Sources */, + 69BF6C6E1DE6D742000ABF09 /* RequestsWindowController.swift in Sources */, + 696573D21DE48EBF00D95D59 /* AdvancedWindowController.swift in Sources */, + 6906B90E1DE29F8300A60B66 /* ConfigWindowController.swift in Sources */, + 6906B9441DE5412B00A60B66 /* SFCountry.swift in Sources */, + 6952BAEA1DF92F9D00DAD397 /* QrWindowController.swift in Sources */, + 6952BAF11DF9529700DAD397 /* QrController.swift in Sources */, + 6906B91B1DE2B8BA00A60B66 /* StatusView.swift in Sources */, + 69C4EE2E1C2919010020FBF8 /* ViewController.swift in Sources */, + 69C4EE2C1C2919010020FBF8 /* AppDelegate.swift in Sources */, + 695B20311C6195500063F794 /* const.swift in Sources */, + 69BF6C701DE6E1E0000ABF09 /* SFAppExtension.swift in Sources */, + 6906B9171DE2A6E300A60B66 /* PreferencesWindowController.swift in Sources */, + 692075871CE6DE83000F1ED9 /* SFVPNManager.swift in Sources */, + 69BF6C711DE6E230000ABF09 /* SFAppIden.swift in Sources */, + 69D18ED31DE7E35F006264F9 /* SFApplication.swift in Sources */, + 693766BA1DFE8F7C0015C549 /* QRView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69C4EE381C29193D0020FBF8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 695B20321C6195510063F794 /* const.swift in Sources */, + 69DA26AC2007AA0C0044FA53 /* ENV.swift in Sources */, + 6989ACED1C312A3400DD1435 /* StackHelper.m in Sources */, + 69DA64E71C2920FE00DC174C /* PacketTunnelProvider.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 693AAE2B200EDF82009E481E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 693AAE24200EDF82009E481E /* XDataService */; + targetProxy = 693AAE2A200EDF82009E481E /* PBXContainerItemProxy */; + }; + 693AAE3D200EE646009E481E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 693AAE24200EDF82009E481E /* XDataService */; + targetProxy = 693AAE3C200EE646009E481E /* PBXContainerItemProxy */; + }; + 696573FB1DE4959B00D95D59 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 696573EB1DE4959B00D95D59 /* A.BIG.T-Today */; + targetProxy = 696573FA1DE4959B00D95D59 /* PBXContainerItemProxy */; + }; + 69784D631DE0A8B1007E32C2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 69C4EE3B1C29193D0020FBF8 /* PacketTunnel-Mac */; + targetProxy = 69784D621DE0A8B1007E32C2 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 692D8CFE1C6A250400C07B3A /* MainInterface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 692D8CFF1C6A250400C07B3A /* Base */, + 6975F1351F32CFBF00F7674C /* zh-Hans */, + ); + name = MainInterface.storyboard; + sourceTree = ""; + }; + 69366E5F1BFECBE700AE123D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 69366E601BFECBE700AE123D /* Base */, + 6975F1311F32CFBF00F7674C /* zh-Hans */, + 697165FE1F395BEE002B13A3 /* en */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 693AAE16200EDA4F009E481E /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 693AAE17200EDA4F009E481E /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 696573F31DE4959B00D95D59 /* TodayViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 696573F41DE4959B00D95D59 /* Base */, + 6975F1371F32CFC000F7674C /* zh-Hans */, + ); + name = TodayViewController.xib; + sourceTree = ""; + }; + 696573F71DE4959B00D95D59 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 696573F81DE4959B00D95D59 /* en */, + 6975F1381F32CFC000F7674C /* zh-Hans */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 69673C4A1F32D41E0003AB6C /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 69673C491F32D41E0003AB6C /* Base */, + 69673C4B1F32D4210003AB6C /* zh-Hans */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + 69673C4E1F32D6A00003AB6C /* help.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 69673C4D1F32D6A00003AB6C /* Base */, + 69673C501F32D6A30003AB6C /* zh-Hans */, + ); + name = help.storyboard; + sourceTree = ""; + }; + 69746FCD1C1A80E500CA44BE /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 69746FCE1C1A80E500CA44BE /* Base */, + 6975F1321F32CFBF00F7674C /* zh-Hans */, + 6929C32F1F32EBCB007C1FA3 /* en */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; + 6975F13B1F32D17D00F7674C /* ana.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6975F13C1F32D18300F7674C /* Base */, + 6975F13E1F32D19400F7674C /* en */, + 6975F13F1F32D1A200F7674C /* zh-Hans */, + ); + name = ana.storyboard; + sourceTree = ""; + }; + 6975F1461F32D2F100F7674C /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 6975F1451F32D2F100F7674C /* Base */, + 6975F1471F32D2F500F7674C /* zh-Hans */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 69C4EE311C2919010020FBF8 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 69C4EE321C2919010020FBF8 /* Base */, + 6975F1331F32CFBF00F7674C /* zh-Hans */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 69F5C358203045AB0075B8E0 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 69F5C357203045AB0075B8E0 /* en */, + 69F5C359203045AE0075B8E0 /* zh-Hans */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 578ED9341C03181300913B2F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 696E73AB1C44982400DF9A39 /* PacketTunnel-iOS.xcconfig */; + buildSettings = { + CLANG_ADDRESS_SANITIZER_CONTAINER_OVERFLOW = NO; + CODE_SIGN_ENTITLEMENTS = PacketTunnel/iOS/PacketTunnel.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + ENABLE_BITCODE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/TunServerUI", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/iosLib", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + $SSL_LIB_DEFINE, + ); + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/PacketTunnel/iOS/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = ( + "-lstdc++", + "-lz", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf4.PacketTunnel; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "eef210fb-7ea4-4a7d-8f18-4ff2f1e1da2b"; + PROVISIONING_PROFILE_SPECIFIER = packet4; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG TIMER"; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)/"; + SWIFT_OBJC_BRIDGING_HEADER = "PacketTunnel/iOS/PacketTunnel-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "$(inherited)"; + }; + name = Debug; + }; + 578ED9351C03181300913B2F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 696E73AB1C44982400DF9A39 /* PacketTunnel-iOS.xcconfig */; + buildSettings = { + CLANG_ADDRESS_SANITIZER_CONTAINER_OVERFLOW = NO; + CODE_SIGN_ENTITLEMENTS = PacketTunnel/iOS/PacketTunnel.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + ENABLE_BITCODE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/TunServerUI", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/iosLib", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + $SSL_LIB_DEFINE, + ); + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/PacketTunnel/iOS/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = ( + "-lstdc++", + "-lz", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf4.PacketTunnel; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "7fd37df6-507e-430d-b3cb-3fefc31a34c9"; + PROVISIONING_PROFILE_SPECIFIER = p4_store; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = TIMER; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)/"; + SWIFT_OBJC_BRIDGING_HEADER = "PacketTunnel/iOS/PacketTunnel-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "$(inherited)"; + }; + name = Release; + }; + 692D8D061C6A250400C07B3A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6948C96E1C59C3B50057774A /* Surf-iOS.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = SurfToday/today.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = 745WQDK4L7; + ENABLE_BITCODE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/iosLib", + ); + INFOPLIST_FILE = SurfToday/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf4.SurfToday; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "59e3bf3a-c4e8-4483-9520-d27b72ce9e7d"; + PROVISIONING_PROFILE_SPECIFIER = today4; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "SurfToday-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 692D8D071C6A250400C07B3A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6948C96E1C59C3B50057774A /* Surf-iOS.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = SurfToday/today.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + DEVELOPMENT_TEAM = 745WQDK4L7; + ENABLE_BITCODE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/iosLib", + ); + INFOPLIST_FILE = SurfToday/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf4.SurfToday; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "139784b1-3780-497b-9e2d-1a0143bd5c52"; + PROVISIONING_PROFILE_SPECIFIER = t4_store; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "SurfToday-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; + 69366E681BFECBE700AE123D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 69366E691BFECBE700AE123D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 69366E6B1BFECBE700AE123D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6948C96E1C59C3B50057774A /* Surf-iOS.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; + CODE_SIGN_ENTITLEMENTS = Surf/Surf.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 745WQDK4L7; + ENABLE_BITCODE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)/iosLib", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/MMDB\"", + "\"$(SRCROOT)/share/include\"", + ); + INFOPLIST_FILE = Surf/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf4; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "2f50898e-83b3-4593-b48b-dc016d890a1b"; + PROVISIONING_PROFILE_SPECIFIER = surf4; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)/"; + SWIFT_OBJC_BRIDGING_HEADER = "Surf/$(SWIFT_MODULE_NAME)-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "arm64 armv7s armv7"; + }; + name = Debug; + }; + 69366E6C1BFECBE700AE123D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6948C96E1C59C3B50057774A /* Surf-iOS.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; + CODE_SIGN_ENTITLEMENTS = Surf/Surf.entitlements; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + COPY_PHASE_STRIP = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + ENABLE_BITCODE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)/iosLib", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/MMDB\"", + "\"$(SRCROOT)/share/include\"", + ); + INFOPLIST_FILE = Surf/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf4; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "7b2bfca4-e903-4dd9-bad7-212ff6bcc70b"; + PROVISIONING_PROFILE_SPECIFIER = sf4_store; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)/"; + SWIFT_OBJC_BRIDGING_HEADER = "Surf/$(SWIFT_MODULE_NAME)-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "arm64 armv7s armv7"; + }; + name = Release; + }; + 693AAE1B200EDA4F009E481E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = Kwazii/Kwazii.entitlements; + CODE_SIGN_IDENTITY = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)/maclab", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = Kwazii/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Kwazii; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 693AAE1C200EDA4F009E481E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = Kwazii/Kwazii.entitlements; + CODE_SIGN_IDENTITY = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)/maclab", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = Kwazii/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Kwazii; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; + 693AAE2F200EDF82009E481E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 693AAE37200EE255009E481E /* xdatamac.xcconfig */; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = XDataService/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.XDataService; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 693AAE30200EDF82009E481E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 693AAE37200EE255009E481E /* xdatamac.xcconfig */; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = XDataService/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.XDataService; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 696573FE1DE4959B00D95D59 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = ""; + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CODE_SIGN_ENTITLEMENTS = "Surf-Today/Surf_Today.entitlements"; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/maclab", + ); + INFOPLIST_FILE = "Surf-Today/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_BUNDLE_IDENTIFIER = "com.abigt.Surf.mac.Surf-Today"; + PRODUCT_NAME = "A.BIG.T-Today"; + PROVISIONING_PROFILE = "1aff835d-b9fc-4f39-bce3-56c2b6449295"; + PROVISIONING_PROFILE_SPECIFIER = SurfToday; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 696573FF1DE4959B00D95D59 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = ""; + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CODE_SIGN_ENTITLEMENTS = "Surf-Today/Surf_Today.entitlements"; + CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/maclab", + ); + INFOPLIST_FILE = "Surf-Today/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_BUNDLE_IDENTIFIER = "com.abigt.Surf.mac.Surf-Today"; + PRODUCT_NAME = "A.BIG.T-Today"; + PROVISIONING_PROFILE = "4c19f325-3933-49d2-b2a1-32cefdb3d37c"; + PROVISIONING_PROFILE_SPECIFIER = SurfTodayXX; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; + 69C4EE361C2919010020FBF8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6947D7711CE4CE5E0020BBCB /* Surf-Mac.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "Surf-Mac/Surf-Mac.entitlements"; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/maclab", + ); + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "Surf-Mac/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf.mac; + PRODUCT_NAME = A.BIG.T; + PROVISIONING_PROFILE = "6fd5297f-b0c7-44a5-89df-078d148c8357"; + PROVISIONING_PROFILE_SPECIFIER = mac6; + SDKROOT = macosx; + SWIFT_OBJC_BRIDGING_HEADER = "Surf-Mac/$(SWIFT_MODULE_NAME)-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 69C4EE371C2919010020FBF8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6947D7711CE4CE5E0020BBCB /* Surf-Mac.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "Surf-Mac/Surf-Mac.entitlements"; + CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/maclab", + ); + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "Surf-Mac/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf.mac; + PRODUCT_NAME = A.BIG.T; + PROVISIONING_PROFILE = "388485b7-2692-4daf-8690-700c62c9bee9"; + PROVISIONING_PROFILE_SPECIFIER = mac6_store; + SDKROOT = macosx; + SWIFT_OBJC_BRIDGING_HEADER = "Surf-Mac/$(SWIFT_MODULE_NAME)-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; + 69C4EE471C29193D0020FBF8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 698BFE291C3A218000CED9EC /* PacketTunnel-Mac.xcconfig */; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = PacketTunnel/Mac/PacketTunnel_Mac.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/maclab", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + $SSL_LIB_DEFINE, + "$(inherited)", + ); + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/PacketTunnel/Mac/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/share/lib", + ); + MACOSX_DEPLOYMENT_TARGET = 10.12; + OTHER_LDFLAGS = ( + "-lssl", + "-lcrypto", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf.mac.extension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "a231acd3-d2b2-4247-9c38-2f260bd665aa"; + PROVISIONING_PROFILE_SPECIFIER = mac6ext; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "TIMER DEBUG"; + SWIFT_OBJC_BRIDGING_HEADER = "PacketTunnel/Mac/PacketTunnel-Mac-Bridging-Header.h"; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "PacketTunnel/Mac/$(SWIFT_MODULE_NAME)-Swift.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "$(inherited)"; + VALIDATE_PRODUCT = YES; + }; + name = Debug; + }; + 69C4EE481C29193D0020FBF8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 698BFE291C3A218000CED9EC /* PacketTunnel-Mac.xcconfig */; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = PacketTunnel/Mac/PacketTunnel_Mac.entitlements; + CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 745WQDK4L7; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/maclab", + ); + GCC_PREPROCESSOR_DEFINITIONS = $SSL_LIB_DEFINE; + HEADER_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/PacketTunnel/Mac/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/share/lib", + ); + MACOSX_DEPLOYMENT_TARGET = 10.12; + OTHER_LDFLAGS = ( + "-lssl", + "-lcrypto", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.abigt.Surf.mac.extension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "c0f3aac9-899c-44ce-aba2-b27bf823f36d"; + PROVISIONING_PROFILE_SPECIFIER = 222; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = TIMER; + SWIFT_OBJC_BRIDGING_HEADER = "PacketTunnel/Mac/PacketTunnel-Mac-Bridging-Header.h"; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "PacketTunnel/Mac/$(SWIFT_MODULE_NAME)-Swift.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "$(inherited)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 578ED9331C03181300913B2F /* Build configuration list for PBXNativeTarget "PacketTunnel-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 578ED9341C03181300913B2F /* Debug */, + 578ED9351C03181300913B2F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 692D8D051C6A250400C07B3A /* Build configuration list for PBXNativeTarget "SurfToday" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 692D8D061C6A250400C07B3A /* Debug */, + 692D8D071C6A250400C07B3A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 69366E511BFECBE700AE123D /* Build configuration list for PBXProject "Surf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 69366E681BFECBE700AE123D /* Debug */, + 69366E691BFECBE700AE123D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 69366E6A1BFECBE700AE123D /* Build configuration list for PBXNativeTarget "Surf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 69366E6B1BFECBE700AE123D /* Debug */, + 69366E6C1BFECBE700AE123D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 693AAE1D200EDA4F009E481E /* Build configuration list for PBXNativeTarget "Kwazii" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 693AAE1B200EDA4F009E481E /* Debug */, + 693AAE1C200EDA4F009E481E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 693AAE2E200EDF82009E481E /* Build configuration list for PBXNativeTarget "XDataService" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 693AAE2F200EDF82009E481E /* Debug */, + 693AAE30200EDF82009E481E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 696573FD1DE4959B00D95D59 /* Build configuration list for PBXNativeTarget "A.BIG.T-Today" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 696573FE1DE4959B00D95D59 /* Debug */, + 696573FF1DE4959B00D95D59 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 69C4EE351C2919010020FBF8 /* Build configuration list for PBXNativeTarget "A.BIG.T" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 69C4EE361C2919010020FBF8 /* Debug */, + 69C4EE371C2919010020FBF8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 69C4EE461C29193D0020FBF8 /* Build configuration list for PBXNativeTarget "PacketTunnel-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 69C4EE471C29193D0020FBF8 /* Debug */, + 69C4EE481C29193D0020FBF8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 69366E4E1BFECBE700AE123D /* Project object */; +} diff --git a/Surf.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Surf.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..49d2ef4 --- /dev/null +++ b/Surf.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Surf.xcodeproj/project.xcworkspace/xcshareddata/Surf.xccheckout b/Surf.xcodeproj/project.xcworkspace/xcshareddata/Surf.xccheckout new file mode 100644 index 0000000..c861177 --- /dev/null +++ b/Surf.xcodeproj/project.xcworkspace/xcshareddata/Surf.xccheckout @@ -0,0 +1,65 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 34FE85AB-E9B1-464B-874B-3C4878403B82 + IDESourceControlProjectName + project + IDESourceControlProjectOriginsDictionary + + 67620B5EFA902936DF04070AF595B76AB0333747 + https://github.com/Alamofire/Alamofire.git + AACA9EEA20FE12DA3331147805C5AB3BDC660A1A + bitbucket.org:yarshure/surf.git + EE56C236A941500E49A26799499985E2ED028F64 + github.com:yarshure/MMDB-Swift.git + + IDESourceControlProjectPath + Surf.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 67620B5EFA902936DF04070AF595B76AB0333747 + ../..Alamofire/ + AACA9EEA20FE12DA3331147805C5AB3BDC660A1A + ../.. + EE56C236A941500E49A26799499985E2ED028F64 + ../..MMDB/ + + IDESourceControlProjectURL + bitbucket.org:yarshure/surf.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + AACA9EEA20FE12DA3331147805C5AB3BDC660A1A + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 67620B5EFA902936DF04070AF595B76AB0333747 + IDESourceControlWCCName + Alamofire + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + EE56C236A941500E49A26799499985E2ED028F64 + IDESourceControlWCCName + MMDB + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + AACA9EEA20FE12DA3331147805C5AB3BDC660A1A + IDESourceControlWCCName + Surf + + + + diff --git a/Surf.xcodeproj/project.xcworkspace/xcshareddata/Surf.xcscmblueprint b/Surf.xcodeproj/project.xcworkspace/xcshareddata/Surf.xcscmblueprint new file mode 100644 index 0000000..ac59b66 --- /dev/null +++ b/Surf.xcodeproj/project.xcworkspace/xcshareddata/Surf.xcscmblueprint @@ -0,0 +1,121 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "AACA9EEA20FE12DA3331147805C5AB3BDC660A1A", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "5C4B6E5BEABBFDA97ED77F2C420014ABE76ABA21" : 0, + "1C75F1C5CFCB95B3702F6F632FA05ED5244B519E" : 0, + "78CEBD94FC52DCE625058FE6959F9449C7CD4A7B" : 9223372036854775807, + "9FD74FCF0A1D92BBF703284651A70CC0554958A4" : 9223372036854775807, + "834DA2CBF1A005FD462115D8041C6D81D5FB12EF" : 9223372036854775807, + "55011AEBD444630C0E9DF47BD2E18FDBBDCC285D" : 9223372036854775807, + "3AE8ED2E684071AF4FB151FA51BF266B82FF45BD" : 9223372036854775807, + "EE56C236A941500E49A26799499985E2ED028F64" : 0, + "AACA9EEA20FE12DA3331147805C5AB3BDC660A1A" : 0, + "CBF92293916D19D8AA3B5911EB5CE04B7EBCA00D" : 9223372036854775807, + "04101981B66E318109934C9516F88D824BB96459" : 9223372036854775807, + "9FB1FDDBA011002795A1FF5BD3CABFA2F79E6A59" : 9223372036854775807, + "DB7231E74227E06B741062C9E94288CC651E14E2" : 0, + "67620B5EFA902936DF04070AF595B76AB0333747" : 0, + "C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "34FE85AB-E9B1-464B-874B-3C4878403B82", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "5C4B6E5BEABBFDA97ED77F2C420014ABE76ABA21" : "..\/bitbucket\/simpletunnel_hack", + "1C75F1C5CFCB95B3702F6F632FA05ED5244B519E" : "surf\/thirdpart\/", + "78CEBD94FC52DCE625058FE6959F9449C7CD4A7B" : "surf\/GRDB\/", + "9FD74FCF0A1D92BBF703284651A70CC0554958A4" : "libkcp\/", + "834DA2CBF1A005FD462115D8041C6D81D5FB12EF" : "surf30\/external\/SFSocket\/", + "55011AEBD444630C0E9DF47BD2E18FDBBDCC285D" : "surf\/GRDB\/SQLCipher\/src\/", + "3AE8ED2E684071AF4FB151FA51BF266B82FF45BD" : "surf\/GRDB\/Tests\/Performance\/SQLite.swift\/", + "EE56C236A941500E49A26799499985E2ED028F64" : "surf\/MMDB\/", + "AACA9EEA20FE12DA3331147805C5AB3BDC660A1A" : "surf30\/", + "CBF92293916D19D8AA3B5911EB5CE04B7EBCA00D" : "surf\/GRDB\/SQLiteCustom\/src\/", + "04101981B66E318109934C9516F88D824BB96459" : "surf\/GRDB\/Tests\/Performance\/fmdb\/", + "9FB1FDDBA011002795A1FF5BD3CABFA2F79E6A59" : "surf\/GRDB\/Tests\/Performance\/Realm\/", + "DB7231E74227E06B741062C9E94288CC651E14E2" : "", + "67620B5EFA902936DF04070AF595B76AB0333747" : "surf\/Alamofire\/", + "C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3" : "SwiftyJSON\/" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "Surf", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Surf.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ccgus\/fmdb.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "04101981B66E318109934C9516F88D824BB96459" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/robbiehanson\/CocoaAsyncSocket.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "1C75F1C5CFCB95B3702F6F632FA05ED5244B519E" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/stephencelis\/SQLite.swift.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "3AE8ED2E684071AF4FB151FA51BF266B82FF45BD" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/groue\/sqlcipher.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "55011AEBD444630C0E9DF47BD2E18FDBBDCC285D" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "bitbucket.org:yarshure\/simpletunnel_hack.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "5C4B6E5BEABBFDA97ED77F2C420014ABE76ABA21" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Alamofire\/Alamofire.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "67620B5EFA902936DF04070AF595B76AB0333747" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/groue\/GRDB.swift.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "78CEBD94FC52DCE625058FE6959F9449C7CD4A7B" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "bitbucket.org:yarshure\/sfsocket.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "834DA2CBF1A005FD462115D8041C6D81D5FB12EF" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/realm\/realm-cocoa.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "9FB1FDDBA011002795A1FF5BD3CABFA2F79E6A59" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/networkextension\/libkcp.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "9FD74FCF0A1D92BBF703284651A70CC0554958A4" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "bitbucket.org:yarshure\/surf.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "AACA9EEA20FE12DA3331147805C5AB3BDC660A1A" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:SwiftyJSON\/SwiftyJSON.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/swiftlyfalling\/SQLiteLib", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CBF92293916D19D8AA3B5911EB5CE04B7EBCA00D" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "bitbucket.org:yarshure\/simpletunnel.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "DB7231E74227E06B741062C9E94288CC651E14E2" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:yarshure\/MMDB-Swift.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "EE56C236A941500E49A26799499985E2ED028F64" + } + ] +} \ No newline at end of file diff --git a/Surf.xcodeproj/project.xcworkspace/xcuserdata/kiwi.xcuserdatad/UserInterfaceState.xcuserstate b/Surf.xcodeproj/project.xcworkspace/xcuserdata/kiwi.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..9202f13 Binary files /dev/null and b/Surf.xcodeproj/project.xcworkspace/xcuserdata/kiwi.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Surf.xcodeproj/project.xcworkspace/xcuserdata/yarshure.xcuserdatad/WorkspaceSettings.xcsettings b/Surf.xcodeproj/project.xcworkspace/xcuserdata/yarshure.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..ff6fa82 --- /dev/null +++ b/Surf.xcodeproj/project.xcworkspace/xcuserdata/yarshure.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,20 @@ + + + + + BuildLocationStyle + UseAppPreferences + CustomBuildIntermediatesPath + Build/Intermediates + CustomBuildLocationType + RelativeToWorkspace + CustomBuildProductsPath + Build/Products + DerivedDataLocationStyle + Default + IssueFilterStyle + ShowActiveSchemeOnly + LiveSourceIssuesEnabled + + + diff --git a/Surf.xcodeproj/xcshareddata/xcschemes/A.BIG.T.xcscheme b/Surf.xcodeproj/xcshareddata/xcschemes/A.BIG.T.xcscheme new file mode 100644 index 0000000..abbd882 --- /dev/null +++ b/Surf.xcodeproj/xcshareddata/xcschemes/A.BIG.T.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcshareddata/xcschemes/PacketTunnel-Mac.xcscheme b/Surf.xcodeproj/xcshareddata/xcschemes/PacketTunnel-Mac.xcscheme new file mode 100644 index 0000000..d22e800 --- /dev/null +++ b/Surf.xcodeproj/xcshareddata/xcschemes/PacketTunnel-Mac.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcshareddata/xcschemes/PacketTunnel-iOS.xcscheme b/Surf.xcodeproj/xcshareddata/xcschemes/PacketTunnel-iOS.xcscheme new file mode 100644 index 0000000..9e44aca --- /dev/null +++ b/Surf.xcodeproj/xcshareddata/xcschemes/PacketTunnel-iOS.xcscheme @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcshareddata/xcschemes/Surf-Today.xcscheme b/Surf.xcodeproj/xcshareddata/xcschemes/Surf-Today.xcscheme new file mode 100644 index 0000000..13f64eb --- /dev/null +++ b/Surf.xcodeproj/xcshareddata/xcschemes/Surf-Today.xcscheme @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcshareddata/xcschemes/Surf.xcscheme b/Surf.xcodeproj/xcshareddata/xcschemes/Surf.xcscheme new file mode 100644 index 0000000..b866a39 --- /dev/null +++ b/Surf.xcodeproj/xcshareddata/xcschemes/Surf.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcshareddata/xcschemes/SurfToday.xcscheme b/Surf.xcodeproj/xcshareddata/xcschemes/SurfToday.xcscheme new file mode 100644 index 0000000..e757315 --- /dev/null +++ b/Surf.xcodeproj/xcshareddata/xcschemes/SurfToday.xcscheme @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/PacketTunnel.xcscheme b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/PacketTunnel.xcscheme new file mode 100644 index 0000000..8488290 --- /dev/null +++ b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/PacketTunnel.xcscheme @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/SimpleTunnelServices.xcscheme b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/SimpleTunnelServices.xcscheme new file mode 100644 index 0000000..2fcab26 --- /dev/null +++ b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/SimpleTunnelServices.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/Surf.xcscheme b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/Surf.xcscheme new file mode 100644 index 0000000..b3b96e0 --- /dev/null +++ b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/Surf.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/xcschememanagement.plist b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..6c9e0f7 --- /dev/null +++ b/Surf.xcodeproj/xcuserdata/kiwi.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,47 @@ + + + + + SchemeUserState + + PacketTunnel.xcscheme + + orderHint + 1 + + SimpleTunnelServices.xcscheme + + orderHint + 2 + + Surf.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 578ED90C1C03096300913B2F + + primary + + + 578ED9281C03181200913B2F + + primary + + + 691B36761C0F5BD7001C815D + + primary + + + 69366E551BFECBE700AE123D + + primary + + + + + diff --git a/Surf.xcodeproj/xcuserdata/yarshure.xcuserdatad/xcschemes/xcschememanagement.plist b/Surf.xcodeproj/xcuserdata/yarshure.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..7903891 --- /dev/null +++ b/Surf.xcodeproj/xcuserdata/yarshure.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,137 @@ + + + + + SchemeUserState + + A.BIG.T.xcscheme_^#shared#^_ + + orderHint + 5 + + Kwazii.xcscheme + + orderHint + 6 + + PacketTunnel-Mac.xcscheme_^#shared#^_ + + orderHint + 1 + + PacketTunnel-iOS.xcscheme_^#shared#^_ + + orderHint + 3 + + Preference.xcscheme + + orderHint + 8 + + Surf-Today.xcscheme_^#shared#^_ + + orderHint + 4 + + Surf.xcscheme_^#shared#^_ + + orderHint + 0 + + SurfToday.xcscheme_^#shared#^_ + + orderHint + 2 + + TestService.xcscheme + + orderHint + 7 + + XDataService.xcscheme + + orderHint + 7 + + + SuppressBuildableAutocreation + + 578ED9281C03181200913B2F + + primary + + + 691B36761C0F5BD7001C815D + + primary + + + 692D8CF61C6A250400C07B3A + + primary + + + 69366E551BFECBE700AE123D + + primary + + + 6938E6301D387E1A00671B96 + + primary + + + 6938E6431D3889F100671B96 + + primary + + + 696573D81DE4953000D95D59 + + primary + + + 696573EB1DE4959B00D95D59 + + primary + + + 696B74D81C3B9C8900BFCA89 + + primary + + + 6989A4FE1C31042D00DD1435 + + primary + + + 69A85E311C29650900CE8F03 + + primary + + + 69BC94B01C29A35A00F7974C + + primary + + + 69C4EE281C2919010020FBF8 + + primary + + + 69C4EE3B1C29193D0020FBF8 + + primary + + + 69DA64D11C291FD300DC174C + + primary + + + + + diff --git a/Surf/AcknowledgeViewController.swift b/Surf/AcknowledgeViewController.swift new file mode 100644 index 0000000..13bac21 --- /dev/null +++ b/Surf/AcknowledgeViewController.swift @@ -0,0 +1,137 @@ +// +// AcknowledgeViewController.swift +// Surf +// +// Created by abigt on 15/12/3. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit + +class AcknowledgeViewController: UIViewController { + + var headers: [String: String] = [:] + var body: String? + var elapsedTime: TimeInterval? + var segueIdentifier: String? + @IBOutlet weak var textView:UITextView? +// var request: Request? { +// didSet { +// oldValue?.cancel() +// +// title = request?.description +// //refreshControl?.endRefreshing() +// headers.removeAll() +// body = nil +// elapsedTime = nil +// } +// } + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Acknowledge" + + + +// let destination = Request.suggestedDownloadDestination( +// directory: .CachesDirectory, +// domain: .UserDomainMask +// ) + //self.request = download(.GET, "http://baike.baidu.com", destination: destination) + + //let req = request(.GET, "http://baike.baidu.com", parameters: nil) + // Do any additional setup after loading the view. + //edgesForExtendedLayout = .All + //preferredContentSize = CGSize.init(width: 0, height: 64) + //textView?.contentInset = UIEdgeInsetsMake(64.0,0.0,0,0.0); + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + let path = Bundle.main.path(forResource: "thanks.txt", ofType: nil) + guard let p = path else {return} + let str = try! NSString.init(contentsOfFile: p, encoding: String.Encoding.utf8.rawValue) + self.textView?.text = str as String + } + private func downloadedBodyString() -> String { + let fileManager = FileManager.default + let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0] + + do { + let contents = try fileManager.contentsOfDirectory( + at: cachesDirectory, + includingPropertiesForKeys: nil, + options: .skipsHiddenFiles + ) + + if let + fileURL = contents.first, + let data = NSData(contentsOf: fileURL) + { + print(data) + let json = try JSONSerialization.jsonObject(with: data as Data, options: JSONSerialization.ReadingOptions()) + let prettyData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) + + if let prettyString = NSString(data: prettyData, encoding: String.Encoding.utf8.rawValue) as String? { + try FileManager.default.removeItem(at: fileURL) + return prettyString + } + } + } catch { + // No-op + } + + return "" + } + @IBAction func refresh() { +// guard let request = request else { +// return +// } +// +// //refreshControl?.beginRefreshing() +// +// let start = CACurrentMediaTime() +// request.responseString { response in +// let end = CACurrentMediaTime() +// self.elapsedTime = end - start +// +// if let response = response.response { +// for (field, value) in response.allHeaderFields { +// self.headers["\(field)"] = "\(value)" +// } +// } +// +// if let segueIdentifier = self.segueIdentifier { +// switch segueIdentifier { +// case "GET", "POST", "PUT", "DELETE": +// self.body = response.result.value +// case "DOWNLOAD": +// self.body = self.downloadedBodyString() +// default: +// break +// } +// } +// +// +// } + } +// override func viewDidAppear(animated: Bool) { +// super.viewDidAppear(animated) +// +// refresh() +// } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/AddEditProxyController.swift b/Surf/AddEditProxyController.swift new file mode 100644 index 0000000..9eacde2 --- /dev/null +++ b/Surf/AddEditProxyController.swift @@ -0,0 +1,645 @@ +// +// AddEditController.swift +// Surf +// +// Created by kiwi on 15/11/20. +// Copyright © 2015年 abigt. All rights reserved. +// + +import Foundation +import UIKit +import SFSocket +import Photos +import AssetsLibrary +import XRuler +enum UIUserInterfaceIdiom : Int { + case Unspecified + + case Phone // iPhone and iPod touch style UI + case Pad // iPad style UI +} +class MiscCell: UITableViewCell { + @IBOutlet weak var button:UIButton? +} +/// The tunnel delegate protocol. +protocol AddEditProxyDelegate:class { + func addProxyConfig(_ controller: AddEditProxyController, proxy:SFProxy)// + func editProxyConfig(_ controller: AddEditProxyController, proxy:SFProxy)// +} +let label:[String] = ["Server","Port","Username","Password","TLS","KCPTUN","KCPTUN parameter"] +let tlsAlert = "Note:if enable TLS,Server value must domain name".localized +let supported_ciphers = [ + "rc4", + "rc4-md5", + "aes-128-cfb", + "aes-192-cfb", + "aes-256-cfb", + "bf-cfb", + "cast5-cfb", + "des-cfb", + "rc2-cfb", + "salsa20", + "chacha20", + "chacha20-ietf" +] +let supported_ciphers_press = "aes" +class SegmentCell:UITableViewCell { + @IBOutlet weak var segement:UISegmentedControl! +} +import Xcon +public class AddEditProxyController: SFTableViewController ,BarcodeScanDelegate,SFMethodDelegate + //UIImagePickerControllerDelegate,UINavigationControllerDelegate +{ + var numberOfSetting: Int = 0 + var useCamera:Bool = true + var proxy:SFProxy! + var qrImage:UIImage? + var chain:Bool = false + //var config:String = "" //fn + weak var delegate:AddEditProxyDelegate? + + var add:Bool = false + var textFields = NSMutableArray() + var firstLoad:Bool = true + + var addressField:UITextField? + var portField:UITextField? + var usernameField:UITextField? + var passwordField:UITextField? + var kcpparamterField:UITextField? + var proxyNameField:UITextField? + //@IBOutlet weak var contro:UISegmentedControl! + + override public func viewDidLoad() { + super.viewDidLoad() + self.title = "Proxy Config".localized + //NSTimer.scheduledTimerWithTimeInterval(1.0, target: self.tableView, selector: "reloadData", userInfo: nil, repeats: false) + //config.proxyName = "Surf" + self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action:#selector(AddEditProxyController.saveConfig(_:))) + + if proxy == nil { + proxy = SFProxy.create(name: "PROXY", type: .SS, address: "", port: "", passwd: "", method: "aes-256-cfb",tls: false) + add = true + } + + } + + @IBAction func valueChanged(sender:UISegmentedControl){ + let index = sender.selectedSegmentIndex + //AxLogger.log("\(sender.titleForSegmentAtIndex(index))") + print(index) + if firstLoad { + var indext = 0 + if proxy.type == .HTTPS || proxy.type == .HTTP{ + indext = 0 + }else { + indext = 1 + } + sender.selectedSegmentIndex = indext + firstLoad = false + return + } + if proxy.method == supported_ciphers_press { + proxy.type = .HTTPAES + } + if index == 0 { + proxy.type = .HTTP + }else if index == 1{ + proxy.type = .SOCKS5 + for method in supported_ciphers { + if method == proxy.method { + proxy.type = .SS + return + } + } + } + + + + } + func saveConfigTemp(){ + proxy.serverAddress = self.addressField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.proxyName = self.proxyNameField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.serverPort = self.portField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.method = self.usernameField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.password = self.passwordField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + } + @IBAction func saveConfig(_ sender: AnyObject){ + //guard let d = self.delegate else{ return } + + if proxy.kcptun { + if !verifyReceipt(.KCP) { + + changeToBuyPage() + return + } + } + proxy.serverAddress = self.addressField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.proxyName = self.proxyNameField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.serverPort = self.portField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.method = self.usernameField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + proxy.password = self.passwordField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + //proxy.mode = self.kcpparamterField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + if proxy.proxyName.isEmpty || proxy.serverAddress.isEmpty || proxy.serverPort.isEmpty { + alertMessageAction("Config Invalid!".localized,complete: nil) + } + + + + if proxy.type == .SS { + var found = false + for method in supported_ciphers { + if method == proxy.method { + found = true + + break + } + } + if found == false { + alertMessageAction("Method Invalid".localized, complete: nil) + return + } + if proxy.password.isEmpty { + alertMessageAction("Empty Password".localized, complete: nil) + return + } + } + + + if proxy.tlsEnable { + + } + + if let port = Int(proxy.serverPort) { + if port == 0 || port > 65535 { + alertMessageAction("\(proxy.serverPort) invalid ",complete: nil) + return + } + + }else { + //crash here + alertMessageAction("\(proxy.serverPort) invalid ",complete: nil) + return + } + + if let d = delegate { + if add { + d.addProxyConfig(self, proxy: proxy) + }else { + d.editProxyConfig(self, proxy: proxy) + } + }else { + _ = ProxyGroupSettings.share.addProxy(proxy) + } + + + + _ = self.navigationController?.popViewController(animated: true) + } + @IBAction func useBarcode(_ sender: AnyObject) { + self.performSegue(withIdentifier: "showBarCode", sender: sender) + + + + } + + func convertConfigString(configString: String){ + let r = SFProxy.createProxyWithURL(configString) + if let proxy = r.proxy { + self.proxy = proxy + tableView.reloadData() + }else { + alertMessageAction(r.message, complete: nil) + } + + + + + } + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + //self.tableView.reloadData() + } + public func barcodeScanDidScan(controller: BarcodeScanViewController, configString:String){ + + if self.presentedViewController == controller { + self.dismiss(animated: true, completion: { () -> Void in + + }) + + } + + self.convertConfigString(configString: configString) + + } + public func barcodeScanCancelScan(controller: BarcodeScanViewController){ + if self.presentedViewController == controller { + self.dismiss(animated: true, completion: { () -> Void in + + }) + + } + + } + override public func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if segue.identifier == "showBarCode"{ + guard let barCodeController = segue.destination as? BarcodeScanViewController else{return} + //barCodeController.useCamera = self.useCamera + barCodeController.delegate = self + //barCodeController.navigationItem.title = "Add Proxy" + + }else if segue.identifier == "showImage"{ + guard let vc = segue.destination as? ImageViewController else{return} + vc.image = qrImage! + + }else if segue.identifier == "showKcp"{ + guard let vc = segue.destination as? KcpTableViewController else{return} + vc.kcpinfo = self.proxy.config + } + + } + @IBAction func saveConfigToImage(_ sender: AnyObject) { + generateQRCodeScale(scale: 10.0) + } + func generateQRCodeScale(scale:CGFloat){ + // + // ss://aes-256-cfb:fb4b532cb4180c9037c5b64bb3c09f7e@108.61.126.194:14860" + + let base64Encoded = proxy.base64String() + let stringData = base64Encoded.data(using: .utf8, allowLossyConversion: false) + let filter = CIFilter(name: "CIQRCodeGenerator") + guard let f = filter else { + return + } + f.setValue(stringData, forKey: "inputMessage") + f.setValue("M", forKey: "inputCorrectionLevel") + guard let image = f.outputImage else { + return + } + let cgImage = CIContext(options:nil).createCGImage(image, from: image.extent) + UIGraphicsBeginImageContext(CGSize(width:image.extent.size.width*scale, height:image.extent.size.height*scale)) + let context = UIGraphicsGetCurrentContext() + context!.interpolationQuality = .none + //CGContextDrawImage(context!,context!.boundingBoxOfClipPath,cgImage!) + context!.draw(cgImage!, in: context!.boundingBoxOfClipPath, byTiling: false) +// if let appIcon = UIImage.init(named: "logo.png") { +// context!.translateBy(x: 0, y: image.extent.size.height*scale) +// context!.scaleBy(x: 1, y: -1) +// let r = CGRect(x:image.extent.size.width*scale/2-120/2, y:image.extent.size.width*scale/2-120/2,width: 120, height:120) +// appIcon.draw(in: r) +// } + + let output = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + //CGImageRelease(cgImage); + let qrImage = UIImage(cgImage: output!.cgImage!, scale: output!.scale, orientation: .downMirrored) + self.qrImage = qrImage + performSegue(withIdentifier: "showImage", sender: nil) + } + + + + public override func numberOfSections(in tableView: UITableView) -> Int { + + return 3 + } + override public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch section { + case 0: + return 1 + case 1: + if proxy.kcptun { + return 8 + } + return 7 + case 2: + return 2 + default: + return 0 + } + } + public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + switch section { + case 0: + return "NAME".localized + case 1: + return "PROXY".localized + case 2: + return "MISC".localized + default: + return "" + } + } + public override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { + + switch section { + case 1: + return tlsAlert + default: + return "" + } + } + +// override public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath){ +// if indexPath.section == 1 && indexPath.row == 0 { +// let c = cell as! SegmentCell +// var index = 0 +// if proxy.type.rawValue < 2 { +// index = proxy.type.rawValue +// }else { +// index = 2 +// } +// c.segement.selectedSegmentIndex == index +// } +// } + @objc func tlsChanged(_ sender:UISwitch) { + let on = sender.isOn + proxy.tlsEnable = on + } + func proxyChainAction(_ sender:UISwitch){ + chain = sender.isOn + } + @objc func kcpEnableAction(_ sender:UISwitch){ + + + + let x = IndexPath.init(row: 7, section: 1) + proxy.kcptun = sender.isOn + if proxy.kcptun { + + tableView.insertRows(at: [x], with: UITableViewRowAnimation.none) + }else { + tableView.deleteRows(at: [x], with: UITableViewRowAnimation.none) + } + + } + public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + switch indexPath.section { + case 0: + let cell = tableView.dequeueReusableCell(withIdentifier: "textfield-cell") as! TextFieldCell + cell.cellLabel?.text = "Name".localized + cell.textField.text = proxy.proxyName + cell.wwdcStyle() + self.proxyNameField = cell.textField + + + return cell + case 1: + if indexPath.row == 0{ + + let cell = tableView.dequeueReusableCell(withIdentifier: "textfield-cell") as! TextFieldCell + cell.cellLabel?.text = "Type".localized + cell.textField.text = proxy.type.description + cell.textField.isEnabled = false + + cell.wwdcStyle() + + return cell + }else { + if indexPath.row == 5 || indexPath.row == 6 { + let cell = tableView.dequeueReusableCell(withIdentifier: "Advance", for: indexPath as IndexPath) as! AdvancedCell + + cell.wwdcStyle() + switch indexPath.row { + case 5: + + if proxy.type == .SS { + cell.label.text = "One Time Auth".localized + }else { + cell.label.text = label[indexPath.row-1].localized + } + cell.s.isOn = proxy.tlsEnable + + + + + cell.s.addTarget(self, action: #selector(AddEditProxyController.tlsChanged(_:)), for: .valueChanged) + return cell + + case 6: + + + cell.label.text = label[indexPath.row-1].localized + cell.s.isOn = proxy.kcptun + cell.s.addTarget(self, action: #selector(AddEditProxyController.kcpEnableAction(_:)), for: .valueChanged) + return cell + default: + return cell + } + + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "textfield-cell") as! TextFieldCell + cell.cellLabel?.text = label[indexPath.row-1].localized + var placeHold:String = "" + + cell.wwdcStyle() + + switch indexPath.row{ + case 1: + cell.textField.text = proxy.serverAddress + self.addressField = cell.textField +// cell.valueChanged = { [weak self] (textfield:UITextField) -> Void in +// self!.proxy.serverAddress = textfield.text!..trimmingCharacters(in: .whitespacesAndNewlines) +// } + placeHold = "server address or ip".localized + case 2: + cell.textField.text = proxy.serverPort + self.portField = cell.textField + cell.textField.keyboardType = .decimalPad +// cell.valueChanged = { [weak self] (textfield:UITextField) -> Void in +// self!.proxy.serverPort = textfield.text!..trimmingCharacters(in: .whitespacesAndNewlines) +// } + placeHold = "server port" + case 3: + + cell.textField.text = proxy.method + self.usernameField = cell.textField + if proxy.type == .SS { + placeHold = "value" + cell.cellLabel?.text = "Method".localized + cell.textField.isEnabled = false + }else { + cell.textField.isEnabled = true + placeHold = "option" +// cell.valueChanged = { [weak self] (textfield:UITextField) -> Void in +// self!.proxy.method = textfield.text!..trimmingCharacters(in: .whitespacesAndNewlines) +// } + } + + case 4: + + cell.textField.text = proxy.password + cell.textField.isSecureTextEntry = true + if proxy.type == .SS{ + placeHold = "value" + }else { + placeHold = "option" + } + self.passwordField = cell.textField +// cell.valueChanged = { [weak self] (textfield:UITextField) -> Void in +// self!.proxy.password = textfield.text!..trimmingCharacters(in: .whitespacesAndNewlines) +// } + + case 7: + //cell.textField.text = proxy.mode//kcptun + self.kcpparamterField = cell.textField + placeHold = "paramter" + self.kcpparamterField?.isHidden = true + cell.cellLabel?.text = label[indexPath.row-1] + cell.textField.isEnabled = true + + default: + break + } + + let s = NSMutableAttributedString(string:placeHold) + //let r = (title as NSString) + s.addAttributes([NSAttributedStringKey.foregroundColor:UIColor.cyan], range: NSMakeRange(0, placeHold.count)) + cell.textField?.attributedPlaceholder = s + return cell + } + + } + + case 2: + var iden:String + if indexPath.row == 0 { + iden = "barcodescan" + }else { + iden = "barcodesave" + } + let cell = tableView.dequeueReusableCell(withIdentifier: iden) as! MiscCell + if ProxyGroupSettings.share.wwdcStyle { + cell.button?.setTitleColor(UIColor.white, for: .normal) + }else { + cell.button?.setTitleColor(UIColor.black, for: .normal) + } + + + return cell + default: + break + } + return UITableViewCell() + } + public override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + + if let cell = tableView.cellForRow(at: indexPath) { + if let x = cell as? TextFieldCell{ + if indexPath.section == 1 { + if indexPath.row == 0 { + return indexPath + }else if indexPath.row == 3{ + if proxy.type == .SS { + return indexPath + }else { + x.textField.becomeFirstResponder() + } + }else { + if x.textField.isHidden { + return indexPath + }else { + x.textField.becomeFirstResponder() + } + + } + }else { + x.textField.becomeFirstResponder() + } + + } + + } + + + return nil + } + public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + if indexPath.section == 1 && indexPath.row == 0 { + + if verifyReceipt(.HTTP) { + showSelectType() + }else { + changeToBuyPage() + } + + + + }else if indexPath.section == 1 && indexPath.row == 3{ + showMethodSelect() + }else if indexPath.section == 1 && indexPath.row == 7 { + self.performSegue(withIdentifier: "showKcp", sender: nil) + }else { + tableView.deselectRow(at: indexPath as IndexPath, animated: false) + } + } + func showMethodSelect(){ + // 临时保存数据 + saveConfigTemp() + let st = UIStoryboard.init(name: "SSMethod", bundle: nil) + guard let vc = st.instantiateInitialViewController() as? SFMethodViewController else {return } + vc.delegate = self + self.navigationController?.pushViewController(vc, animated: true) + } + func didSelectMethod(controller: SFMethodViewController, method:String){ + if proxy.type == .SS { + proxy.method = method + tableView.reloadData() + } + } + func showSelectType() { + + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + style = .actionSheet + break + + } + guard let indexPath = tableView.indexPathForSelectedRow else {return} + + //let result = results[indexPath.row] + let alert = UIAlertController.init(title: "Alert".localized, message: "Please Select Proxy Type".localized, preferredStyle: style) + + let action = UIAlertAction.init(title: "HTTP", style: .default) {[unowned self ] (action:UIAlertAction) -> Void in + + self.proxy.type = .HTTP + + self.tableView.deselectRow(at: indexPath, animated: true) + self.tableView.reloadData() + } + let action1 = UIAlertAction.init(title: "SOCKS5", style: .default) { [unowned self ] (action:UIAlertAction) -> Void in + + self.proxy.type = .SOCKS5 + self.tableView.deselectRow(at: indexPath, animated: true) + self.tableView.reloadData() + } + let action2 = UIAlertAction.init(title: "SS", style: .default) { [unowned self ] (action:UIAlertAction) -> Void in + + self.proxy.type = .SS + self.tableView.deselectRow(at: indexPath, animated: true) + self.tableView.reloadData() + } + let cancle = UIAlertAction.init(title: "Cancel".localized, style: .cancel) { [unowned self ] (action:UIAlertAction) -> Void in + + self.tableView.deselectRow(at: indexPath, animated: true) + } + alert.addAction(action) + alert.addAction(action1) + alert.addAction(action2) + alert.addAction(cancle) + self.present(alert, animated: true) { () -> Void in + + } + + } + + +} diff --git a/Surf/AnalyzeTableViewController.swift b/Surf/AnalyzeTableViewController.swift new file mode 100644 index 0000000..aff7f76 --- /dev/null +++ b/Surf/AnalyzeTableViewController.swift @@ -0,0 +1,515 @@ +// +// AnalyzeTableViewController.swift +// Surf +// +// Created by abigt on 16/2/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import NetworkExtension +import SwiftyJSON +import SFSocket +import CoreTelephony +import Fabric +import SystemKitiOS +import IoniconsSwift +import XRuler +extension SFVPNStatistics{ + func status() ->NSAttributedString { + let txt = "\u{f35a}\t\(self.runing)" + " Memory: " + self.memoryString() + let s = NSMutableAttributedString(string:txt) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + } + func speed() ->NSAttributedString{ + let text = "Speed: \(self.lastTraffice.report())" + let s = NSMutableAttributedString(string:text) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + + + } + func maxspeed() ->NSAttributedString{ + let text = "Max Speed: \(self.maxTraffice.report())" + let s = NSMutableAttributedString(string:text) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + + } + func cell() ->NSAttributedString{ + let text = "Total: \(self.totalTraffice.reportTraffic())" + let s = NSMutableAttributedString(string:text) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + + } + func wifi() ->NSAttributedString{ + let text = "\u{f25c} \(self.wifiTraffice.reportTraffic())" + let s = NSMutableAttributedString(string:text) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + + + //let text = "DIRECT: \(self.directTraffice.reportTraffic())" + } + func direct() ->NSAttributedString{ + let text = "PROXY: \(self.proxyTraffice.reportTraffic())" + let s = NSMutableAttributedString(string:text) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + + } + func proxy() ->NSAttributedString{ + + let text = "CELL: \(self.cellTraffice.reportTraffic())" + let s = NSMutableAttributedString(string:text) + let f = UIFont.init(name: "Ionicons", size: 20)! + s.addAttributes([NSAttributedStringKey.font:f], range: NSMakeRange(0, 1)) + return s + + } +} +class StatusCell: UITableViewCell { + @IBOutlet weak var catLabel:UILabel! + @IBOutlet weak var upLabel:UILabel! + @IBOutlet weak var upInfoLabel:UILabel! + @IBOutlet weak var downLabel:UILabel! + @IBOutlet weak var downInfoLabel:UILabel! + func updateUI() { + if ProxyGroupSettings.share.wwdcStyle { + catLabel.textColor = UIColor.white + downLabel.textColor = UIColor.white + downInfoLabel.textColor = UIColor.white + upLabel.textColor = UIColor.white + upInfoLabel.textColor = UIColor.white + }else { + catLabel.textColor = UIColor.black + downLabel.textColor = UIColor.black + downInfoLabel.textColor = UIColor.black + upLabel.textColor = UIColor.black + upInfoLabel.textColor = UIColor.black + } + } +} +class AnalyzeTableViewController: SFTableViewController { + + var report:SFVPNStatistics = SFVPNStatistics.shared + //var last:SFInterfaceTraffic = SFInterfaceTraffic() + let df = DateFormatter() + var charts:[Double] = [] + let info = CTTelephonyNetworkInfo() + var lastreportDate = Date() + @IBOutlet weak var chartsView:ChartsView! + var reportTimer:Timer? + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.navigationController?.tabBarItem.image = Ionicons.statsBars.image(30) + self.navigationController?.tabBarItem.title = "Analyze".localized + self.title = "Analyze".localized + } + override func viewDidLoad() { + super.viewDidLoad() + + df.dateFormat = "yyyy/MM/dd HH:mm:ss" + self.title = "Analyze".localized + + //self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(title: "Refresh", style: .plain, target: self, action: #selector(requestReportXPC(_:))) + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat{ + + return 48 + } + func startTimer() { + if let m = SFVPNManager.shared.manager, m.isEnabled{ + if reportTimer == nil { + reportTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(AnalyzeTableViewController.requestReportXPC(_:)), userInfo: nil, repeats: true) + return + }else { + if let t = reportTimer, !(t.isValid) { + reportTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(AnalyzeTableViewController.requestReportXPC(_:)), userInfo: nil, repeats: true) + } + } + + }else { + if reportTimer == nil { + reportTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(AnalyzeTableViewController.requestReport(_:)), userInfo: nil, repeats: true) + return + }else { + if let t = reportTimer, !(t.isValid) { + reportTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(AnalyzeTableViewController.requestReport(_:)), userInfo: nil, repeats: true) + } + } + + } + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + startTimer() + + } + override func viewDidDisappear(_ animated: Bool) { + super.viewWillAppear(animated) + reportTimer?.invalidate() + } + @objc func requestReport(_ timer:Timer){ + let now = getInterfaceTraffic() + if now.TunSent != 0 && now.TunReceived != 0 { + //report.lastTraffice.tx = now.TunSent - + report.lastTraffice.tx = UInt(now.TunSent) - report.totalTraffice.tx + report.lastTraffice.rx = UInt(now.TunReceived) - report.totalTraffice.rx + charts.append(Double(report.lastTraffice.tx/1024)) + report.updateMax() + report.totalTraffice.tx = UInt(now.TunSent) + report.totalTraffice.rx = UInt(now.TunReceived) + + + } + tableView.reloadData() + } + @objc func requestReportXPC(_ timer:Timer) { + //print("000") + //let d0 = Date() + //mylog("---- status:") + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + //print("\(m.protocolConfiguration)") + let date = NSDate() + let me = SFVPNXPSCommand.STATUS.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8) + + { + do { + try session.sendProviderMessage(message) { [weak self] response in + // print("------\(Date()) %0.2f",Date().timeIntervalSince(d0)) + if response != nil { + self!.processData(data: response!) + //print("------\(Date()) %0.2f",Date().timeIntervalSince(d0)) + } else { + //self!.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + //alertMessageAction("Failed to Get result ",complete: nil) + } + }else { + //alertMessageAction("Connection not Stated",complete: nil) + } + }else { + //alertMessageAction("message dont init",complete: nil) + tableView.reloadData() + } + + } + +// func flowProcess(data:Data){ +// +// let obj = try! JSON.init(data: data) +// if obj.error == nil { +// //alertMessageAction("message dont init",complete: nil) +// report.netflow.mapObject(j: obj["netflow"]) +// chartsView.updateFlow(report.netflow) +// } +// +// } + func processData(data:Data) { + + //results.removeAll() + //print("111") + //let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) + let obj = try! JSON.init(data: data) + if obj.error == nil { + + //alertMessageAction("message dont init",complete: nil) + report.map(j: obj) + + + + + //bug here + if let m = SFVPNManager.shared.manager, m.connection.status == .connected{ + chartsView.updateFlow(report.netflow) + chartsView.isHidden = false + }else { + chartsView.isHidden = true + } + + + tableView.reloadData() + //tableView.reloadSections(, with: .automatic) + + } + + } + deinit { + + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + //showStat + //showResult + //showRecent + //showLog +// override func prepare(for segue: UIStoryboardSegue, sender: Any?) { +// +// } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + + + tableView.deselectRow(at: indexPath, animated: true) + var iden:String + var show:Bool = false + switch indexPath.section { + case 1: + if indexPath.row == 0 { + iden = "showRecent" + }else { + iden = "showResult" + } +// case 1: +// iden = "showStat" + case 0: + iden = "showRouter" + show = true + default: + show = true + iden = "showLog" + } + show = true + + + +// if let manager = SFVPNManager.shared.manager where manager.connection.status == .Connected { +// show = true +// } + self.performSegue(withIdentifier: iden,sender:indexPath) + + } + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + return 3 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + switch section { + + case 1: + return 2 + case 0: + if let manager = SFVPNManager.shared.manager, manager.connection.status == .connected{ + + if let _ = info.subscriberCellularProvider { + return 8 + } + return 7 + }else { + return 0 + } +// if showStart(){ +// +// return 4+4 //tra +// }else { +// return 0 +// } + case 2: + return 1 + default: + break + } + return 0 + } + + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + +// Recent Requests +// Rule Test Results +// Statistics +// Logs + var cell:UITableViewCell? + switch indexPath.section { + case 1: + cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath ) + + if indexPath.row == 0 { + cell?.textLabel?.text = "Recent Requests".localized + }else { + cell?.textLabel?.text = "Rule Test Results".localized + } + cell?.textLabel?.font = UIFont.systemFont(ofSize: 17.0) + case 0: + let cell = tableView.dequeueReusableCell(withIdentifier: "StatusCell", for: indexPath ) as! StatusCell + configCell(cell: cell,indexPath: indexPath) + + return cell +// case 0: +// let cell = tableView.dequeueReusableCell(withIdentifier: "chartCell", for: indexPath ) as! ChartsCell +// +// +// +// return cell + default: + cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath ) + + + cell?.textLabel?.text = "Sessions".localized + + } + cell?.updateStandUI() + + return cell! + // Configure the cell... + + } + + func configCell(cell:StatusCell, indexPath:IndexPath){ + //print("$$$$ \(report.lastTraffice.rx)") + var flag = false + if let manager = SFVPNManager.shared.manager, manager.connection.status == .connected{ + flag = true + }else { + //flag = showStart() + + } + if !flag { + + return + } + let now = Date() + var reportAnswers = true + + if now.timeIntervalSince(lastreportDate) > 5 { + //reportAnswers = true + lastreportDate = now + } + + // + + let f = UIFont.init(name: "Ionicons", size: 20)! + cell.downLabel.text = "\u{f35d}" + cell.downLabel.font = f + cell.upLabel.text = "\u{f366}" + cell.upLabel.font = f + + cell.updateUI() + + + if flag { + + + func memoryUnit(_ value: Double) -> String { + if value < 1.0 { return String(Int(value * 1000.0)) + "MB" } + else { return NSString(format:"%.2f", value) as String + "GB" } + } + + switch indexPath.row { + + case 0: + let memoryUsage = System.memoryUsage() + cell.catLabel.text = "\u{f3b3}" + cell.downInfoLabel.text = memoryUnit(memoryUsage.free) + " " + report.memoryString() + cell.downLabel.isHidden = true + cell.upLabel.isHidden = true + cell.upInfoLabel.text = report.runing + if reportAnswers { + Answers.logCustomEvent(withName: "Running", + customAttributes: [ + "Memory": report.memoryUsed, + "Second": Int(now.timeIntervalSince(report.sessionStartTime)), + ]) + } + return + case 1: + + infoFor(cell: cell, icon: "\u{f4af}", report: report.lastTraffice, speed: true) + case 2: + + + infoFor(cell: cell, icon: "\u{f4b0}", report: report.maxTraffice, speed: true) + case 3: + + + infoFor(cell: cell, icon: "\u{f37c}", report: report.totalTraffice, speed: false) + case 4: + + infoFor(cell: cell, icon: "\u{f394}", report: report.directTraffice, speed: false) + case 5: + + infoFor(cell: cell, icon: "\u{f4a8}", report: report.proxyTraffice, speed: false) + case 6: + + + + infoFor(cell: cell, icon: "\u{f25c}", report: report.wifiTraffice, speed: false) + case 7: + + infoFor(cell: cell, icon: "\u{f274}", report: report.cellTraffice, speed: false) + default: + break + } + //print("TCP Connection: \(report.connectionCount) memory:\(report.memoryUsed) ") + }else { + cell.textLabel?.text = "Session Not Start".localized + cell.catLabel.isHidden = true + cell.downLabel.isHidden = true + cell.downInfoLabel.isHidden = true + cell.upLabel.isHidden = true + cell.upInfoLabel.isHidden = true + } + cell.downLabel.isHidden = false + cell.upLabel.isHidden = false + } + + + + func infoFor(cell:StatusCell,icon:String,report:SFTraffic,speed:Bool) { + cell.upInfoLabel.text = report.toString(x: report.tx,label: "",speed: speed) + cell.downInfoLabel.text = report.toString(x: report.rx,label: "",speed: speed) + cell.catLabel.text = icon + } + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + if segue.identifier == "showRouter" { + guard let vc = segue.destination as? LogFileViewController else {return} + if let index = sender as? IndexPath { + if index.section == 0 { + vc.showRouter = true + } + } + + } + } + + +} diff --git a/Surf/AppDelegate.swift b/Surf/AppDelegate.swift new file mode 100644 index 0000000..0dee1f0 --- /dev/null +++ b/Surf/AppDelegate.swift @@ -0,0 +1,610 @@ +// +// AppDelegate.swift +// Surf +// +// Created by abigt on 15/11/20. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit +import NetworkExtension +import Darwin +import AxLogger +import SFSocket +import SwiftyStoreKit +import Crashlytics +import Fabric +import XRuler +import Alamofire +import ObjectMapper +import AVFoundation +import Xcon +import XProxy +extension String { + var localized: String { + return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "") + } +} +//import Bugly +//public func BLogError(_ format: String, _ args: CVarArg...){ +// BLYLogv(BuglyLogLevel.error, format, getVaList(args)) +// +//} +// +//public func BLogWarn(_ format: String, _ args: CVarArg...){ +// BLYLogv(BuglyLogLevel.warn, format, getVaList(args)) +//} +// +//public func BLogInfo(_ format: String, _ args: CVarArg...){ +// BLYLogv(BuglyLogLevel.info, format, getVaList(args)) +//} +// +//public func BLogDebug(_ format: String, _ args: CVarArg...){ +// BLYLogv(BuglyLogLevel.debug, format, getVaList(args)) +//} + +public func iCloudSyncEnabled() ->Bool{ + return UserDefaults.standard.bool(forKey: "icloudsync"); +} +public func saveiCloudSync(_ t:Bool) { + UserDefaults.standard.set(t, forKey:"icloudsync" ) +} + +func reportMemoryUsed() ->UInt64 { + return 0 +} +func crashSignalHandler(signal:Int32) +{ + + exit(Int32(signal)); +} + + +func installSignalHandler() +{ + //NSSetUncaughtExceptionHandler(&HandleException); + // learning + //http://www.cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html + //http://devmonologue.com/ios/ios/implementing-crash-reporting-for-ios/ + //#ifdef DEBUG + signal(SIGABRT, crashSignalHandler); + signal(SIGSEGV, crashSignalHandler); + signal(SIGBUS, crashSignalHandler); + signal(SIGKILL, crashSignalHandler); + signal(SIGSYS, crashSignalHandler); + signal(SIGTERM, crashSignalHandler); + signal(SIGSTOP, crashSignalHandler); + signal(SIGTSTP, crashSignalHandler); + signal(SIGXCPU, crashSignalHandler); + signal(SIGXFSZ, crashSignalHandler); + signal(SIGILL, crashSignalHandler); + signal(SIGFPE, crashSignalHandler); + signal(SIGPIPE, crashSignalHandler); + signal(SIGTRAP, crashSignalHandler); + signal(SIGHUP, SIG_IGN); + let queue: DispatchQueue = DispatchQueue.global() + let source = DispatchSource.makeProcessSource(identifier: 0, eventMask: .signal, queue: queue) + + + let q = DispatchQueue.init(label: "test") + q.async { + source.setEventHandler { + _ = (source as! DispatchSource.ProcessEvent).rawValue + // crashSignalHandler(signal: event) + + } + source.resume() + } + +} + +@UIApplicationMain + +class AppDelegate: UIResponder, UIApplicationDelegate { + + + var iCloudToken:Data? + var iCloudEnable:Bool = false + enum ShortcutIdentifier: String { + case First + case Second + case Third + case Fourth + + // MARK: Initializers + + init?(fullType: String) { + guard let last = fullType.components(separatedBy: ".").last else { return nil } + + self.init(rawValue: last) + } + + // MARK: Properties + + var type: String { + return Bundle.main.bundleIdentifier! + ".\(self.rawValue)" + } + } +// func testAES() { +// +// let password = "xxXxab12lkdjflksjd" // Humans are terrible at picking passwords +// let message = "Attack at dawn".dataUsingEncoding(NSUTF8StringEncoding)! +// +// // Encrypting +// let ciphertext: NSData = { +// func randomSaltAndKeyForPassword(password: String) -> (salt: NSData, key: NSData) { +// let salt = RNCryptor.randomDataOfLength(RNCryptor.FormatV3.saltSize) +// let key = RNCryptor.FormatV3.keyForPassword(password, salt: salt) +// return (salt, key) +// } +// +// let (encryptionSalt, encryptionKey) = randomSaltAndKeyForPassword(password) +// let (hmacSalt, hmacKey) = randomSaltAndKeyForPassword(password) +// let encryptor = RNCryptor.EncryptorV3(encryptionKey: encryptionKey, hmacKey: hmacKey) +// +// let ciphertext = NSMutableData(data: encryptionSalt) +// ciphertext.appendData(hmacSalt) +// ciphertext.appendData(encryptor.encryptData(message)) +// return ciphertext +// }() +// +// // Decrypting +// let plaintext: NSData = { +// let encryptionSaltRange = NSRange(location: 0, length: RNCryptor.FormatV3.saltSize) +// let hmacSaltRange = NSRange(location: NSMaxRange(encryptionSaltRange), length: RNCryptor.FormatV3.saltSize) +// let bodyRange = NSRange(NSMaxRange(hmacSaltRange).. Bool { + var handled = false + + // Verify that the provided `shortcutItem`'s `type` is one handled by the application. + guard ShortcutIdentifier(fullType: shortcutItem.type) != nil else { return false } + + guard let shortCutType = shortcutItem.type as String? else { return false } + let config = ProxyGroupSettings.share.config + switch (shortCutType) { + case ShortcutIdentifier.First.type: + // Handle shortcut 1 (static). + handled = true + break + case ShortcutIdentifier.Second.type: + // Handle shortcut 2 (static). + handled = true + break + case ShortcutIdentifier.Third.type: + // Handle shortcut 3 (dynamic). + if let info = shortcutItem.userInfo { + let x = info[AppDelegate.applicationShortcutUserInfoIconKey] as! NSNumber + + ProxyGroupSettings.share.selectIndex = x.intValue + try! ProxyGroupSettings.share.save() + //self.window?.rootViewController + NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ProxyIndexChanged"), object: nil) + print("\(x)") + } + + handled = true + break + case ShortcutIdentifier.Fourth.type: + // Handle shortcut 4 (dynamic). + + _ = try! SFVPNManager.shared.startStopToggled(config) + handled = true + break + default: + break + } + + // Construct an alert using the details of the shortcut used to open the application. +// let alertController = UIAlertController(title: "Shortcut Handled", message: "\"\(shortcutItem.localizedTitle)\"", preferredStyle: .alert) +// let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil) +// alertController.addAction(okAction) +// +// // Display an alert indicating the shortcut selected from the home screen. +// window!.rootViewController?.present(alertController, animated: true, completion: nil) + + return handled + } + + var window: UIWindow? + + + func appAppearance(_ blackStyle:Bool ){ + + + if blackStyle { + let color = UIColor.init(red: 0x29/255.0, green: 0x2d/255.0, blue: 0x36/255.0, alpha: 1.0) + + //UIApplication.sharedApplication().statusBarStyle = .LightContent + UINavigationBar.appearance().barTintColor = color + UINavigationBar.appearance().tintColor = UIColor.white + UINavigationBar.appearance().isTranslucent = false + UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor:UIColor.white, + NSAttributedStringKey.font:UIFont.systemFont(ofSize: 21.0) + ] + UITableViewCell.appearance().backgroundColor = UIColor.init(red: 0x26/255.0, green: 0x28/255.0, blue: 0x32/255.0, alpha: 1.0) + + let color2 = UIColor.init(red: 0x2A/255.0, green: 0x2d/255.0, blue: 0x36/255.0, alpha: 1.0) + UITabBar.appearance().barTintColor = color2 + + let color4 = UIColor.init(red: 0x91/255.0, green: 0xAC/255.0, blue: 0xF3/255.0, alpha: 1.0) + UITabBar.appearance().tintColor = color4 + if #available(iOS 10.0, *) { + UITabBar.appearance().unselectedItemTintColor = UIColor.gray + } else { + // Fallback on earlier versions + } + UILabel.appearance(whenContainedInInstancesOf: [UITableViewCell.self]).backgroundColor = UIColor.clear + // UILabel.appearance().backgroundColor = UIColor.clear + // UITableViewCell.appearance().textLabel?.backgroundColor = UIColor.clear + UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor:UIColor.gray], for: .normal) + UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor:color4], for: .selected) + let color3 = UIColor.init(red: 0x26/255.0, green: 0x28/255.0, blue: 0x32/255.0, alpha: 1.0) + + UITableView.appearance().backgroundColor = color3 + UITableView.appearance().separatorColor = UIColor.init(red: 0x44/255.0, green: 0x45/255.0, blue: 0x4c/255.0, alpha: 1.0) + + UISwitch.appearance().onTintColor = UIColor.cyan// color //UIColor.init(red: 0x91/255.0, green: 0xAC/255.0, blue: 0xF3/255.0, alpha: 1.0) + UISwitch.appearance().tintColor = color4 + UISwitch.appearance().thumbTintColor = UIColor.init(red: 0x91/255.0, green: 0xAC/255.0, blue: 0xF3/255.0, alpha: 1.0) + + UISegmentedControl.appearance().tintColor = color4 + + UITextView.appearance().backgroundColor = color3 + UITextView.appearance().textColor = UIColor.white + }else { + let color = UIColor.init(red: 0x0b/255.0, green: 0x60/255.0, blue: 0xb1/255.0, alpha: 1.0) + //UIApplication.sharedApplication().statusBarStyle = .LightContent + UINavigationBar.appearance().barTintColor = color + UINavigationBar.appearance().tintColor = UIColor.white + UINavigationBar.appearance().isTranslucent = false + UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor:UIColor.white, + NSAttributedStringKey.font:UIFont.systemFont(ofSize: 21.0) + ] + + UITableView.appearance().backgroundColor = UIColor.groupTableViewBackground + UITableView.appearance().separatorColor = UIColor.lightGray + + UITableViewCell.appearance().backgroundColor = UIColor.white + + let color2 = UIColor.init(red: 0x1/255.0, green: 0x2d/255.0, blue: 0x36/255.0, alpha: 1.0) + UITabBar.appearance().barTintColor = nil + + let color4 = UIColor.init(red: 0x91/255.0, green: 0xAC/255.0, blue: 0xF3/255.0, alpha: 1.0) + UITabBar.appearance().tintColor = color4 + if #available(iOS 10.0, *) { + UITabBar.appearance().unselectedItemTintColor = UIColor.gray + } else { + // Fallback on earlier versions + } + UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor:UIColor.gray], for: .normal) + UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor:color4], for: .selected) + let color3 = UIColor.init(red: 0x26/255.0, green: 0x28/255.0, blue: 0x32/255.0, alpha: 1.0) + + + + + + + UISwitch.appearance().onTintColor = nil // color //UIColor.init(red: 0x91/255.0, green: 0xAC/255.0, blue: 0xF3/255.0, alpha: 1.0) + UISwitch.appearance().tintColor = nil + UISwitch.appearance().thumbTintColor = nil + + UISegmentedControl.appearance().tintColor = nil + + UITextView.appearance().backgroundColor = UIColor.white + UITextView.appearance().textColor = UIColor.black + UILabel.appearance(whenContainedInInstancesOf: [UITableViewCell.self]).textColor = nil + } + + if let rootview = window?.rootViewController { + let x = rootview as! UITabBarController + let nv = x.viewControllers?.first! as! UINavigationController + let vc = nv.viewControllers.first! as! ProxyGroupViewController + + vc.alertMessageAction("Theme Changed") + } + self.window?.subviews.forEach({ (view: UIView) in + view.removeFromSuperview() + self.window?.addSubview(view) + }) + } + func testIcon() { + if #available(iOS 10.3, *) { + UIApplication.shared.setAlternateIconName("", completionHandler: { (error) in + + }) + } else { + // Fallback on earlier versions + } + } + func testload(){ + let x = ProxyGroupSettings.share + print(x.selectIndex) + let _ = x.proxys + } + + func completeIAPTransactions() { + + SwiftyStoreKit.completeTransactions(atomically: true) { purchases in + + for purchase in purchases { + // swiftlint:disable:next for_where + if purchase.transaction.transactionState == .purchased || purchase.transaction.transactionState == .restored { + + if purchase.needsFinishTransaction { + // Deliver content from server, then: + SwiftyStoreKit.finishTransaction(purchase.transaction) + } + print("purchased: \(purchase.productId)") + } + } + } + } + func verify(){ + guard let u = Bundle.main.appStoreReceiptURL else {return } + do { + let data = try Data.init(contentsOf: u) + print(" record \(data)") + let rr = data.base64EncodedString() + uploadReceipt(rr) + + }catch let e { + print("nobuy record \(e.localizedDescription)") + } + } + func uploadReceipt(_ re:String) { + let p = ["receipt":re] + Alamofire.request("http://35.189.177.19:5888/verify", method: .post, parameters: p, encoding: URLEncoding.default, headers: nil) + .responseJSON { (JSON) in + switch JSON.result{ + case .success(let resp): + + if let m = Mapper().map(JSONObject:resp) { + print(m) + } + + case .failure(let err): + print(err.localizedDescription) + } + } + + + } + func test() { + SKit.proxyIpAddr = "240.7.1.10" + + SKit.dnsAddr = "218.75.4.130" + SKit.proxyHTTPSIpAddr = "240.7.1.11" + SKit.xxIpAddr = "240.7.1.12" + SKit.tunIP = "240.7.1.9" + Xcon.debugEnable = true + XRuler.groupIdentifier = "group.com.abigt.Surf" + var url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: XRuler.groupIdentifier)! + url.appendPathComponent("abigt.conf") + + + } + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool{ + + + verify() + + Fabric.with([Crashlytics.self]) + // Fabric.with([Answers.self]) + +// let config = BuglyConfig() +// +// config.debugMode = true +// +// config.viewControllerTrackingEnable = true +// +// config.reportLogLevel = BuglyLogLevel.warn +// +// Bugly.start(withAppId: "44950d891c", config: config) +// BLogError("Swift Log Print %@", "Test") +// BLogWarn("Swift Log Print %@", "Test") + + + completeIAPTransactions() + + + + //_ = NEHotspotHelper.supportedNetworkInterfaces() + + + + + prepareApp() + + SFConfigManager.manager.copyConfig() + SFConfigManager.manager.loadConfigs() + + // Override point for customization after application launch. + let shouldPerformAdditionalDelegateHandling = true + + + // Install initial verstions of our two extra dynamic shortcuts. + if application.shortcutItems != nil {//where shortcutItems.isEmpty + application.shortcutItems?.removeAll() + // Construct the items. + //MARK: disable this feature +// if let p = ProxyGroupSettings.share.findProxy("Proxy"){ +// let showName = p.showString() +// var icon = UIApplicationShortcutIcon(type: .play) +// var value = UIApplicationShortcutIconType.play.rawValue +// var title = "Connect" +// if let m = SFVPNManager.shared.manager { +// if m.connection.status == .connected{ +// //connect = true +// icon = UIApplicationShortcutIcon(type: .pause) +// value = UIApplicationShortcutIconType.pause.rawValue +// title = "Disconnect" +// } +// } +// +// let shortcut4 = UIMutableApplicationShortcutItem(type: ShortcutIdentifier.Fourth.type, localizedTitle:title , localizedSubtitle: "Proxy \(showName)", icon:icon, userInfo: [ +// AppDelegate.applicationShortcutUserInfoIconKey:value] +// ) +// +// // Update the application providing the initial 'dynamic' shortcut items. +// application.shortcutItems?.append(shortcut4) +// } +// +// for index in 0 ..< ProxyGroupSettings.share.cutCount() { +// let proxy = ProxyGroupSettings.share.proxys[index] +// let shortcut3 = UIMutableApplicationShortcutItem(type: ShortcutIdentifier.Third.type, localizedTitle: proxy.showString(), localizedSubtitle: nil, icon: nil, userInfo: [ +// AppDelegate.applicationShortcutUserInfoIconKey: index//UIApplicationShortcutIconType.Play.rawValue +// ] +// ) +// print("\(proxy.serverAddress):\(proxy.serverPort)") +// application.shortcutItems?.append(shortcut3) +// } + + + + + } + + icloudPrepare() + icloudNoti() + + appAppearance(ProxyGroupSettings.share.wwdcStyle ) + return shouldPerformAdditionalDelegateHandling //true + } + + /* + Called when the user activates your application by selecting a shortcut on the home screen, except when + application(_:,willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions) returns `false`. + You should handle the shortcut in those callbacks and return `false` if possible. In that case, this + callback is used if your application is already launched in the background. + */ + + func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler:@escaping (Bool) -> Void) { + _ = handleShortCutItem(shortcutItem: shortcutItem) + + + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + func application(_ application: UIApplication, handleOpen url: URL) -> Bool { + + return true + } + private func application(app: UIApplication, openURL url: URL, options: [String : AnyObject]) -> Bool { + if url.isFileURL == true { + let info = ["url":url] + NotificationCenter.default.post(name: NSNotification.Name(rawValue: "shouldSaveConfNotification"), object: self, userInfo: info) + + }else { + if let host = url.host { + var start = false + if host == "start"{ + start = true + } + var status = false + if let m = SFVPNManager.shared.manager{ + + if m.connection.status == .connected || m.connection.status == .connecting{ + status = true + } + + if start && status == false { + let s = ProxyGroupSettings.share.config + _ = try! SFVPNManager.shared.startStopToggled(s) + } + if status == false && status { + let s = ProxyGroupSettings.share.config + _ = try! SFVPNManager.shared.startStopToggled(s) + } + + }else { + let s = ProxyGroupSettings.share.config + _ = try! SFVPNManager.shared.startStopToggled(s) + } + } + + } + + return true + + } + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + NotificationCenter.default.post(name: NSNotification.Name(rawValue: "applicationDidBecomeActive"), object: application) + guard let shortcut = launchedShortcutItem else { return } + + + _ = handleShortCutItem(shortcutItem: shortcut) + + launchedShortcutItem = nil + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Surf/Assets.xcassets/1060-switches.imageset/1060-switches.png b/Surf/Assets.xcassets/1060-switches.imageset/1060-switches.png new file mode 100644 index 0000000..dfd573a Binary files /dev/null and b/Surf/Assets.xcassets/1060-switches.imageset/1060-switches.png differ diff --git a/Surf/Assets.xcassets/1060-switches.imageset/1060-switches@2x.png b/Surf/Assets.xcassets/1060-switches.imageset/1060-switches@2x.png new file mode 100644 index 0000000..76aefee Binary files /dev/null and b/Surf/Assets.xcassets/1060-switches.imageset/1060-switches@2x.png differ diff --git a/Surf/Assets.xcassets/1060-switches.imageset/1060-switches@3x.png b/Surf/Assets.xcassets/1060-switches.imageset/1060-switches@3x.png new file mode 100644 index 0000000..08fdfa3 Binary files /dev/null and b/Surf/Assets.xcassets/1060-switches.imageset/1060-switches@3x.png differ diff --git a/Surf/Assets.xcassets/1060-switches.imageset/Contents.json b/Surf/Assets.xcassets/1060-switches.imageset/Contents.json new file mode 100644 index 0000000..e9c3fc8 --- /dev/null +++ b/Surf/Assets.xcassets/1060-switches.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1060-switches.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1060-switches@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1060-switches@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected.png b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected.png new file mode 100644 index 0000000..c8a8a4f Binary files /dev/null and b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected.png differ diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected@2x.png b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected@2x.png new file mode 100644 index 0000000..c0f1651 Binary files /dev/null and b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected@2x.png differ diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected@3x.png b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected@3x.png new file mode 100644 index 0000000..212fc5b Binary files /dev/null and b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/1062-layers-2-toolbar-selected@3x.png differ diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/Contents.json b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/Contents.json new file mode 100644 index 0000000..e46e61e --- /dev/null +++ b/Surf/Assets.xcassets/1062-layers-2-toolbar-selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1062-layers-2-toolbar-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1062-layers-2-toolbar-selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1062-layers-2-toolbar-selected@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar.png b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar.png new file mode 100644 index 0000000..1d2578d Binary files /dev/null and b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar.png differ diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar@2x.png b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar@2x.png new file mode 100644 index 0000000..6f522df Binary files /dev/null and b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar@3x.png b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar@3x.png new file mode 100644 index 0000000..29ec3fa Binary files /dev/null and b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/1062-layers-2-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/Contents.json new file mode 100644 index 0000000..948e685 --- /dev/null +++ b/Surf/Assets.xcassets/1062-layers-2-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1062-layers-2-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1062-layers-2-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1062-layers-2-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected.png b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected.png new file mode 100644 index 0000000..0d26ee7 Binary files /dev/null and b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected.png differ diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected@2x.png b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected@2x.png new file mode 100644 index 0000000..3d1e44a Binary files /dev/null and b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected@2x.png differ diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected@3x.png b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected@3x.png new file mode 100644 index 0000000..53f5ef5 Binary files /dev/null and b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/1165-taoism-yin-yang-selected@3x.png differ diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/Contents.json b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/Contents.json new file mode 100644 index 0000000..bb56a23 --- /dev/null +++ b/Surf/Assets.xcassets/1165-taoism-yin-yang-selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1165-taoism-yin-yang-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1165-taoism-yin-yang-selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1165-taoism-yin-yang-selected@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang.png b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang.png new file mode 100644 index 0000000..f16f63d Binary files /dev/null and b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang.png differ diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang@2x.png b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang@2x.png new file mode 100644 index 0000000..16a73c9 Binary files /dev/null and b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang@2x.png differ diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang@3x.png b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang@3x.png new file mode 100644 index 0000000..ce4714a Binary files /dev/null and b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/1165-taoism-yin-yang@3x.png differ diff --git a/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/Contents.json b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/Contents.json new file mode 100644 index 0000000..07b8652 --- /dev/null +++ b/Surf/Assets.xcassets/1165-taoism-yin-yang.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1165-taoism-yin-yang.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1165-taoism-yin-yang@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1165-taoism-yin-yang@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar.png b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar.png new file mode 100644 index 0000000..95ec90b Binary files /dev/null and b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar.png differ diff --git a/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar@2x.png b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar@2x.png new file mode 100644 index 0000000..33c6594 Binary files /dev/null and b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar@3x.png b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar@3x.png new file mode 100644 index 0000000..aceb18f Binary files /dev/null and b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/1175-numbered-list-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/Contents.json new file mode 100644 index 0000000..1184004 --- /dev/null +++ b/Surf/Assets.xcassets/1175-numbered-list-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1175-numbered-list-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1175-numbered-list-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1175-numbered-list-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected.png b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected.png new file mode 100644 index 0000000..8fb5162 Binary files /dev/null and b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected.png differ diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected@2x.png b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected@2x.png new file mode 100644 index 0000000..3368212 Binary files /dev/null and b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected@2x.png differ diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected@3x.png b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected@3x.png new file mode 100644 index 0000000..5ccc358 Binary files /dev/null and b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/1176-bulleted-list-toolbar-selected@3x.png differ diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/Contents.json b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/Contents.json new file mode 100644 index 0000000..a2d62ee --- /dev/null +++ b/Surf/Assets.xcassets/1176-bulleted-list-toolbar-selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1176-bulleted-list-toolbar-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1176-bulleted-list-toolbar-selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1176-bulleted-list-toolbar-selected@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar.png b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar.png new file mode 100644 index 0000000..8fb5162 Binary files /dev/null and b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar.png differ diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar@2x.png b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar@2x.png new file mode 100644 index 0000000..3368212 Binary files /dev/null and b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar@3x.png b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar@3x.png new file mode 100644 index 0000000..5ccc358 Binary files /dev/null and b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/1176-bulleted-list-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/Contents.json new file mode 100644 index 0000000..fa883f4 --- /dev/null +++ b/Surf/Assets.xcassets/1176-bulleted-list-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1176-bulleted-list-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1176-bulleted-list-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1176-bulleted-list-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar.png b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar.png new file mode 100644 index 0000000..079cc82 Binary files /dev/null and b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar.png differ diff --git a/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar@2x.png b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar@2x.png new file mode 100644 index 0000000..bf8c27c Binary files /dev/null and b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar@3x.png b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar@3x.png new file mode 100644 index 0000000..8aff66d Binary files /dev/null and b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/1180-align-justify-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/Contents.json new file mode 100644 index 0000000..a7e4e0b --- /dev/null +++ b/Surf/Assets.xcassets/1180-align-justify-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1180-align-justify-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1180-align-justify-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1180-align-justify-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected.png b/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected.png new file mode 100644 index 0000000..c892774 Binary files /dev/null and b/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected.png differ diff --git a/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected@2x.png b/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected@2x.png new file mode 100644 index 0000000..2ec3cd2 Binary files /dev/null and b/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected@2x.png differ diff --git a/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected@3x.png b/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected@3x.png new file mode 100644 index 0000000..9bbe6a3 Binary files /dev/null and b/Surf/Assets.xcassets/1295-rss-selected.imageset/1295-rss-selected@3x.png differ diff --git a/Surf/Assets.xcassets/1295-rss-selected.imageset/Contents.json b/Surf/Assets.xcassets/1295-rss-selected.imageset/Contents.json new file mode 100644 index 0000000..f030162 --- /dev/null +++ b/Surf/Assets.xcassets/1295-rss-selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1295-rss-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1295-rss-selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1295-rss-selected@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/1295-rss.imageset/1295-rss.png b/Surf/Assets.xcassets/1295-rss.imageset/1295-rss.png new file mode 100644 index 0000000..571df45 Binary files /dev/null and b/Surf/Assets.xcassets/1295-rss.imageset/1295-rss.png differ diff --git a/Surf/Assets.xcassets/1295-rss.imageset/1295-rss@2x.png b/Surf/Assets.xcassets/1295-rss.imageset/1295-rss@2x.png new file mode 100644 index 0000000..a823099 Binary files /dev/null and b/Surf/Assets.xcassets/1295-rss.imageset/1295-rss@2x.png differ diff --git a/Surf/Assets.xcassets/1295-rss.imageset/1295-rss@3x.png b/Surf/Assets.xcassets/1295-rss.imageset/1295-rss@3x.png new file mode 100644 index 0000000..ede3c6c Binary files /dev/null and b/Surf/Assets.xcassets/1295-rss.imageset/1295-rss@3x.png differ diff --git a/Surf/Assets.xcassets/1295-rss.imageset/Contents.json b/Surf/Assets.xcassets/1295-rss.imageset/Contents.json new file mode 100644 index 0000000..460907d --- /dev/null +++ b/Surf/Assets.xcassets/1295-rss.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1295-rss.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "1295-rss@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "1295-rss@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1.png b/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1.png new file mode 100644 index 0000000..3fc93d5 Binary files /dev/null and b/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1.png differ diff --git a/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1@2x.png b/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1@2x.png new file mode 100644 index 0000000..9f7ee5e Binary files /dev/null and b/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1@2x.png differ diff --git a/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1@3x.png b/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1@3x.png new file mode 100644 index 0000000..9414545 Binary files /dev/null and b/Surf/Assets.xcassets/441-help-symbol1.imageset/441-help-symbol1@3x.png differ diff --git a/Surf/Assets.xcassets/441-help-symbol1.imageset/Contents.json b/Surf/Assets.xcassets/441-help-symbol1.imageset/Contents.json new file mode 100644 index 0000000..aeefbdc --- /dev/null +++ b/Surf/Assets.xcassets/441-help-symbol1.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "441-help-symbol1.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "441-help-symbol1@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "441-help-symbol1@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2.png b/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2.png new file mode 100644 index 0000000..58dc7f4 Binary files /dev/null and b/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2.png differ diff --git a/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2@2x.png b/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2@2x.png new file mode 100644 index 0000000..6eb8754 Binary files /dev/null and b/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2@2x.png differ diff --git a/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2@3x.png b/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2@3x.png new file mode 100644 index 0000000..e7a88b4 Binary files /dev/null and b/Surf/Assets.xcassets/451-help-symbol2.imageset/451-help-symbol2@3x.png differ diff --git a/Surf/Assets.xcassets/451-help-symbol2.imageset/Contents.json b/Surf/Assets.xcassets/451-help-symbol2.imageset/Contents.json new file mode 100644 index 0000000..7345667 --- /dev/null +++ b/Surf/Assets.xcassets/451-help-symbol2.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "451-help-symbol2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "451-help-symbol2@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "451-help-symbol2@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected.png b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected.png new file mode 100644 index 0000000..2dec371 Binary files /dev/null and b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected.png differ diff --git a/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected@2x.png b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected@2x.png new file mode 100644 index 0000000..1d5b548 Binary files /dev/null and b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected@2x.png differ diff --git a/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected@3x.png b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected@3x.png new file mode 100644 index 0000000..d4bd3ad Binary files /dev/null and b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/702-share-toolbar-selected@3x.png differ diff --git a/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/Contents.json b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/Contents.json new file mode 100644 index 0000000..f2de6cb --- /dev/null +++ b/Surf/Assets.xcassets/702-share-toolbar-selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "702-share-toolbar-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "702-share-toolbar-selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "702-share-toolbar-selected@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar.png b/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar.png new file mode 100644 index 0000000..ea0ce74 Binary files /dev/null and b/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar.png differ diff --git a/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar@2x.png b/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar@2x.png new file mode 100644 index 0000000..2566f50 Binary files /dev/null and b/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar@3x.png b/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar@3x.png new file mode 100644 index 0000000..c84cba0 Binary files /dev/null and b/Surf/Assets.xcassets/702-share-toolbar.imageset/702-share-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/702-share-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/702-share-toolbar.imageset/Contents.json new file mode 100644 index 0000000..cbac3e3 --- /dev/null +++ b/Surf/Assets.xcassets/702-share-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "702-share-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "702-share-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "702-share-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected.png b/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected.png new file mode 100644 index 0000000..3ae24c5 Binary files /dev/null and b/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected.png differ diff --git a/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected@2x.png b/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected@2x.png new file mode 100644 index 0000000..612122a Binary files /dev/null and b/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected@2x.png differ diff --git a/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected@3x.png b/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected@3x.png new file mode 100644 index 0000000..668fb16 Binary files /dev/null and b/Surf/Assets.xcassets/704-compose-selected.imageset/704-compose-selected@3x.png differ diff --git a/Surf/Assets.xcassets/704-compose-selected.imageset/Contents.json b/Surf/Assets.xcassets/704-compose-selected.imageset/Contents.json new file mode 100644 index 0000000..5a4dc27 --- /dev/null +++ b/Surf/Assets.xcassets/704-compose-selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "704-compose-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "704-compose-selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "704-compose-selected@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar.png b/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar.png new file mode 100644 index 0000000..368b93f Binary files /dev/null and b/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar.png differ diff --git a/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar@2x.png b/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar@2x.png new file mode 100644 index 0000000..d18e239 Binary files /dev/null and b/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar@3x.png b/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar@3x.png new file mode 100644 index 0000000..dda9c5c Binary files /dev/null and b/Surf/Assets.xcassets/704-compose-toolbar.imageset/704-compose-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/704-compose-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/704-compose-toolbar.imageset/Contents.json new file mode 100644 index 0000000..2161946 --- /dev/null +++ b/Surf/Assets.xcassets/704-compose-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "704-compose-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "704-compose-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "704-compose-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/724-info.imageset/724-info.png b/Surf/Assets.xcassets/724-info.imageset/724-info.png new file mode 100644 index 0000000..44affcd Binary files /dev/null and b/Surf/Assets.xcassets/724-info.imageset/724-info.png differ diff --git a/Surf/Assets.xcassets/724-info.imageset/724-info@2x.png b/Surf/Assets.xcassets/724-info.imageset/724-info@2x.png new file mode 100644 index 0000000..093aded Binary files /dev/null and b/Surf/Assets.xcassets/724-info.imageset/724-info@2x.png differ diff --git a/Surf/Assets.xcassets/724-info.imageset/724-info@3x.png b/Surf/Assets.xcassets/724-info.imageset/724-info@3x.png new file mode 100644 index 0000000..daa9b2a Binary files /dev/null and b/Surf/Assets.xcassets/724-info.imageset/724-info@3x.png differ diff --git a/Surf/Assets.xcassets/724-info.imageset/Contents.json b/Surf/Assets.xcassets/724-info.imageset/Contents.json new file mode 100644 index 0000000..3220c48 --- /dev/null +++ b/Surf/Assets.xcassets/724-info.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "724-info.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "724-info@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "724-info@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/750-home-selected.imageset/750-home-selected.png b/Surf/Assets.xcassets/750-home-selected.imageset/750-home-selected.png new file mode 100644 index 0000000..c31c0d6 Binary files /dev/null and b/Surf/Assets.xcassets/750-home-selected.imageset/750-home-selected.png differ diff --git a/Surf/Assets.xcassets/750-home-selected.imageset/Contents.json b/Surf/Assets.xcassets/750-home-selected.imageset/Contents.json new file mode 100644 index 0000000..88f8cbd --- /dev/null +++ b/Surf/Assets.xcassets/750-home-selected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "750-home-selected.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/750-home.imageset/750-home.png b/Surf/Assets.xcassets/750-home.imageset/750-home.png new file mode 100644 index 0000000..eb3f9d0 Binary files /dev/null and b/Surf/Assets.xcassets/750-home.imageset/750-home.png differ diff --git a/Surf/Assets.xcassets/750-home.imageset/750-home@2x.png b/Surf/Assets.xcassets/750-home.imageset/750-home@2x.png new file mode 100644 index 0000000..4f36f66 Binary files /dev/null and b/Surf/Assets.xcassets/750-home.imageset/750-home@2x.png differ diff --git a/Surf/Assets.xcassets/750-home.imageset/750-home@3x.png b/Surf/Assets.xcassets/750-home.imageset/750-home@3x.png new file mode 100644 index 0000000..46228fe Binary files /dev/null and b/Surf/Assets.xcassets/750-home.imageset/750-home@3x.png differ diff --git a/Surf/Assets.xcassets/750-home.imageset/Contents.json b/Surf/Assets.xcassets/750-home.imageset/Contents.json new file mode 100644 index 0000000..25b9561 --- /dev/null +++ b/Surf/Assets.xcassets/750-home.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "750-home.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "750-home@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "750-home@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar.png b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar.png new file mode 100644 index 0000000..b0d4da6 Binary files /dev/null and b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar.png differ diff --git a/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar@2x.png b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar@2x.png new file mode 100644 index 0000000..37298c1 Binary files /dev/null and b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar@2x.png differ diff --git a/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar@3x.png b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar@3x.png new file mode 100644 index 0000000..e697099 Binary files /dev/null and b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/760-refresh-3-toolbar@3x.png differ diff --git a/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/Contents.json b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/Contents.json new file mode 100644 index 0000000..f99a517 --- /dev/null +++ b/Surf/Assets.xcassets/760-refresh-3-toolbar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "760-refresh-3-toolbar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "760-refresh-3-toolbar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "760-refresh-3-toolbar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/Aid.imageset/Aid.png b/Surf/Assets.xcassets/Aid.imageset/Aid.png new file mode 100644 index 0000000..382a150 Binary files /dev/null and b/Surf/Assets.xcassets/Aid.imageset/Aid.png differ diff --git a/Surf/Assets.xcassets/Aid.imageset/Aid@2x.png b/Surf/Assets.xcassets/Aid.imageset/Aid@2x.png new file mode 100644 index 0000000..bf86133 Binary files /dev/null and b/Surf/Assets.xcassets/Aid.imageset/Aid@2x.png differ diff --git a/Surf/Assets.xcassets/Aid.imageset/Aid@3x.png b/Surf/Assets.xcassets/Aid.imageset/Aid@3x.png new file mode 100644 index 0000000..758023e Binary files /dev/null and b/Surf/Assets.xcassets/Aid.imageset/Aid@3x.png differ diff --git a/Surf/Assets.xcassets/Aid.imageset/Contents.json b/Surf/Assets.xcassets/Aid.imageset/Contents.json new file mode 100644 index 0000000..638dbaa --- /dev/null +++ b/Surf/Assets.xcassets/Aid.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Aid.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Aid@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Aid@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/AirPort4_21x16_@1x.png b/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/AirPort4_21x16_@1x.png new file mode 100644 index 0000000..869ef09 Binary files /dev/null and b/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/AirPort4_21x16_@1x.png differ diff --git a/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/AirPort4_21x16_@2x.png b/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/AirPort4_21x16_@2x.png new file mode 100644 index 0000000..0d5875f Binary files /dev/null and b/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/AirPort4_21x16_@2x.png differ diff --git a/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/Contents.json b/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/Contents.json new file mode 100644 index 0000000..0539bbd --- /dev/null +++ b/Surf/Assets.xcassets/AirPort4_21x16_-1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "AirPort4_21x16_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "AirPort4_21x16_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/AirPort4_21x16_.imageset/Contents.json b/Surf/Assets.xcassets/AirPort4_21x16_.imageset/Contents.json new file mode 100644 index 0000000..f8f827e --- /dev/null +++ b/Surf/Assets.xcassets/AirPort4_21x16_.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/Contents.json b/Surf/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..7cbf684 --- /dev/null +++ b/Surf/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,142 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "iTunesArtwork80w.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "iTunesArtwork120-1.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "57x57", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "size" : "57x57", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "iTunesArtwork120.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "iTunesArtwork180.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "iTunesArtwork80w-1.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "iTunesArtwork76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "iTunesArtwork152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "iTunesArtwork167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "iTunesArtwork@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork120-1.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork120-1.png new file mode 100644 index 0000000..2f65097 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork120-1.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork120.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork120.png new file mode 100644 index 0000000..2f65097 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork120.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork152.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork152.png new file mode 100644 index 0000000..75aebe9 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork152.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork167.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork167.png new file mode 100644 index 0000000..d7be945 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork167.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork180.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork180.png new file mode 100644 index 0000000..6fb0153 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork180.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork76.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork76.png new file mode 100644 index 0000000..345bd46 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork76.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork80w-1.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork80w-1.png new file mode 100644 index 0000000..1c9f528 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork80w-1.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork80w.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork80w.png new file mode 100644 index 0000000..1c9f528 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork80w.png differ diff --git a/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@1x.png b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@1x.png new file mode 100644 index 0000000..a7c4e60 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@1x.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/512120-1.png b/Surf/Assets.xcassets/AppIcon3.appiconset/512120-1.png new file mode 100644 index 0000000..c7b1f75 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/512120-1.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/512120.png b/Surf/Assets.xcassets/AppIcon3.appiconset/512120.png new file mode 100644 index 0000000..c7b1f75 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/512120.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/512180.png b/Surf/Assets.xcassets/AppIcon3.appiconset/512180.png new file mode 100644 index 0000000..3a24445 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/512180.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/51240.png b/Surf/Assets.xcassets/AppIcon3.appiconset/51240.png new file mode 100644 index 0000000..fdca9a5 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/51240.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/51276.png b/Surf/Assets.xcassets/AppIcon3.appiconset/51276.png new file mode 100644 index 0000000..7407267 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/51276.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/51280.png b/Surf/Assets.xcassets/AppIcon3.appiconset/51280.png new file mode 100644 index 0000000..67d24ed Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/51280.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/Contents.json b/Surf/Assets.xcassets/AppIcon3.appiconset/Contents.json new file mode 100644 index 0000000..a51431d --- /dev/null +++ b/Surf/Assets.xcassets/AppIcon3.appiconset/Contents.json @@ -0,0 +1,143 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "iTunesArtwork40.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "512120-1.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "57x57", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "size" : "57x57", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "512120.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "512180.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "51240.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "51280.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "51276.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "iTunesArtwork152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "iTunesArtwork167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "iTunesArtwork1024x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork1024x.png b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork1024x.png new file mode 100644 index 0000000..94304b2 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork1024x.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork152.png b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork152.png new file mode 100644 index 0000000..1e7271e Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork152.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork167.png b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork167.png new file mode 100644 index 0000000..f493c05 Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork167.png differ diff --git a/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork40.png b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork40.png new file mode 100644 index 0000000..b727b0f Binary files /dev/null and b/Surf/Assets.xcassets/AppIcon3.appiconset/iTunesArtwork40.png differ diff --git a/Surf/Assets.xcassets/Brand Assets.launchimage/Contents.json b/Surf/Assets.xcassets/Brand Assets.launchimage/Contents.json new file mode 100644 index 0000000..74e1280 --- /dev/null +++ b/Surf/Assets.xcassets/Brand Assets.launchimage/Contents.json @@ -0,0 +1,104 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "subtype" : "2436h", + "scale" : "3x" + }, + { + "orientation" : "landscape", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "subtype" : "2436h", + "scale" : "3x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "8.0", + "subtype" : "736h", + "scale" : "3x" + }, + { + "orientation" : "landscape", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "8.0", + "subtype" : "736h", + "scale" : "3x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "8.0", + "subtype" : "667h", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "subtype" : "retina4", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/Color.colorset/Contents.json b/Surf/Assets.xcassets/Color.colorset/Contents.json new file mode 100644 index 0000000..c6e5d3d --- /dev/null +++ b/Surf/Assets.xcassets/Color.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "1.000", + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000" + } + } + } + ] +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/Contents.json b/Surf/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Surf/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/Contents.json b/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/Contents.json new file mode 100644 index 0000000..c6cb1fd --- /dev/null +++ b/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "GlobeIcon_26x26_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "GlobeIcon_26x26_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/GlobeIcon_26x26_@1x.png b/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/GlobeIcon_26x26_@1x.png new file mode 100644 index 0000000..8fab38a Binary files /dev/null and b/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/GlobeIcon_26x26_@1x.png differ diff --git a/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/GlobeIcon_26x26_@2x.png b/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/GlobeIcon_26x26_@2x.png new file mode 100644 index 0000000..9e32077 Binary files /dev/null and b/Surf/Assets.xcassets/GlobeIcon_26x26_.imageset/GlobeIcon_26x26_@2x.png differ diff --git a/Surf/Assets.xcassets/GrayDot.imageset/Contents.json b/Surf/Assets.xcassets/GrayDot.imageset/Contents.json new file mode 100644 index 0000000..4edb1ee --- /dev/null +++ b/Surf/Assets.xcassets/GrayDot.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "GrayDot@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "GrayDot.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "GrayDot@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/GrayDot.imageset/GrayDot.png b/Surf/Assets.xcassets/GrayDot.imageset/GrayDot.png new file mode 100644 index 0000000..905fce2 Binary files /dev/null and b/Surf/Assets.xcassets/GrayDot.imageset/GrayDot.png differ diff --git a/Surf/Assets.xcassets/GrayDot.imageset/GrayDot@1x.png b/Surf/Assets.xcassets/GrayDot.imageset/GrayDot@1x.png new file mode 100644 index 0000000..3e491a6 Binary files /dev/null and b/Surf/Assets.xcassets/GrayDot.imageset/GrayDot@1x.png differ diff --git a/Surf/Assets.xcassets/GrayDot.imageset/GrayDot@3x.png b/Surf/Assets.xcassets/GrayDot.imageset/GrayDot@3x.png new file mode 100644 index 0000000..d6db719 Binary files /dev/null and b/Surf/Assets.xcassets/GrayDot.imageset/GrayDot@3x.png differ diff --git a/Surf/Assets.xcassets/GreenDot.imageset/Contents.json b/Surf/Assets.xcassets/GreenDot.imageset/Contents.json new file mode 100644 index 0000000..298d73d --- /dev/null +++ b/Surf/Assets.xcassets/GreenDot.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "GreenDot@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "GreenDot.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "GreenDot@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/GreenDot.imageset/GreenDot.png b/Surf/Assets.xcassets/GreenDot.imageset/GreenDot.png new file mode 100644 index 0000000..86cf5de Binary files /dev/null and b/Surf/Assets.xcassets/GreenDot.imageset/GreenDot.png differ diff --git a/Surf/Assets.xcassets/GreenDot.imageset/GreenDot@1x.png b/Surf/Assets.xcassets/GreenDot.imageset/GreenDot@1x.png new file mode 100644 index 0000000..eaf9686 Binary files /dev/null and b/Surf/Assets.xcassets/GreenDot.imageset/GreenDot@1x.png differ diff --git a/Surf/Assets.xcassets/GreenDot.imageset/GreenDot@3x.png b/Surf/Assets.xcassets/GreenDot.imageset/GreenDot@3x.png new file mode 100644 index 0000000..7f07110 Binary files /dev/null and b/Surf/Assets.xcassets/GreenDot.imageset/GreenDot@3x.png differ diff --git a/Surf/Assets.xcassets/Image-1.imageset/Contents.json b/Surf/Assets.xcassets/Image-1.imageset/Contents.json new file mode 100644 index 0000000..f8f827e --- /dev/null +++ b/Surf/Assets.xcassets/Image-1.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/Image-2.imageset/Contents.json b/Surf/Assets.xcassets/Image-2.imageset/Contents.json new file mode 100644 index 0000000..6024e57 --- /dev/null +++ b/Surf/Assets.xcassets/Image-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "start_firstlaunch_user-1.pdf", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/Image-2.imageset/start_firstlaunch_user-1.pdf b/Surf/Assets.xcassets/Image-2.imageset/start_firstlaunch_user-1.pdf new file mode 100644 index 0000000..86698ce Binary files /dev/null and b/Surf/Assets.xcassets/Image-2.imageset/start_firstlaunch_user-1.pdf differ diff --git a/Surf/Assets.xcassets/Image.imageset/Checkmark-1.png b/Surf/Assets.xcassets/Image.imageset/Checkmark-1.png new file mode 100644 index 0000000..b0d1a89 Binary files /dev/null and b/Surf/Assets.xcassets/Image.imageset/Checkmark-1.png differ diff --git a/Surf/Assets.xcassets/Image.imageset/Contents.json b/Surf/Assets.xcassets/Image.imageset/Contents.json new file mode 100644 index 0000000..4f9c781 --- /dev/null +++ b/Surf/Assets.xcassets/Image.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Checkmark-1.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/Contents.json b/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/Contents.json new file mode 100644 index 0000000..a53ae99 --- /dev/null +++ b/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ListIcon-64_64x59_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ListIcon-64_64x59_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/ListIcon-64_64x59_@1x.png b/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/ListIcon-64_64x59_@1x.png new file mode 100644 index 0000000..48c5382 Binary files /dev/null and b/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/ListIcon-64_64x59_@1x.png differ diff --git a/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/ListIcon-64_64x59_@2x.png b/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/ListIcon-64_64x59_@2x.png new file mode 100644 index 0000000..9648702 Binary files /dev/null and b/Surf/Assets.xcassets/ListIcon-64_64x59_.imageset/ListIcon-64_64x59_@2x.png differ diff --git a/Surf/Assets.xcassets/ListIcon_24x24_.imageset/Contents.json b/Surf/Assets.xcassets/ListIcon_24x24_.imageset/Contents.json new file mode 100644 index 0000000..667833e --- /dev/null +++ b/Surf/Assets.xcassets/ListIcon_24x24_.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ListIcon_24x24_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ListIcon_24x24_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/ListIcon_24x24_.imageset/ListIcon_24x24_@1x.png b/Surf/Assets.xcassets/ListIcon_24x24_.imageset/ListIcon_24x24_@1x.png new file mode 100644 index 0000000..d412e37 Binary files /dev/null and b/Surf/Assets.xcassets/ListIcon_24x24_.imageset/ListIcon_24x24_@1x.png differ diff --git a/Surf/Assets.xcassets/ListIcon_24x24_.imageset/ListIcon_24x24_@2x.png b/Surf/Assets.xcassets/ListIcon_24x24_.imageset/ListIcon_24x24_@2x.png new file mode 100644 index 0000000..cd2c638 Binary files /dev/null and b/Surf/Assets.xcassets/ListIcon_24x24_.imageset/ListIcon_24x24_@2x.png differ diff --git a/Surf/Assets.xcassets/RedDot.imageset/Contents.json b/Surf/Assets.xcassets/RedDot.imageset/Contents.json new file mode 100644 index 0000000..8139a78 --- /dev/null +++ b/Surf/Assets.xcassets/RedDot.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "RedDot@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "RedDot.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "RedDot@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/RedDot.imageset/RedDot.png b/Surf/Assets.xcassets/RedDot.imageset/RedDot.png new file mode 100644 index 0000000..a1284fc Binary files /dev/null and b/Surf/Assets.xcassets/RedDot.imageset/RedDot.png differ diff --git a/Surf/Assets.xcassets/RedDot.imageset/RedDot@1x.png b/Surf/Assets.xcassets/RedDot.imageset/RedDot@1x.png new file mode 100644 index 0000000..e0e69b9 Binary files /dev/null and b/Surf/Assets.xcassets/RedDot.imageset/RedDot@1x.png differ diff --git a/Surf/Assets.xcassets/RedDot.imageset/RedDot@3x.png b/Surf/Assets.xcassets/RedDot.imageset/RedDot@3x.png new file mode 100644 index 0000000..a2ff1a7 Binary files /dev/null and b/Surf/Assets.xcassets/RedDot.imageset/RedDot@3x.png differ diff --git a/Surf/Assets.xcassets/WWDC.colorset/Contents.json b/Surf/Assets.xcassets/WWDC.colorset/Contents.json new file mode 100644 index 0000000..7fc4669 --- /dev/null +++ b/Surf/Assets.xcassets/WWDC.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0x29", + "alpha" : "1.000", + "blue" : "0x36", + "green" : "0x2D" + } + } + } + ] +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/Contents.json b/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/Contents.json new file mode 100644 index 0000000..12b99d2 --- /dev/null +++ b/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "WiFiIcon_26x26_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "WiFiIcon_26x26_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/WiFiIcon_26x26_@1x.png b/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/WiFiIcon_26x26_@1x.png new file mode 100644 index 0000000..bbd1d63 Binary files /dev/null and b/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/WiFiIcon_26x26_@1x.png differ diff --git a/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/WiFiIcon_26x26_@2x.png b/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/WiFiIcon_26x26_@2x.png new file mode 100644 index 0000000..f9a1c1f Binary files /dev/null and b/Surf/Assets.xcassets/WiFiIcon_26x26_.imageset/WiFiIcon_26x26_@2x.png differ diff --git a/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/Contents.json b/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/Contents.json new file mode 100644 index 0000000..7ffd0f9 --- /dev/null +++ b/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "WiFi_64_64x64_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "WiFi_64_64x64_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/WiFi_64_64x64_@1x.png b/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/WiFi_64_64x64_@1x.png new file mode 100644 index 0000000..1648ad6 Binary files /dev/null and b/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/WiFi_64_64x64_@1x.png differ diff --git a/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/WiFi_64_64x64_@2x.png b/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/WiFi_64_64x64_@2x.png new file mode 100644 index 0000000..e5611a5 Binary files /dev/null and b/Surf/Assets.xcassets/WiFi_64_64x64_.imageset/WiFi_64_64x64_@2x.png differ diff --git a/Surf/Assets.xcassets/back.imageset/Contents.json b/Surf/Assets.xcassets/back.imageset/Contents.json new file mode 100644 index 0000000..3bad3d0 --- /dev/null +++ b/Surf/Assets.xcassets/back.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "back.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "back@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "back@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/back.imageset/back.png b/Surf/Assets.xcassets/back.imageset/back.png new file mode 100644 index 0000000..6d5e91c Binary files /dev/null and b/Surf/Assets.xcassets/back.imageset/back.png differ diff --git a/Surf/Assets.xcassets/back.imageset/back@2x.png b/Surf/Assets.xcassets/back.imageset/back@2x.png new file mode 100644 index 0000000..5ff9e63 Binary files /dev/null and b/Surf/Assets.xcassets/back.imageset/back@2x.png differ diff --git a/Surf/Assets.xcassets/back.imageset/back@3x.png b/Surf/Assets.xcassets/back.imageset/back@3x.png new file mode 100644 index 0000000..11aea7d Binary files /dev/null and b/Surf/Assets.xcassets/back.imageset/back@3x.png differ diff --git a/Surf/Assets.xcassets/checkmark.imageset/Checkmark-1.png b/Surf/Assets.xcassets/checkmark.imageset/Checkmark-1.png new file mode 100644 index 0000000..b0d1a89 Binary files /dev/null and b/Surf/Assets.xcassets/checkmark.imageset/Checkmark-1.png differ diff --git a/Surf/Assets.xcassets/checkmark.imageset/Contents.json b/Surf/Assets.xcassets/checkmark.imageset/Contents.json new file mode 100644 index 0000000..4f9c781 --- /dev/null +++ b/Surf/Assets.xcassets/checkmark.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Checkmark-1.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/config.imageset/Contents.json b/Surf/Assets.xcassets/config.imageset/Contents.json new file mode 100644 index 0000000..2d811fe --- /dev/null +++ b/Surf/Assets.xcassets/config.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "config.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "config@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "config@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/config.imageset/config.png b/Surf/Assets.xcassets/config.imageset/config.png new file mode 100644 index 0000000..51bb2c2 Binary files /dev/null and b/Surf/Assets.xcassets/config.imageset/config.png differ diff --git a/Surf/Assets.xcassets/config.imageset/config@2x.png b/Surf/Assets.xcassets/config.imageset/config@2x.png new file mode 100644 index 0000000..f13935d Binary files /dev/null and b/Surf/Assets.xcassets/config.imageset/config@2x.png differ diff --git a/Surf/Assets.xcassets/config.imageset/config@3x.png b/Surf/Assets.xcassets/config.imageset/config@3x.png new file mode 100644 index 0000000..5fe2650 Binary files /dev/null and b/Surf/Assets.xcassets/config.imageset/config@3x.png differ diff --git a/Surf/Assets.xcassets/diamond.imageset/Contents.json b/Surf/Assets.xcassets/diamond.imageset/Contents.json new file mode 100644 index 0000000..1cc2d2a --- /dev/null +++ b/Surf/Assets.xcassets/diamond.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "diamond.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "diamond@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "diamond@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/diamond.imageset/diamond.png b/Surf/Assets.xcassets/diamond.imageset/diamond.png new file mode 100644 index 0000000..562dfa0 Binary files /dev/null and b/Surf/Assets.xcassets/diamond.imageset/diamond.png differ diff --git a/Surf/Assets.xcassets/diamond.imageset/diamond@2x.png b/Surf/Assets.xcassets/diamond.imageset/diamond@2x.png new file mode 100644 index 0000000..1138ce0 Binary files /dev/null and b/Surf/Assets.xcassets/diamond.imageset/diamond@2x.png differ diff --git a/Surf/Assets.xcassets/diamond.imageset/diamond@3x.png b/Surf/Assets.xcassets/diamond.imageset/diamond@3x.png new file mode 100644 index 0000000..b0ef528 Binary files /dev/null and b/Surf/Assets.xcassets/diamond.imageset/diamond@3x.png differ diff --git a/Surf/Assets.xcassets/done.imageset/Contents.json b/Surf/Assets.xcassets/done.imageset/Contents.json new file mode 100644 index 0000000..59baa9f --- /dev/null +++ b/Surf/Assets.xcassets/done.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "done.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "done@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "done@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/done.imageset/done.png b/Surf/Assets.xcassets/done.imageset/done.png new file mode 100644 index 0000000..33968a9 Binary files /dev/null and b/Surf/Assets.xcassets/done.imageset/done.png differ diff --git a/Surf/Assets.xcassets/done.imageset/done@2x.png b/Surf/Assets.xcassets/done.imageset/done@2x.png new file mode 100644 index 0000000..4335f8d Binary files /dev/null and b/Surf/Assets.xcassets/done.imageset/done@2x.png differ diff --git a/Surf/Assets.xcassets/done.imageset/done@3x.png b/Surf/Assets.xcassets/done.imageset/done@3x.png new file mode 100644 index 0000000..45461f6 Binary files /dev/null and b/Surf/Assets.xcassets/done.imageset/done@3x.png differ diff --git a/Surf/Assets.xcassets/first.imageset/Contents.json b/Surf/Assets.xcassets/first.imageset/Contents.json new file mode 100644 index 0000000..33a7451 --- /dev/null +++ b/Surf/Assets.xcassets/first.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "first.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/first.imageset/first.pdf b/Surf/Assets.xcassets/first.imageset/first.pdf new file mode 100644 index 0000000..47d911d Binary files /dev/null and b/Surf/Assets.xcassets/first.imageset/first.pdf differ diff --git a/Surf/Assets.xcassets/help.imageset/Contents.json b/Surf/Assets.xcassets/help.imageset/Contents.json new file mode 100644 index 0000000..06b1c86 --- /dev/null +++ b/Surf/Assets.xcassets/help.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "help.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "help@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "help@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/help.imageset/help.png b/Surf/Assets.xcassets/help.imageset/help.png new file mode 100644 index 0000000..6b31d85 Binary files /dev/null and b/Surf/Assets.xcassets/help.imageset/help.png differ diff --git a/Surf/Assets.xcassets/help.imageset/help@2x.png b/Surf/Assets.xcassets/help.imageset/help@2x.png new file mode 100644 index 0000000..a145505 Binary files /dev/null and b/Surf/Assets.xcassets/help.imageset/help@2x.png differ diff --git a/Surf/Assets.xcassets/help.imageset/help@3x.png b/Surf/Assets.xcassets/help.imageset/help@3x.png new file mode 100644 index 0000000..e08d5fc Binary files /dev/null and b/Surf/Assets.xcassets/help.imageset/help@3x.png differ diff --git a/Surf/Assets.xcassets/list.imageset/Contents.json b/Surf/Assets.xcassets/list.imageset/Contents.json new file mode 100644 index 0000000..a923638 --- /dev/null +++ b/Surf/Assets.xcassets/list.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "list.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "list@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "list@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/list.imageset/list.png b/Surf/Assets.xcassets/list.imageset/list.png new file mode 100644 index 0000000..2bc28fa Binary files /dev/null and b/Surf/Assets.xcassets/list.imageset/list.png differ diff --git a/Surf/Assets.xcassets/list.imageset/list@2x.png b/Surf/Assets.xcassets/list.imageset/list@2x.png new file mode 100644 index 0000000..cbdaefb Binary files /dev/null and b/Surf/Assets.xcassets/list.imageset/list@2x.png differ diff --git a/Surf/Assets.xcassets/list.imageset/list@3x.png b/Surf/Assets.xcassets/list.imageset/list@3x.png new file mode 100644 index 0000000..e30c85b Binary files /dev/null and b/Surf/Assets.xcassets/list.imageset/list@3x.png differ diff --git a/Surf/Assets.xcassets/log.imageset/Contents.json b/Surf/Assets.xcassets/log.imageset/Contents.json new file mode 100644 index 0000000..9d601c4 --- /dev/null +++ b/Surf/Assets.xcassets/log.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "log.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "log@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "log@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/log.imageset/log.png b/Surf/Assets.xcassets/log.imageset/log.png new file mode 100644 index 0000000..b734450 Binary files /dev/null and b/Surf/Assets.xcassets/log.imageset/log.png differ diff --git a/Surf/Assets.xcassets/log.imageset/log@2x.png b/Surf/Assets.xcassets/log.imageset/log@2x.png new file mode 100644 index 0000000..ce9d8aa Binary files /dev/null and b/Surf/Assets.xcassets/log.imageset/log@2x.png differ diff --git a/Surf/Assets.xcassets/log.imageset/log@3x.png b/Surf/Assets.xcassets/log.imageset/log@3x.png new file mode 100644 index 0000000..c9a03b9 Binary files /dev/null and b/Surf/Assets.xcassets/log.imageset/log@3x.png differ diff --git a/Surf/Assets.xcassets/logo.imageset/Contents.json b/Surf/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..b54d173 --- /dev/null +++ b/Surf/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "logo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "logo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/logo.imageset/logo@2x.png b/Surf/Assets.xcassets/logo.imageset/logo@2x.png new file mode 100644 index 0000000..9702626 Binary files /dev/null and b/Surf/Assets.xcassets/logo.imageset/logo@2x.png differ diff --git a/Surf/Assets.xcassets/logo.imageset/logo@3x.png b/Surf/Assets.xcassets/logo.imageset/logo@3x.png new file mode 100644 index 0000000..72638f4 Binary files /dev/null and b/Surf/Assets.xcassets/logo.imageset/logo@3x.png differ diff --git a/Surf/Assets.xcassets/misc.imageset/Contents.json b/Surf/Assets.xcassets/misc.imageset/Contents.json new file mode 100644 index 0000000..06b1c86 --- /dev/null +++ b/Surf/Assets.xcassets/misc.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "help.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "help@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "help@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/misc.imageset/help.png b/Surf/Assets.xcassets/misc.imageset/help.png new file mode 100644 index 0000000..bb8dc95 Binary files /dev/null and b/Surf/Assets.xcassets/misc.imageset/help.png differ diff --git a/Surf/Assets.xcassets/misc.imageset/help@2x.png b/Surf/Assets.xcassets/misc.imageset/help@2x.png new file mode 100644 index 0000000..b83e64a Binary files /dev/null and b/Surf/Assets.xcassets/misc.imageset/help@2x.png differ diff --git a/Surf/Assets.xcassets/misc.imageset/help@3x.png b/Surf/Assets.xcassets/misc.imageset/help@3x.png new file mode 100644 index 0000000..d2c49e9 Binary files /dev/null and b/Surf/Assets.xcassets/misc.imageset/help@3x.png differ diff --git a/Surf/Assets.xcassets/plane.imageset/Contents.json b/Surf/Assets.xcassets/plane.imageset/Contents.json new file mode 100644 index 0000000..a74f95a --- /dev/null +++ b/Surf/Assets.xcassets/plane.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "plane@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/plane.imageset/plane@2x.png b/Surf/Assets.xcassets/plane.imageset/plane@2x.png new file mode 100644 index 0000000..bd25dda Binary files /dev/null and b/Surf/Assets.xcassets/plane.imageset/plane@2x.png differ diff --git a/Surf/Assets.xcassets/second.imageset/Contents.json b/Surf/Assets.xcassets/second.imageset/Contents.json new file mode 100644 index 0000000..03bd9c9 --- /dev/null +++ b/Surf/Assets.xcassets/second.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "second.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/second.imageset/second.pdf b/Surf/Assets.xcassets/second.imageset/second.pdf new file mode 100644 index 0000000..401614e Binary files /dev/null and b/Surf/Assets.xcassets/second.imageset/second.pdf differ diff --git a/Surf/Assets.xcassets/star.imageset/Contents.json b/Surf/Assets.xcassets/star.imageset/Contents.json new file mode 100644 index 0000000..14cf9e0 --- /dev/null +++ b/Surf/Assets.xcassets/star.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "star.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "star@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "star@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/star.imageset/star.png b/Surf/Assets.xcassets/star.imageset/star.png new file mode 100644 index 0000000..7483239 Binary files /dev/null and b/Surf/Assets.xcassets/star.imageset/star.png differ diff --git a/Surf/Assets.xcassets/star.imageset/star@2x.png b/Surf/Assets.xcassets/star.imageset/star@2x.png new file mode 100644 index 0000000..20c43eb Binary files /dev/null and b/Surf/Assets.xcassets/star.imageset/star@2x.png differ diff --git a/Surf/Assets.xcassets/star.imageset/star@3x.png b/Surf/Assets.xcassets/star.imageset/star@3x.png new file mode 100644 index 0000000..e635f0f Binary files /dev/null and b/Surf/Assets.xcassets/star.imageset/star@3x.png differ diff --git a/Surf/Assets.xcassets/start.imageset/Contents.json b/Surf/Assets.xcassets/start.imageset/Contents.json new file mode 100644 index 0000000..0ddb327 --- /dev/null +++ b/Surf/Assets.xcassets/start.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "start.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "start@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "start@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/start.imageset/start.png b/Surf/Assets.xcassets/start.imageset/start.png new file mode 100644 index 0000000..a0669f0 Binary files /dev/null and b/Surf/Assets.xcassets/start.imageset/start.png differ diff --git a/Surf/Assets.xcassets/start.imageset/start@2x.png b/Surf/Assets.xcassets/start.imageset/start@2x.png new file mode 100644 index 0000000..c96320d Binary files /dev/null and b/Surf/Assets.xcassets/start.imageset/start@2x.png differ diff --git a/Surf/Assets.xcassets/start.imageset/start@3x.png b/Surf/Assets.xcassets/start.imageset/start@3x.png new file mode 100644 index 0000000..8e4e051 Binary files /dev/null and b/Surf/Assets.xcassets/start.imageset/start@3x.png differ diff --git a/Surf/Assets.xcassets/videos-pTab-library-off_27x20_.imageset/Contents.json b/Surf/Assets.xcassets/videos-pTab-library-off_27x20_.imageset/Contents.json new file mode 100644 index 0000000..b77c331 --- /dev/null +++ b/Surf/Assets.xcassets/videos-pTab-library-off_27x20_.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "videos-pTab-library-off_27x20_@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/videos-pTab-library-off_27x20_.imageset/videos-pTab-library-off_27x20_@3x.png b/Surf/Assets.xcassets/videos-pTab-library-off_27x20_.imageset/videos-pTab-library-off_27x20_@3x.png new file mode 100644 index 0000000..5b6084a Binary files /dev/null and b/Surf/Assets.xcassets/videos-pTab-library-off_27x20_.imageset/videos-pTab-library-off_27x20_@3x.png differ diff --git a/Surf/Assets.xcassets/videos-pTab-library-on_27x20_.imageset/Contents.json b/Surf/Assets.xcassets/videos-pTab-library-on_27x20_.imageset/Contents.json new file mode 100644 index 0000000..f24e9e7 --- /dev/null +++ b/Surf/Assets.xcassets/videos-pTab-library-on_27x20_.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "videos-pTab-library-on_27x20_@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Surf/Assets.xcassets/videos-pTab-library-on_27x20_.imageset/videos-pTab-library-on_27x20_@3x.png b/Surf/Assets.xcassets/videos-pTab-library-on_27x20_.imageset/videos-pTab-library-on_27x20_@3x.png new file mode 100644 index 0000000..8ee25d2 Binary files /dev/null and b/Surf/Assets.xcassets/videos-pTab-library-on_27x20_.imageset/videos-pTab-library-on_27x20_@3x.png differ diff --git a/Surf/BarChatsCell.swift b/Surf/BarChatsCell.swift new file mode 100644 index 0000000..c4cff82 --- /dev/null +++ b/Surf/BarChatsCell.swift @@ -0,0 +1,135 @@ +// +// BarChatsCell.swift +// Surf +// +// Created by abigt on 2018/1/16. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import UIKit +import Charts +import XRuler +class BarChatsCell: UIView,ChartViewDelegate { + @IBOutlet weak var chartView:Charts.BarChartView? + + override func awakeFromNib(){ + if let chartView = chartView { + chartView.chartDescription?.enabled = false + + chartView.dragEnabled = true + chartView.setScaleEnabled(true) + chartView.pinchZoomEnabled = false + + // ChartYAxis *leftAxis = chartView.leftAxis; + + let xAxis = chartView.xAxis + xAxis.labelPosition = .bottom + + chartView.rightAxis.enabled = false + + + chartView.delegate = self + + chartView.drawBarShadowEnabled = false + chartView.drawValueAboveBarEnabled = false + + chartView.maxVisibleCount = 60 + + + xAxis.labelPosition = .bottom + xAxis.labelFont = .systemFont(ofSize: 10) + xAxis.granularity = 1 + xAxis.labelCount = 7 + //xAxis.valueFormatter = DayAxisValueFormatter(chart: chartView) + + let leftAxisFormatter = NumberFormatter() + leftAxisFormatter.minimumFractionDigits = 0 + leftAxisFormatter.maximumFractionDigits = 1 + leftAxisFormatter.negativeSuffix = " $" + leftAxisFormatter.positiveSuffix = " $" + + let leftAxis = chartView.leftAxis + leftAxis.labelFont = .systemFont(ofSize: 10) + leftAxis.labelCount = 8 + leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: leftAxisFormatter) + leftAxis.labelPosition = .outsideChart + leftAxis.spaceTop = 0.15 + leftAxis.axisMinimum = 0 // FIXME: HUH?? this replaces startAtZero = YES + + let rightAxis = chartView.rightAxis + rightAxis.enabled = true + rightAxis.labelFont = .systemFont(ofSize: 10) + rightAxis.labelCount = 8 + rightAxis.valueFormatter = leftAxis.valueFormatter + rightAxis.spaceTop = 0.15 + rightAxis.axisMinimum = 0 + + let l = chartView.legend + l.horizontalAlignment = .left + l.verticalAlignment = .bottom + l.orientation = .horizontal + l.drawInside = false + l.form = .circle + l.formSize = 9 + l.font = UIFont(name: "HelveticaNeue-Light", size: 11)! + l.xEntrySpace = 4 + // chartView.legend = l + +// let marker = XYMarkerView(color: UIColor(white: 180/250, alpha: 1), +// font: .systemFont(ofSize: 12), +// textColor: .white, +// insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8), +// xAxisValueFormatter: chartView.xAxis.valueFormatter!) +// marker.chartView = chartView +// marker.minimumSize = CGSize(width: 80, height: 40) +// chartView.marker = marker + + + // slidersValueChanged(nil) + } + } + func updateChartData() { + + + self.setDataCount(60, range: UInt32(1000)) + } + + func setDataCount(_ count: Int, range: UInt32) { + guard let chartView = chartView else { + return + } + let start = 1 + + let yVals = (start.. BarChartDataEntry in + let mult = range + 1 + let val = Double(arc4random_uniform(mult)) + if arc4random_uniform(100) < 25 { + return BarChartDataEntry(x: Double(i), y: val, icon: UIImage(named: "icon")) + } else { + return BarChartDataEntry(x: Double(i), y: val) + } + } + + var set1: BarChartDataSet! = nil + if let set = chartView.data?.dataSets.first as? BarChartDataSet { + set1 = set + set1.values = yVals + chartView.data?.notifyDataChanged() + chartView.notifyDataSetChanged() + } else { + set1 = BarChartDataSet(values: yVals, label: "The year 2017") + set1.colors = ChartColorTemplates.material() + set1.drawValuesEnabled = false + + let data = BarChartData(dataSet: set1) + data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) + data.barWidth = 0.9 + chartView.data = data + } + + // chartView.setNeedsDisplay() + } + func updateFlow(_ flow:NetFlow) { + updateChartData() + } +} diff --git a/Surf/BarcodeScanViewController.swift b/Surf/BarcodeScanViewController.swift new file mode 100644 index 0000000..435ddd0 --- /dev/null +++ b/Surf/BarcodeScanViewController.swift @@ -0,0 +1,268 @@ +// +// ViewController.swift +// QcodeCapture +// +// Created by kiwi on 15/11/18. +// Copyright © 2015年 kiwi. All rights reserved. +// + +import UIKit +import AVFoundation + +/// The tunnel delegate protocol. +@objc public protocol BarcodeScanDelegate: class { + func barcodeScanDidScan(controller: BarcodeScanViewController, configString:String) + func barcodeScanCancelScan(controller: BarcodeScanViewController) + +} + +public class BarcodeScanViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate{ + + let kScanQRCodeQueueName = "ScanQRCodeQueueName" + var captureSession: AVCaptureSession? + var videoPreviewLayer : AVCaptureVideoPreviewLayer? + var lastResult : Bool! + + weak var delegate:BarcodeScanDelegate? + func alertMessageAction(message:String,complete:(() -> Void)?) { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert".localized, message: message, preferredStyle: style) + let action = UIAlertAction.init(title: "OK".localized, style: .default) { (action:UIAlertAction) -> Void in + if let callback = complete { + callback() + } + } + alert.addAction(action) + self.present(alert, animated: true) { () -> Void in + + } + } + override public func viewDidLoad() { + super.viewDidLoad() + + + + // Do any additional setup after loading the view, typically from a nib. + } + + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + let cameraMediaType = AVMediaType.video + let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: cameraMediaType) + + switch cameraAuthorizationStatus { + + // The client is authorized to access the hardware supporting a media type. + case .authorized: + _ = startReading() + + // The client is not authorized to access the hardware for the media type. The user cannot change + // the client's status, possibly due to active restrictions such as parental controls being in place. + case .restricted: + alertMessageAction(message: "Camera Have Restricted", complete: nil) + + // The user explicitly denied access to the hardware supporting a media type for the client. + case .denied: + alertMessageAction(message: "Camera Have Denied, Please Enable in System Settings", complete: nil) + + // Indicates that the user has not yet made a choice regarding whether the client can access the hardware. + case .notDetermined: + // Prompting user for the permission to use the camera. + AVCaptureDevice.requestAccess(for: cameraMediaType) { [unowned self ] granted in + if granted { + DispatchQueue.main.async { + _ = self.startReading() + } + + //print("Granted access to \(cameraMediaType)") + } else { + print("Not granted access to \(cameraMediaType)") + } + } + } + + } + override public func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + @IBAction func cancleAction(_ sender: AnyObject) { + guard let d = self.delegate else{ + return + } + //self.navigationController?.popViewController(animated:(<#T##animated: Bool##Bool#>) + d.barcodeScanCancelScan(controller: self) + } + func startReading() -> Bool{ +// let error: NSError? + if captureSession == nil { + let captureDevice: AVCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video)! + + let input = try! AVCaptureDeviceInput(device: captureDevice) + + captureSession = AVCaptureSession() + captureSession?.addInput(input) + + let captureMetadataOutput = AVCaptureMetadataOutput() + captureSession?.addOutput(captureMetadataOutput) + + let dispatchQueue = DispatchQueue(label:kScanQRCodeQueueName) + captureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatchQueue) + captureMetadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr] + videoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession!) + videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill + videoPreviewLayer?.frame = self.view.frame + //self.view.layer.addSublayer(!) + self.view.layer.insertSublayer(videoPreviewLayer!, at:0) + } + + + + + + if captureSession?.isRunning == false { + captureSession?.startRunning() + } + + + return true + } + + func stopReading(){ + captureSession?.stopRunning() + + } + public func metadataOutput(_ captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection){ + + if let metadataObj = metadataObjects.first as? AVMetadataMachineReadableCodeObject { + var result: String? + + if metadataObj.type == AVMetadataObject.ObjectType.qr{ + result = metadataObj.stringValue + } + let q = DispatchQueue.main + q.async { + self.reportScanResult(result: result) + } + + } + + } + + + func reportScanResult(result:String!){ + stopReading() + + + guard let d = self.delegate else{ + return + } + d.barcodeScanDidScan(controller: self, configString: result) + } + public override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + + @IBAction func scanbarCodeFromPhotoLibrary(_ sender:AnyObject){ + let picker = UIImagePickerController() + let src = UIImagePickerControllerSourceType.savedPhotosAlbum + picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: src)! + + picker.delegate = self + self .present(picker, animated: true) { () -> Void in + + } + + } + public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { + + self.dismiss(animated: true) { () -> Void in + + } + + let image = info[UIImagePickerControllerOriginalImage] as! UIImage + let ciImage:CIImage = CIImage(image: image)! + var message:String = "" + let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) + + let features = detector!.features(in: ciImage) + + if features.count > 0{ + + for feature in features as! [CIQRCodeFeature]{ + message += feature.messageString! + } + if let _ = NSURL.init(string: message ) { + delegate?.barcodeScanDidScan(controller: self, configString: message) + }else { +// if let data = NSData.init(base64EncodedString: message, options:.IgnoreUnknownCharacters){ +// if let _ = String.init(data: data, encoding: NSUTF8StringEncoding) { +// delegate?.barcodeScanDidScan(self, configString: message) +// }else { +// alertMessageAction("\(message) Invalid", complete: nil) +// } +// } + // + delegate?.barcodeScanDidScan(controller: self, configString: message) + } + + + + + //self.convertConfigString(message) + + + }else{ + + let alert = UIAlertController.init(title: "Error", message: "No Valid QRCode Detected", preferredStyle: .alert) + alert.addAction(UIAlertAction.init(title: "OK", style: .cancel, handler: nil)) + + self.present(alert, animated: true, completion: nil) + } + + } + public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { + self.dismiss(animated: true) { () -> Void in + + } +// if let session = captureSession { +// videoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession) +// videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill +// videoPreviewLayer?.frame = self.view.frame +// //self.view.layer.addSublayer(!) +// self.view.layer.insertSublayer(videoPreviewLayer!, atIndex:0) +// session.startRunning() +// } + } + public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator){ + coordinator.animateAlongsideTransition(in: self.view, animation: { (ctx) in + let transition = CATransition() + transition.duration = ctx.transitionDuration + + // Make it fade + transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + transition.type = kCATransitionFade + self.videoPreviewLayer?.add(transition, forKey: "Fade") + if size.width > size.height { + //land + self.videoPreviewLayer?.setAffineTransform( CGAffineTransform(rotationAngle: -.pi/2)) + }else { + self.videoPreviewLayer?.setAffineTransform(CGAffineTransform(rotationAngle: 0.0)) + } + self.videoPreviewLayer?.frame.origin = self.view.frame.origin + }) { (ctx) in + + } + + } +} + diff --git a/Surf/Base.lproj/InfoPlist.strings b/Surf/Base.lproj/InfoPlist.strings new file mode 100644 index 0000000..fbe8882 --- /dev/null +++ b/Surf/Base.lproj/InfoPlist.strings @@ -0,0 +1,7 @@ +/* + InfoPlist.strings + Surf + + Created by abigt on 2017/8/3. + Copyright © 2017年 A.BIG.T. All rights reserved. +*/ diff --git a/Surf/Base.lproj/LaunchScreen.xib b/Surf/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..54798b1 --- /dev/null +++ b/Surf/Base.lproj/LaunchScreen.xib @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/Base.lproj/Localizable.strings b/Surf/Base.lproj/Localizable.strings new file mode 100644 index 0000000..bd4453d --- /dev/null +++ b/Surf/Base.lproj/Localizable.strings @@ -0,0 +1,15 @@ +/* + Localizable.strings + Surf + + Created by abigt on 2017/8/3. + Copyright © 2017年 A.BIG.T. All rights reserved. +*/ +"iCloud sync" = "iCloud sync"; + +"Proxy Chain" = "Proxy Chain"; +"Theme" = "Theme"; +"Advance" = "Advance"; +"Purchase" = "Purchase"; +"Clean Cache" = "Clean Cache"; +"Status" = "Status"; diff --git a/Surf/Base.lproj/Main.storyboard b/Surf/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f988bff --- /dev/null +++ b/Surf/Base.lproj/Main.storyboard @@ -0,0 +1,1865 @@ + + + + + + + + + + + + + + + Ionicons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/Base.lproj/ana.storyboard b/Surf/Base.lproj/ana.storyboard new file mode 100644 index 0000000..bbd2339 --- /dev/null +++ b/Surf/Base.lproj/ana.storyboard @@ -0,0 +1,1057 @@ + + + + + + + + + + + + + + Courier + + + Ionicons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/Base.lproj/help.storyboard b/Surf/Base.lproj/help.storyboard new file mode 100644 index 0000000..969f7f2 --- /dev/null +++ b/Surf/Base.lproj/help.storyboard @@ -0,0 +1,506 @@ + + + + + + + + + + + + + + Ionicons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/BuyViewController.swift b/Surf/BuyViewController.swift new file mode 100755 index 0000000..397c8c4 --- /dev/null +++ b/Surf/BuyViewController.swift @@ -0,0 +1,470 @@ +// +// ViewController.swift +// SwiftyStoreKit +// +// Created by Andrea Bizzotto on 03/09/2015. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit +import StoreKit +import SwiftyStoreKit +import ObjectMapper +import SFSocket + +import XRuler +class PurchaseCell: UITableViewCell { + @IBOutlet weak var purchase:UIButton! +} +class ProductCell: PurchaseCell { + var haveInfo:Bool = false + @IBOutlet weak var production:UILabel! +} +let buyKey = "com.abigt.Surf.buy" + +class ViewController: SFTableViewController { + + + var receipt:Receipt? + let purchase1Suffix = RegisteredPurchase.Pro + //let purchase2Suffix = RegisteredPurchase.VIP// autoRenewablePurchase + @IBOutlet var versionLable:UILabel? + @IBOutlet weak var productInfoLabel:UILabel! + //@IBOutlet weak var statusButton:UIButton! + // MARK: actions + @IBAction func getInfo1() { + getInfo(purchase1Suffix) + } + @IBAction func purchase1() { + purchase(purchase1Suffix) + } + @IBAction func verifyPurchase1() { + verifyPurchase(purchase1Suffix) + } +// @IBAction func getInfo2() { +// getInfo(purchase2Suffix) +// } +// @IBAction func purchase2() { +// purchase(purchase2Suffix) +// } +// @IBAction func verifyPurchase2() { +// verifyPurchase(purchase2Suffix) +// } + override func numberOfSections(in tableView: UITableView) -> Int{ + return 3 + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch section { + case 0: + return 4 + case 1: + return 1 + case 2: + return 2 + default: + return 0 + + } + } + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + return nil + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 2 { + let cell = tableView.dequeueReusableCell(withIdentifier: "purchase") as! PurchaseCell + if indexPath.row == 1 { + cell.purchase.setTitle("Restore Purchase", for: .normal) + cell.purchase.addTarget(self, action: #selector(ViewController.restorePurchases), for: .touchUpInside) + }else { + cell.purchase.setTitle("Verify Purchase", for: .normal) + cell.purchase.addTarget(self, action: #selector(ViewController.verifyPurchase1), for: .touchUpInside) + } + return cell + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "product") as! ProductCell + var product = RegisteredPurchase.Pro + let features = ["Enable KCP","Enable HTTP/Socks5","Enable Customize Rules","Enable Analyze"] + if indexPath.section == 0 { + cell.purchase.tag = indexPath.row + switch indexPath.row { + case 0: + product = RegisteredPurchase.KCP + cell.production.text = features[0] + case 1: + product = RegisteredPurchase.HTTP + cell.production.text = features[1] + case 2: + product = RegisteredPurchase.Rule + cell.production.text = features[2] + case 3: + product = RegisteredPurchase.Analyze + cell.production.text = features[3] + default: + break + } + }else { + cell.purchase.tag = 999 + } + if ProxyGroupSettings.share.wwdcStyle { + cell.production.textColor = UIColor.white + }else { + cell.production.textColor = UIColor.black + } + if !cell.haveInfo { + print("get product info \(product.rawValue)") + NetworkActivityIndicatorManager.networkOperationStarted() + SwiftyStoreKit.retrieveProductsInfo([appBundleId + "." + product.rawValue]) { result in + NetworkActivityIndicatorManager.networkOperationFinished() + cell.haveInfo = true + cell.production.text = self.messageForProductRetrievalInfo(result) + + //self.showAlert(self.alertForProductRetrievalInfo(result)) + } + } + var test:Bool = false + if test { + if let r = self.receipt { + for ps in r.in_app { + print("***** purchsed \(ps.product_id) \(product.rawValue)") + if ps.product_id == appBundleId + "." + product.rawValue { + cell.purchase.isEnabled = false + cell.purchase.setTitle("Purchased", for: .normal) + print("purchsed \(ps.product_id)") + break + } + } + + + } + + }else { + if verifyReceiptBuy(.Pro) { + cell.purchase.isEnabled = false + cell.purchase.setTitle("Purchased", for: .normal) + }else { + //验证单个商品有没有买 + if let r = self.receipt { + for ps in r.in_app { + print("***** purchsed \(ps.product_id) \(product.rawValue)") + if ps.product_id == appBundleId + "." + product.rawValue { + cell.purchase.isEnabled = false + cell.purchase.setTitle("Purchased", for: .normal) + print("purchsed \(ps.product_id)") + break + } + } + + + } + } + } + + + + + + if cell.purchase.allTargets.isEmpty { + cell.purchase.addTarget(self, action: #selector(ViewController.buyProduct(_:)), for: .touchUpInside) + } + + + return cell + } + + } + @objc func buyProduct(_ sender:UIButton){ + + switch sender.tag { + case 999: + purchase(RegisteredPurchase.Pro) + case 0: + purchase(RegisteredPurchase.KCP) + case 1: + purchase(RegisteredPurchase.HTTP) + case 2: + purchase(RegisteredPurchase.Rule) + case 3: + purchase(RegisteredPurchase.Analyze) + default: + break + } + } + override func viewDidLoad() { + + super.viewDidLoad() + self.title = "Purchase" + + if let r = ProxyGroupSettings.share.receipt { + self.receipt = r + + }else { + _ = verifyReceipt(.Pro) + } + + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if let r = ProxyGroupSettings.share.receipt { + if let ts = Int64(r.original_purchase_date_ms) { + let buy_date = Date.init(timeIntervalSince1970:TimeInterval(ts/1000)) + let df = DateFormatter() + df.dateFormat = "yyyy/MM/dd HH:mm:ss" + df.timeZone = NSTimeZone.system + versionLable?.text = "Version " + String(r.original_application_version) + " \(df.string(from: buy_date))" + } + } + } + func verifyReceiptBuy(_ product:RegisteredPurchase = RegisteredPurchase.Pro) ->Bool{ + + if (Int(appBuild())! % 2) != 0 { + return true + } + if findPurchase(product) { + return true + }else { + verifyProduct(product, result: { t in + print("111 verifyReceiptBuy \(product.rawValue)") + if t { + if product == .Pro { + + print("pro version \(product.rawValue)") + } + self.tableView.reloadData() + }else { + print("not pro version \(product.rawValue)") + } + }) + + return false + } + + } + + //只是Pro而已,其他独立feature 单独 + func verify(result: @escaping (Bool) ->Void) { + + NetworkActivityIndicatorManager.networkOperationStarted() + verifyReceipt { appresult in + NetworkActivityIndicatorManager.networkOperationFinished() + //self.showAlert(self.alertForVerifyReceipt(result)) + switch appresult { + case .success(let receipt): + //print("Verify receipt Success: \(receipt)") + let r = Mapper().map(JSON: receipt) + if let rr = r?.receipt { + self.receipt = rr + + do { + try ProxyGroupSettings.share.saveReceipt(rr) + }catch let e { + print(" \(e.localizedDescription)") + } + + //按版本,不是购买时间3.2 以后免费 + + let buyversion = rr.original_application_version.components(separatedBy: ".") + let localversion = "3.2".components(separatedBy: ".") + var purched = false + for (idx,item) in buyversion.enumerated() { + + + if idx < localversion.count { + let x = localversion[idx] + if Int(x)! > Int(item)! { + + purched = true + break + }else { + continue + } + }else { + + + break + } + } + if purched { + result(purched) + }else { + for inapp in rr.in_app { + if inapp.product_id == "com.abigt.Surf.Pro" { + print("version buy version > 3.2 ,buy \(inapp.product_id)") + purched = true + break + } + } + } + result(purched) + }else { + result(false) + } + + case .error(let error): + print("Verify receipt Failed: \(error)") + var alert:UIAlertController + switch error { + case .noReceiptData: + alert = self.alertWithTitle("Receipt verification", message: "No receipt data. Try again.") + + case .networkError(let error): + alert = self.alertWithTitle("Receipt verification", message: "Network error while verifying receipt: \(error)") + + default: + alert = self.alertWithTitle("Receipt verification", message: "Receipt verification failed: \(error)") + } + self.showAlert(alert) + } + + } + } + func getInfo(_ purchase: RegisteredPurchase) { + + NetworkActivityIndicatorManager.networkOperationStarted() + SwiftyStoreKit.retrieveProductsInfo([appBundleId + "." + purchase.rawValue]) { result in + NetworkActivityIndicatorManager.networkOperationFinished() + self.productInfoLabel.text = self.messageForProductRetrievalInfo(result) + //self.showAlert(self.alertForProductRetrievalInfo(result)) + } + } + + func purchase(_ purchase: RegisteredPurchase) { + + NetworkActivityIndicatorManager.networkOperationStarted() + SwiftyStoreKit.purchaseProduct(appBundleId + "." + purchase.rawValue, atomically: true) { result in + NetworkActivityIndicatorManager.networkOperationFinished() + + if case .success(let purchase) = result { + // Deliver content from server, then: + if purchase.needsFinishTransaction { + SwiftyStoreKit.finishTransaction(purchase.transaction) + } + self.verify(result: { t in + if t { + self.tableView.reloadData() + } + }) + + } + if let alert = self.alertForPurchaseResult(result) { + self.showAlert(alert) + } + } + } + + @IBAction func restorePurchases() { + + NetworkActivityIndicatorManager.networkOperationStarted() + SwiftyStoreKit.restorePurchases(atomically: true) { results in + NetworkActivityIndicatorManager.networkOperationFinished() + + for purchase in results.restoredPurchases where purchase.needsFinishTransaction { + // Deliver content from server, then: + SwiftyStoreKit.finishTransaction(purchase.transaction) + } + self.showAlert(self.alertForRestorePurchases(results)) + } + } + +// @IBAction func verifyReceipt() { +// +// NetworkActivityIndicatorManager.networkOperationStarted() +// verifyReceipt { result in +// NetworkActivityIndicatorManager.networkOperationFinished() +// self.showAlert(self.alertForVerifyReceipt(result)) +// } +// } + +// func verifyReceipt(completion: @escaping (VerifyReceiptResult) -> Void) { +// +// let appleValidator = AppleReceiptValidator(service: .production) +// let password = "e09dbf3ea2454af4bb5f55c8a5d00d8c" +// SwiftyStoreKit.verifyReceipt(using: appleValidator, password: password, completion: completion) +// } + + func verifyPurchase(_ purchase: RegisteredPurchase) { + + NetworkActivityIndicatorManager.networkOperationStarted() + verifyReceipt { result in + NetworkActivityIndicatorManager.networkOperationFinished() + + switch result { + case .success(let receipt): + + let productId = self.appBundleId + "." + purchase.rawValue + + switch purchase { + case .autoRenewablePurchase: + let purchaseResult = SwiftyStoreKit.verifySubscription( + ofType: .autoRenewable, + productId: productId, + inReceipt: receipt, + validUntil: Date() + ) + self.showAlert(self.alertForVerifySubscription(purchaseResult)) + case .nonRenewingPurchase: + let purchaseResult = SwiftyStoreKit.verifySubscription( + ofType: .nonRenewing(validDuration: 60), + productId: productId, + inReceipt: receipt, + validUntil: Date() + ) + self.showAlert(self.alertForVerifySubscription(purchaseResult)) + default: + let purchaseResult = SwiftyStoreKit.verifyPurchase( + productId: productId, + inReceipt: receipt + ) + self.showAlert(self.alertForVerifyPurchase(purchaseResult)) + } + + case .error: + self.showAlert(self.alertForVerifyReceipt(result)) + } + } + } + +#if os(iOS) + override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } +#endif + override func alertForRestorePurchases(_ results: RestoreResults) -> UIAlertController { + + if results.restoreFailedPurchases.count > 0 { + print("Restore Failed: \(results.restoreFailedPurchases)") + return alertWithTitle("Restore failed", message: "Unknown error. Please contact support") + } else if results.restoredPurchases.count > 0 { + print("Restore Success: \(results.restoredPurchases)") + //statusButton.setTitle("Not Purchased", for: .normal) + UserDefaults.standard.set("", forKey: buyKey) + UserDefaults.standard.synchronize() + + return alertWithTitle("Purchases Restored", message: "All purchases have been restored") + } else { + print("Nothing to Restore") + return alertWithTitle("Nothing to restore", message: "No previous purchases were found") + } + } +} + +// MARK: User facing alerts +extension ViewController { + + +} diff --git a/Surf/ChartsView.swift b/Surf/ChartsView.swift new file mode 100644 index 0000000..485ff28 --- /dev/null +++ b/Surf/ChartsView.swift @@ -0,0 +1,160 @@ +// +// ChartsCell.swift +// Surf +// +// Created by abigt on 2017/6/29. +// Copyright © 2017年 abigt. All rights reserved. +// + +import UIKit +import Charts +import SFSocket +import XRuler + +class ChartsView:UIView,ChartViewDelegate { + @IBOutlet var chatView:LineChartView? + + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + override func awakeFromNib(){ + if let c = chatView { + // c.delegate = self + + c.chartDescription?.enabled = false + c.dragEnabled = true + c.setScaleEnabled(true) + c.drawGridBackgroundEnabled = true + c.pinchZoomEnabled = true + c.backgroundColor = UIColor.init(white: 204/255.0, alpha: 1.0) + + let l:Legend = c.legend; + l.form = .line; + l.font = UIFont.systemFont(ofSize: 11.0)// [UIFont fontWithName:@"HelveticaNeue-Light" size:11.f]; + l.textColor = UIColor.white; + l.horizontalAlignment = .left; + l.verticalAlignment = .bottom; + l.orientation = .horizontal; + l.drawInside = false; + + let xAxis:XAxis = c.xAxis; + xAxis.labelFont = UIFont.systemFont(ofSize: 11.0) + xAxis.labelTextColor = UIColor.white; + xAxis.drawGridLinesEnabled = false; + xAxis.drawAxisLineEnabled = false; + xAxis.axisMaximum = 60 + + let leftAxis:YAxis = c.leftAxis; + leftAxis.labelTextColor = UIColor.cyan + leftAxis.axisMaximum = 50 + leftAxis.axisMinimum = 0.0; + leftAxis.drawGridLinesEnabled = true; + leftAxis.drawZeroLineEnabled = false; + leftAxis.granularityEnabled = true; + +// let rightAxis:YAxis = c.rightAxis; +// rightAxis.labelTextColor = UIColor.red; +// rightAxis.axisMaximum = 900.0; +// rightAxis.axisMinimum = -200.0; +// rightAxis.drawGridLinesEnabled = false; +// rightAxis.granularityEnabled = false; + +// _sliderX.value = 20.0; +// _sliderY.value = 30.0; + // [self slidersValueChanged:nil]; + // c.animate(xAxisDuration: 2.5) + + } + } + func updateFlow(_ flow:NetFlow) { + let data = flow.flow(.total) + self.update(data) + } + func update(_ data:[Double]){ + + var yVals1:[ChartDataEntry] = [] + var index :Double = 0 + + var unit = "KB/s" + var sbq:Double = 1.0 + let rate = 1.2 + if let max = data.max() { + + + + + if max < 1024{ + unit = "B/s" + sbq = 1 + }else if max >= 1024 && max < 1024*1024 { + sbq = 1024.0 + unit = "KB/s" + }else if max >= 1024*1024 && max < 1024*1024*1024 { + //return label + "\(x/1024/1024) MB" + s + unit = "MB/s" + sbq = 1024.0*1024.0 + }else { + //return label + "\(x/1024/1024/1024) GB" + s + unit = "GB/s" + sbq = 1024.0*1024.0*1024 + } + } + + + for i in data { + let yy:Double = i / sbq + + let y = ChartDataEntry.init(x: index, y: yy) + yVals1.append(y) + index += 1 + } + var set1:LineChartDataSet + if let cc = chatView { + + let leftAxis:YAxis = cc.leftAxis; + leftAxis.labelTextColor = UIColor.cyan + + if let max = data.max() { + + leftAxis.axisMaximum = max * rate/sbq + + + + } + + if let d = cc.data { + if d.dataSetCount > 0 { + set1 = d.dataSets[0] as! LineChartDataSet + set1.values = yVals1 + set1.label = unit + cc.data!.notifyDataChanged() + cc.notifyDataSetChanged() + } + }else { + + + set1 = LineChartDataSet.init(values: yVals1, label: unit) + set1.axisDependency = .left; + set1.drawFilledEnabled = true + set1.mode = .cubicBezier + set1.drawValuesEnabled = false + set1.setColor(UIColor.red) + set1.setCircleColor(UIColor.white) + set1.lineWidth = 2.0; + set1.circleRadius = 3.0; + set1.fillAlpha = 65/255.0; + set1.drawCirclesEnabled = false + set1.fillColor = UIColor.brown + set1.highlightColor = UIColor.yellow + set1.drawCircleHoleEnabled = false; + + let ids:[IChartDataSet] = [set1] + let ldata:LineChartData = LineChartData.init(dataSets: ids) + ldata.setValueTextColor(UIColor.white) + ldata.setValueFont(UIFont.systemFont(ofSize: 9.0)) + cc.data = ldata + } + } + } +} diff --git a/Surf/CheckTableViewController.swift b/Surf/CheckTableViewController.swift new file mode 100644 index 0000000..87d3f22 --- /dev/null +++ b/Surf/CheckTableViewController.swift @@ -0,0 +1,95 @@ +// +// CheckTableViewController.swift +// Surf +// +// Created by abigt on 2018/1/13. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import UIKit + +class CheckTableViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 0 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 0 + } + + /* + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/ClientTunnelConnection.swift b/Surf/ClientTunnelConnection.swift new file mode 100644 index 0000000..722117f --- /dev/null +++ b/Surf/ClientTunnelConnection.swift @@ -0,0 +1,116 @@ +/* + Copyright (C) 2015 Apple Inc. All Rights Reserved. + See LICENSE.txt for this sample’s licensing information + + Abstract: + This file contains the ClientTunnelConnection class. The ClientTunnelConnection class handles the encapsulation and decapsulation of IP packets in the client side of the SimpleTunnel tunneling protocol. +*/ + +import Foundation +import NetworkExtension +#if os(iOS) +import SimpleTunnelServices +#else + import SimpleTunnelServicesMac +#endif +// MARK: Protocols + +/// The delegate protocol for ClientTunnelConnection. +protocol ClientTunnelConnectionDelegate { + /// Handle the connection being opened. + func tunnelConnectionDidOpen(connection: ClientTunnelConnection, configuration: [NSObject: AnyObject]) + /// Handle the connection being closed. + func tunnelConnectionDidClose(connection: ClientTunnelConnection, error: NSError?) +} + +/// An object used to tunnel IP packets using the SimpleTunnel protocol. +class ClientTunnelConnection: Connection { + + // MARK: Properties + + /// The connection delegate. + let delegate: ClientTunnelConnectionDelegate + + /// The flow of IP packets. + let packetFlow: NEPacketTunnelFlow + + // MARK: Initializers + + init(tunnel: ClientTunnel, clientPacketFlow: NEPacketTunnelFlow, connectionDelegate: ClientTunnelConnectionDelegate) { + delegate = connectionDelegate + packetFlow = clientPacketFlow + let newConnectionIdentifier = arc4random() + super.init(connectionIdentifier: Int(newConnectionIdentifier), parentTunnel: tunnel) + } + + // MARK: Interface + + /// Open the connection by sending a "connection open" message to the tunnel server. + func open() { + guard let clientTunnel = tunnel as? ClientTunnel else { return } + + let properties = createMessagePropertiesForConnection(identifier, commandType: .Open, extraProperties:[ + TunnelMessageKey.TunnelType.rawValue: TunnelLayer.IP.rawValue + ]) + + clientTunnel.sendMessage(properties) { error in + if let error = error { + self.delegate.tunnelConnectionDidClose(self, error: error) + } + } + NSLog("send properties:%@",properties) + } + + /// Handle packets coming from the packet flow. + func handlePackets(packets: [NSData], protocols: [NSNumber]) { + guard let clientTunnel = tunnel as? ClientTunnel else { return } + + let properties = createMessagePropertiesForConnection(identifier, commandType: .Packets, extraProperties:[ + TunnelMessageKey.Packets.rawValue: packets, + TunnelMessageKey.Protocols.rawValue: protocols + ]) + + clientTunnel.sendMessage(properties) { error in + if let sendError = error { + self.delegate.tunnelConnectionDidClose(self, error: sendError) + return + } + + // Read more packets. + self.packetFlow.readPacketsWithCompletionHandler { inPackets, inProtocols in + self.handlePackets(inPackets, protocols: inProtocols) + } + } + } + + /// Make the initial readPacketsWithCompletionHandler call. + func startHandlingPackets() { + packetFlow.readPacketsWithCompletionHandler { inPackets, inProtocols in + self.handlePackets(inPackets, protocols: inProtocols) + } + } + + // MARK: Connection + + /// Handle the event of the connection being established. + override func handleOpenCompleted(resultCode: TunnelConnectionOpenResult, properties: [NSObject: AnyObject]) { + guard resultCode == .Success else { + delegate.tunnelConnectionDidClose(self, error: SimpleTunnelError.BadConnection as NSError) + return + } + + // Pass the tunnel network settings to the delegate. + if let configuration = properties[TunnelMessageKey.Configuration.rawValue] as? [NSObject: AnyObject] { + delegate.tunnelConnectionDidOpen(self, configuration: configuration) + } + else { + delegate.tunnelConnectionDidOpen(self, configuration: [:]) + } + NSLog("send properties:%@",properties) + } + + /// Send packets to the virtual interface to be injected into the IP stack. + override func sendPackets(packets: [NSData], protocols: [NSNumber]) { + packetFlow.writePackets(packets, withProtocols: protocols) + } +} diff --git a/Surf/ConfigEditViewController.swift b/Surf/ConfigEditViewController.swift new file mode 100644 index 0000000..7fdaf0d --- /dev/null +++ b/Surf/ConfigEditViewController.swift @@ -0,0 +1,153 @@ +// +// ConfigEditViewController.swift +// Surf +// +// Created by 孔祥波 on 7/20/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +class ConfigEditViewController: UIViewController { + //@IBOutlet var textViewBottomConst:NSLayoutConstraint! + var url:URL! + var titleView:TitleView? + @IBOutlet var textView:UITextView! + func alertMessageAction(_ message:String,complete:(() -> Void)?) { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: message, preferredStyle: style) + let action = UIAlertAction.init(title: "OK", style: .default) { (action:UIAlertAction) -> Void in + if let callback = complete { + callback() + } + } + alert.addAction(action) + self.present(alert, animated: true) { () -> Void in + + } + } + + override func viewDidLoad() { + super.viewDidLoad() + guard let config = SFConfigManager.manager.selectConfig else {return} + self.url = SFConfigManager.manager.urlForConfig(config) + let string = try! String.init(contentsOf: url, encoding: .utf8) + //NSString.init(contentsOfURL: url, usedEncoding: NSUTF8StringEncoding) + self.textView.text = string + titleView = TitleView.init(frame: CGRect(x:0, y:0, width:240,height: 60)); + //titleView?.backgroundColor = UIColor.cyanColor() + navigationItem.titleView = titleView + + let btn = UIButton.init(type: .system) + btn.frame = CGRect(x:0, y:0, width: 22, height:22) + //btn.tintColor = UIColor.blueColor() + + btn.setImage(UIImage.init(named: "done"), for: .highlighted) + btn.setImage(UIImage.init(named: "done"), for: .normal) + btn.addTarget(self, action: #selector(ConfigEditViewController.doneAction(_:)), for: .touchUpInside) + navigationItem.rightBarButtonItem = UIBarButtonItem.init(customView: btn) + + NotificationCenter.default.addObserver(self, selector: #selector(ConfigEditViewController.keyboardShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(ConfigEditViewController.keyboardHiden(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) + // Do any additional setup after loading the view. + } + @objc func keyboardShow(_ noti:NSNotification){ + guard let info = noti.userInfo else {return} + let keyboardFrameValue:NSValue = info[UIKeyboardFrameEndUserInfoKey] as! NSValue + let keyboardFrame = keyboardFrameValue.cgRectValue + var contentInsets: UIEdgeInsets = self.textView.contentInset; + contentInsets.bottom = keyboardFrame.height; + self.textView.contentInset = contentInsets; + self.textView.scrollIndicatorInsets = contentInsets; + } + @objc func keyboardHiden(_ noti:NSNotification){ + var contentInsets:UIEdgeInsets = self.textView.contentInset; + contentInsets.bottom = 0.0; + + self.textView.contentInset = contentInsets; + self.textView.scrollIndicatorInsets = contentInsets; + } + + @objc func doneAction(_ sender:AnyObject){ + let content = textView.text + var c = ProxyGroupSettings.share.config + if c.hasSuffix(".conf"){ + c = c.components(separatedBy: ".conf").first! + } + if !removeFile(url){ + return + } + do { + try content?.write(to: url, atomically:true, encoding: String.Encoding.utf8) + + }catch let e as NSError{ + alertMessageAction("Save Config Error \(e.localizedDescription)", complete: nil) + return + } + if let s = SFConfigManager.manager.selectConfig { + SFConfigManager.manager.reloadConfig(s.configName) + } + SFConfigManager.manager.writeToGroup(c) + + _ = self.navigationController?.popViewController(animated: true) + } + func removeFile(_ u:URL) ->Bool { + if fm.fileExists(atPath: u.path){ + do { + try fm.removeItem(at: u) + return true + + }catch let e as NSError { + alertMessageAction("Save Config Error \(e.localizedDescription)", complete: nil) + return false + + } + } + return true + } + func updateTitleView(_ config:String){ + let x = config.components(separatedBy:".").first! + let url = applicationDocumentsDirectory.appendingPathComponent(config) + if fm.fileExists(atPath: url.path){ + let config = SFConfig.init(path: url.path, loadRule: true) + self.titleView?.subLabel.text = config.description() + }else { + self.titleView?.subLabel.text = "Config not Found,Please Add" + + } + + + self.titleView?.titleLabel.text = x + + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + let c = ProxyGroupSettings.share.config + updateTitleView(c) + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/ConfigTableViewController.swift b/Surf/ConfigTableViewController.swift new file mode 100644 index 0000000..2c3c264 --- /dev/null +++ b/Surf/ConfigTableViewController.swift @@ -0,0 +1,640 @@ +// +// ConfigTableViewController.swift +// Surf +// +// Created by abigt on 16/1/18. +// Copyright © 2016年 abigt. All rights reserved. +// + + +import UIKit +import Foundation +import SFSocket +import XRuler +import Xcon +@objc protocol ConfigTableViewControllerDelegate:class { + func saveConfig(controller: ConfigTableViewController, config:String,edit:Bool)// file name + +} +public enum SFConfigMode:Int, CustomStringConvertible{ + case Edit = 0 + case NewDefault = 1 + case NewDefaultRule = 2 + public var description: String { + switch self { + case .Edit:return "Edit" + case .NewDefault:return "NewDefault" + case .NewDefaultRule:return "NewDefaultRule" + } + } +} +struct SFAction { + var title:String + var action:String + init(t:String,a:String){ + title = t + action = a + } +} +class ConfigTableViewController: SFTableViewController,LoglevelDelegate ,AddEditProxyDelegate,AddEditRulerDelegate{ + + + var config:SFConfig? + var mode:SFConfigMode = .Edit + + var fileName:String = "" + weak var delegate:ConfigTableViewControllerDelegate? + var misc:[SFAction] = []// + weak var nameField:UITextField? +// override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { +// super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) +// +// } + + func loadSFConfig(){ + var path:String? + switch mode { + case .Edit: + if !fileName.isEmpty{ + let url = applicationDocumentsDirectory.appendingPathComponent(fileName) + path = url.path + + }else { + path = Bundle.main.path(forResource: DefaultConfig, ofType: nil) + + } + case .NewDefault: + path = Bundle.main.path(forResource: DefaultConfig, ofType: nil) + + case .NewDefaultRule: + path = Bundle.main.path(forResource: sampleConfig, ofType: nil) + + } + if let p = path { + let q = DispatchQueue(label:"com.abigt.config") + q.async ( execute: { [unowned self] in + self.config = SFConfig.init(path: p,loadRule: true) + DispatchQueue.main.async(execute:{ + self.tableView.reloadData() + }) + + }) + + }else { + alertMessageAction("Error load Config", complete: nil) + } + + } + func loadMisc() { + let x:[String:String] = ["Export To iTunes Share":"itunesShare","Export To iCloud":"icloudShare","Duplicate":"duplicate"] + for (key,value) in x { + let y = SFAction.init(t: key, a: value) + misc.append(y) + } + } + override func viewDidLoad() { + super.viewDidLoad() + //self.title = "Config Rules" + loadMisc() + if config == nil { + loadSFConfig() + }else { + fileName = config!.configName + configExt + } + + //let = UILabel.init() + let back = UIBarButtonItem.init(title: "Cancel", style: .plain, target: self, action: #selector(ConfigTableViewController.backAction(_:))) + let done = UIBarButtonItem.init(title: "Done", style: .plain, target: self, action: #selector(ConfigTableViewController.doneAction(_:))) + self.navigationItem.leftBarButtonItem = back + self.navigationItem.rightBarButtonItem = done + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + self.tableView.reloadData() + } + @objc func backAction(_ sender:AnyObject){ + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: "Discard unsaved changed?", preferredStyle: style) + let action = UIAlertAction.init(title: "Stay", style: .default) { (action:UIAlertAction) -> Void in + + } + let action2 = UIAlertAction.init(title: "Discard", style: .default) { (action:UIAlertAction) -> Void in + _ = self.navigationController?.popViewController(animated:true) + } + + alert.addAction(action) + alert.addAction(action2) + + + self.present(alert, animated: true) { () -> Void in + + } + + + } + @objc func doneAction(_ sender:AnyObject){ + + + var alertMessage:String? + //var force:Bool = false + if let config = self.config { + var toName:String = "" + if let f = self.nameField { // Done maybe input not finish + toName = f.text! + } + + if toName.isEmpty { + alertMessageAction("Configuration Name invalid",complete: nil) + return + } + let error:SFConfigWriteError = config.writeConfig(name: toName, copy: false, force: true,shareiTunes: false) + switch error { + case .success: + + if toName == config.configName { + delegate?.saveConfig(controller: self, config: config.configName, edit: true) + }else { + delegate?.saveConfig(controller: self, config: toName, edit: false) + } + _ = self.navigationController?.popViewController(animated: true) + return + case .exist: + alertMessage = "\(error.description), force save?" + case .noName: + alertMessage = "\(error.description), please input Name" + case .other: + alertMessage = "\(error.description) error" + } + } + if let message = alertMessage { + + alertMessageAction(message, complete: nil) + } + + } +// func loadRuler(inout ruler:[SFRuler],j:JSON,type:SFRulerType) { +// if j.error == nil{ +// //print(j) +// if j.type == .Dictionary { +// for (key,value) in j.dictionaryValue{ +// let r = SFRuler() +// r.name = key +// r.type = type +// let p = value["Proxy"] +// if p.error == nil { +// r.proxyName = p.stringValue +// } +// ruler.append(r) +// } +// } +// }else { +// //show error +// } +// } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + var title = "" + switch section { + case 0: + title = "NAME" + case 1: + title = "GENERAL" +// case 2: +// title = "PROXY" + case 2: + title = "RULE" + case 3: + title = "MISC" + default: + break + } + return title + } + override func numberOfSections(in tableView: UITableView) -> Int { + return 4 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + var count = 0 + if let config = self.config { + switch section { + case 0: + count = 1 //name + case 1: + count = 1 //general +// case 2: +// +// count = 1 + config.proxys.count + case 2: + let c = config.keyworldRulers.count + config.ipcidrRulers.count + config.sufixRulers.count + config.geoipRulers.count + config.agentRuler.count + 1 + if c > 0 { + count = 3 + }else { + count = 2 + } + //rulers + case 3: + count = misc.count + default: + break + } + } + + + return count + } + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + + if indexPath.section == 0 { + return nil + } + return indexPath + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + if let config = self.config { + switch indexPath.section { + case 0 : + let cell = tableView.dequeueReusableCell(withIdentifier: "name") as! TextFieldCell + + cell.textField.text = config.configName + cell.wwdcStyle() + + self.nameField = cell.textField + cell.valueChanged = { [weak self] (textfield:UITextField) -> Void in + let text = textfield.text! + if self!.config!.configName != text{ + self!.config!.configName = text + self!.config!.changed = true + } + + } + cell.wwdcStyle() + return cell + case 1 : + let cell = tableView.dequeueReusableCell(withIdentifier: "loglevel") as! TwoLableCell + + if let g = config.general { + cell.cellLabel.text = g.loglevel + } + cell.wwdcStyle() + return cell + + case 2 : + let c = config.keyworldRulers.count + config.ipcidrRulers.count + config.sufixRulers.count + config.geoipRulers.count + config.agentRuler.count + 1 + var count = 1 + + if c > 0{ + count = 2 + } + + var cell:UITableViewCell? + if count == 2 { + if indexPath.row == 0{ + cell = tableView.dequeueReusableCell(withIdentifier:"twoline") + cell?.textLabel!.text = "Rules" + + cell?.detailTextLabel!.text = "\(c) Rules" + + + }else if indexPath.row == 1{ + + cell = tableView.dequeueReusableCell(withIdentifier:"twoline") + cell?.textLabel!.text = "DNS Map ..." + + cell?.detailTextLabel?.text = "\(config.hosts.count) Record" + + }else { + + cell = tableView.dequeueReusableCell(withIdentifier: "twoline") + cell?.textLabel!.text = "DNS Server ..." + + if let g = config.general { + cell?.detailTextLabel?.text = "\(g.dnsserver.count) Record" + }else { + cell?.detailTextLabel?.text = "" + } + + + } + cell?.updateStandUI() + + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "AddRule") + cell?.textLabel!.text = "Add Rule ..." + cell?.updateStandUI() + + + } + return cell! + case 3: + let cell = tableView.dequeueReusableCell(withIdentifier:"AddRule") + let m = misc[indexPath.row] + cell?.textLabel!.text = m.title + cell?.updateStandUI() + + return cell! + + default: + break + } + } + + let cell = UITableViewCell() + cell.textLabel?.text = "config error" + return cell + + } + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + +// if indexPath.section == 2 { +// if let c = config { +// if indexPath.row < c.proxys.count { +// return true +// } +// } +// +// } + return false + } + override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { + +// if indexPath.section == 2 { +// if let c = config { +// if indexPath.row < c.proxys.count { +// return .Delete +// } +// } +// +// } + return .none + } + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + + if editingStyle == .delete{ + if indexPath.section == 2 { + if let c = config { + if indexPath.row < c.proxys.count { + c.proxys.remove(at: indexPath.row) + tableView.deleteRows(at: [indexPath], with: .automatic) + } + } + + } + + } + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + + tableView.deselectRow(at: indexPath, animated: false) + switch indexPath.section{ + case 0: break + case 1: break + //self.performSegue(withIdentifier:"loglevel", sender: tableView.cellForRowAtIndexPath(indexPath)) +// case 2: +// self.performSegue(withIdentifier:"AddEditProxy", sender: tableView.cellForRowAtIndexPath(indexPath)) + case 2: + if indexPath.row == 0{ + self.performSegue(withIdentifier: "showRules", sender: tableView.cellForRow(at: indexPath)) + }else if indexPath.row == 1{ + self.performSegue(withIdentifier: "showHosts", sender: tableView.cellForRow(at: indexPath)) + }else { + self.performSegue(withIdentifier: "dnsServer", sender: tableView.cellForRow(at: indexPath)) + } + + case 3: + let m = misc[indexPath.row] + miscSwith(m: m) + default: + break + } + //delegate?.importFileConfig(self, config: iTunesFiles[indexPath.row]) + } + func miscSwith(m:SFAction) { + //["Export To iTunes Share":"itunesShare","Export To iCloud":"icloudShare","Duplicate":"duplicate"] + let action = m.action + //performSelector not support in Swift lang + if action == "itunesShare" { + itunesShare() + }else if action == "icloudShare" { + icloudShare() + }else if action == "duplicate" { + duplicate() + }else { + + } + + } + func itunesShare(){ + if let c = config { + if c.writeConfig(name: c.configName, copy: false, force: true,shareiTunes: true) == .success { + alertMessageAction("iTunes Share save Success",complete: nil) + }else { + alertMessageAction("iTunes Share save failed",complete: nil) + } + }else { + alertMessageAction("config invale",complete: nil) + } + + + } + + func duplicate(){ + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: "Please input Config Name", preferredStyle: style) + let action = UIAlertAction.init(title: "OK", style: .default) { [weak self] (action:UIAlertAction) -> Void in + if let field = alert.textFields?.first { + if let configName = field.text { + if !configName.isEmpty { + if self!.config?.writeConfig(name: configName, copy: true, force: true,shareiTunes: false) == .success { + self!.delegate?.saveConfig(controller: self!, config: configName, edit: false) + _ = self!.navigationController?.popViewController(animated: true) + }else { + self!.alertMessageAction("Error",complete: nil) + } + }else { + self!.alertMessageAction("config Name invalid",complete: nil) + } + } + } + } + let actionC = UIAlertAction.init(title: "Cancel", style: .default) { (action:UIAlertAction) -> Void in + + } + alert.addTextField { (textfield) -> Void in + + } + alert.addAction(action) + alert.addAction(actionC) + self.present(alert, animated: true) { () -> Void in + + } + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if segue.identifier == "loglevel" { + guard let c = segue.destination as? LoglevelTableViewController else {return} + c.delegate = self + // c.general = config?.general + }else if segue.identifier == "AddEditProxy"{ + guard let c = segue.destination as? AddEditProxyController else {return} + guard let indexPath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + if indexPath.row < (config?.proxys.count)!{ + c.proxy = config?.proxys[indexPath.row] + } + c.delegate = self + }else if segue.identifier == "showRules" { + guard let c = segue.destination as? RulesTableViewController else {return} + c.config = self.config + + }else if segue.identifier == "addRule" { + guard let c = segue.destination as? RuleTableViewController else {return} + c.config = self.config + c.delegate = self + }else if segue.identifier == "showHosts" { + guard let c = segue.destination as? HostsTableViewController else {return} + c.config = self.config + //c.delegate = self + }else if segue.identifier == "dnsServer" { + guard let c = segue.destination as? DNSViewController else {return} + c.config = self.config + //c.delegate = self + } + } + func addRulerConfig(controller: RuleTableViewController, rule:SFRuler){ + switch rule.type { + case .domainkeyword: + config!.keyworldRulers.append(rule) + case .ipcidr: + config!.ipcidrRulers.append(rule) + case .domainsuffix: + config!.sufixRulers.append(rule) + case .geoip: + config!.geoipRulers.append(rule) + case .agent: + config!.agentRuler.append(rule) + default: + break + } + tableView.reloadData() + } + func editRulerConfig(controller: RuleTableViewController, rule:SFRuler,newType:SFRulerType){ + tableView.reloadData() + } + open override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { + let v = view as! UITableViewHeaderFooterView + if ProxyGroupSettings.share.wwdcStyle { + v.contentView.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + }else { + v.contentView.backgroundColor = UIColor.groupTableViewBackground + } + + } + open override func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int){ + let v = view as! UITableViewHeaderFooterView + if ProxyGroupSettings.share.wwdcStyle { + v.contentView.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + }else { + v.contentView.backgroundColor = UIColor.groupTableViewBackground + } + + } + func didSelectLogLevel(controller: LoglevelTableViewController){ + if let config = config{ + config.changed = true + tableView.reloadData() + } + + } + func addProxyConfig(_ controller: AddEditProxyController, proxy: SFProxy) { + + if let config = config{ + + config.proxys.append(proxy) + tableView.reloadData() + } + } + func editProxyConfig(_ controller: AddEditProxyController, proxy:SFProxy){ + if let config = config{ + config.changed = true + //config.proxys.append(proxy) + tableView.reloadData() + } + } + +} +extension ConfigTableViewController: UIDocumentPickerDelegate{//UIDocumentMenuDelegate + + func icloudShare() { + // let importMenu = UIDocumentMenuViewController.init(documentTypes: [configExt], inMode: .Import) + // importMenu.delegate = self + // self.present(importMenu, animated: true) { () -> Void in + // + // } + //kUTTypeJSON + //self.alertMessageAction("Export Config need todo") + let document = applicationDocumentsDirectory + let dest = document.appendingPathComponent(config!.configName + configExt) + + if let data = config?.genData() { + + try! data.write(to: dest, atomically: true,encoding:String.Encoding.utf8) + //alertMessageAction("Export Success!!") + }else { + alertMessageAction("Export Config Failure",complete: nil) + return + } + + + let picker = UIDocumentPickerViewController.init(url: dest, in: .exportToService) + picker.delegate = self + self.present(picker, animated: true) { () -> Void in + + } + } + // internal func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) + // { + // self.dismissViewControllerAnimated(true) { () -> Void in + // + // } + // } + // + // + // internal func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController){ + // self.dismissViewControllerAnimated(true) { () -> Void in + // + // } + // } + internal func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL){ + print(url) + + self.dismiss(animated: true) { () -> Void in + + } + + } + + internal func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController){ + self.dismiss(animated: true) { () -> Void in + } + } +} diff --git a/Surf/CountrySelectController.swift b/Surf/CountrySelectController.swift new file mode 100644 index 0000000..042f9fc --- /dev/null +++ b/Surf/CountrySelectController.swift @@ -0,0 +1,53 @@ +// +// CountrySelectController.swift +// Surf +// +// Created by abigt on 16/2/22. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +protocol CountryDelegate:class { + func countrySelected(controller: CountrySelectController, code:String)// +} +class CountrySelectController: SFTableViewController { + var list:[String] = [] + weak var delegate:CountryDelegate? + //var code:String! + func loadCountrys(){ + let path = Bundle.main.path(forResource: "ISO_3166.txt", ofType: nil) + + do { + let str = try String.init(contentsOfFile: path!, encoding: .utf8) + list = str.components(separatedBy: "\n") + }catch let error { + alertMessageAction("\(error.localizedDescription)",complete: nil) + } + } + override func viewDidLoad() { + self.title = "Select Country" + loadCountrys() + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return list.count + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) + cell.textLabel?.text = list[indexPath.row] + return cell + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + self.delegate?.countrySelected(controller: self, code: list[indexPath.row]) + _ = self.navigationController?.popViewController(animated: true) + } +} diff --git a/Surf/DNSViewController.swift b/Surf/DNSViewController.swift new file mode 100644 index 0000000..290c7c6 --- /dev/null +++ b/Surf/DNSViewController.swift @@ -0,0 +1,89 @@ +// +// DNSViewController.swift +// Surf +// +// Created by abigt on 16/5/25. +// Copyright © 2016年 abigt. All rights reserved. +// + + +import UIKit +import SFSocket +import XRuler +class DNSViewController: HostEditTableViewController { + var dnsString:String = "" + var config:SFConfig! + override func viewDidLoad() { + super.viewDidLoad() + self.title = "DNS Server" + let edit = UIBarButtonItem.init(barButtonSystemItem: .done, target: self, action: #selector(HostEditTableViewController.doneAction(_:))) + navigationItem.rightBarButtonItem = edit + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + override func doneAction(_ anyObject:AnyObject) { + // if let _ = delegate { + let indexPath = IndexPath.init(row: 0, section: 0) + let cell = tableView.cellForRow(at: indexPath) as! TextFieldCell + let result = cell.textField.text! + if let g = config.general { + + g.updateDNS(result) + } + + + + //d.hostDidChange(self, new: new) + //} + _ = navigationController?.popViewController(animated: true) + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + return "DNS Server Setting" + } + override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { + return "You can overide the System Default DNS Server" + } + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 1 + } + + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "hostCell", for: indexPath as IndexPath) as! TextFieldCell + + // Configure the cell... + if indexPath.section == 0 { + cell.wwdcStyle() + + cell.textField.placeholder = "Separated by Commas," + if let g = config.general { + cell.textField.text = g.dnsString() + } + } + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: true) + let cell = tableView.cellForRow(at: indexPath) as! TextFieldCell + cell.textField.becomeFirstResponder() + } +} diff --git a/Surf/DataShare.swift b/Surf/DataShare.swift new file mode 100644 index 0000000..9c6b79a --- /dev/null +++ b/Surf/DataShare.swift @@ -0,0 +1,38 @@ +// +// DataShare.swift +// Surf +// +// Created by abigt on 15/12/4. +// Copyright © 2015年 abigt. All rights reserved. +// + +import Foundation +class DataShare:NSObject{ + static func save(sock:Socks) ->Bool{ + let path = DataShare.configPath() + let r = NSKeyedArchiver.archiveRootObject(sock, toFile: path ) + if r { + print("saved") + return true + }else { + print("n") + return false + } + } + static func configPath() ->String{ + + let urlContain = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.abigt.Surf") + let url = urlContain!.appendingPathComponent(".config") + let u = url.path + return u + + } + static func readConfig() ->Socks{ + let path = DataShare.configPath() + let x = NSKeyedUnarchiver.unarchiveObject(withFile: path) + if let list = x { + return list as! Socks + } + return Socks() + } +} diff --git a/Surf/DebugViewController.swift b/Surf/DebugViewController.swift new file mode 100644 index 0000000..9965670 --- /dev/null +++ b/Surf/DebugViewController.swift @@ -0,0 +1,106 @@ +// +// DebugViewController.swift +// Surf +// +// Created by 孔祥波 on 7/18/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit + +class DebugViewController: SFTableViewController { + + let config:[String] = ["DNS","WI-FI","CELL"] + var dns:[String] = [] + override func viewDidLoad() { + super.viewDidLoad() + let edit = UIBarButtonItem.init(barButtonSystemItem: .add, target: self, action: #selector(DebugViewController.loadXX(_:))) + navigationItem.rightBarButtonItem = edit + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + func loadXX(_ sender:AnyObject){ + + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of rows + return 1 + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return config.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "debug", for: indexPath) + + // Configure the cell... + cell.textLabel?.text = config[indexPath.row] + switch indexPath.row { + case 0: + cell.detailTextLabel?.text = "" + default: + break + } + return cell + } + + + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/Default.conf b/Surf/Default.conf new file mode 100644 index 0000000..6237f31 --- /dev/null +++ b/Surf/Default.conf @@ -0,0 +1,17 @@ +[General] +skip-proxy = 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, localhost, *.local +bypass-tun = bypass-tun = 10.0.0.0/8, 172.0.0.0/8, 0.0.0.0/8, 1.0.0.0/9, 1.160.0.0/11, 1.192.0.0/11, 10.0.0.0/8, 14.0.0.0/11, 14.96.0.0/11, 14.128.0.0/11, 14.192.0.0/11, 27.0.0.0/10, 27.96.0.0/11, 27.128.0.0/9, 36.0.0.0/10, 36.96.0.0/11, 36.128.0.0/9, 39.0.0.0/11, 39.64.0.0/10, 39.128.0.0/10, 42.0.0.0/8, 43.224.0.0/11, 45.64.0.0/10, 47.64.0.0/10, 49.0.0.0/9, 49.128.0.0/11, 49.192.0.0/10, 54.192.0.0/11, 58.0.0.0/9, 58.128.0.0/11, 58.192.0.0/10, 59.32.0.0/11, 59.64.0.0/10, 59.128.0.0/9, 60.0.0.0/10, 60.160.0.0/11, 60.192.0.0/10, 61.0.0.0/10, 61.64.0.0/11, 61.128.0.0/10, 61.224.0.0/11, 100.64.0.0/10, 101.0.0.0/9, 101.128.0.0/11, 101.192.0.0/11, 101.228.0.0/14, 101.232.0.0/13, 101.240.0.0/12, 103.0.0.0/10, 103.192.0.0/10, 106.224.0.0/11, 110.0.0.0/8, 111.0.0.0/11, 111.32.0.0/12, 111.48.0.0/13, 111.56.0.0/14, 111.60.0.0/15, 111.62.0.0/16, 111.64.0.0/10, 111.128.0.0/9, 112.0.0.0/9, 112.128.0.0/11, 112.192.0.0/10, 113.0.0.0/9, 113.128.0.0/11, 113.192.0.0/10, 114.0.0.0/9, 114.128.0.0/11, 114.192.0.0/10, 115.0.0.0/8, 116.0.0.0/8, 117.0.0.0/9, 117.128.0.0/10, 118.0.0.0/11, 118.64.0.0/10, 118.128.0.0/9, 119.0.0.0/9, 119.128.0.0/10, 119.224.0.0/11, 120.0.0.0/10, 120.64.0.0/11, 120.128.0.0/11, 120.192.0.0/10, 121.0.0.0/9, 121.192.0.0/10, 122.0.0.0/8, 123.0.0.0/10, 123.64.0.0/11, 123.96.0.0/12, 123.112.0.0/13, 123.120.0.0/14, 123.124.0.0/16, 124.0.0.0/8, 125.0.0.0/9, 125.160.0.0/11, 125.192.0.0/10, 127.0.0.0/8, 139.0.0.0/11, 139.128.0.0/9, 140.64.0.0/11, 140.128.0.0/11, 140.192.0.0/10, 144.0.0.0/10, 144.96.0.0/11, 144.224.0.0/11, 150.0.0.0/11, 150.96.0.0/11, 150.128.0.0/11, 150.192.0.0/10, 152.96.0.0/11, 153.0.0.0/10, 153.96.0.0/11, 157.0.0.0/10, 157.96.0.0/11, 157.128.0.0/11, 157.224.0.0/11, 159.224.0.0/11, 161.192.0.0/11, 162.96.0.0/11, 163.0.0.0/10, 163.96.0.0/11, 163.128.0.0/10, 163.192.0.0/11, 166.96.0.0/11, 167.128.0.0/10, 167.192.0.0/11, 168.160.0.0/11, 169.254.0.0/16, 171.0.0.0/9, 171.192.0.0/11, 172.16.0.0/12, 175.0.0.0/9, 175.128.0.0/10, 180.64.0.0/10, 180.128.0.0/9, 182.0.0.0/8, 183.0.0.0/10, 183.64.0.0/11, 183.128.0.0/9, 192.0.0.0/24, 192.0.2.0/24, 192.88.99.0/24, 192.96.0.0/11, 192.160.0.0/11, 198.18.0.0/15, 198.51.100.0/24, 202.0.0.0/9, 202.128.0.0/10, 202.192.0.0/11, 203.0.0.0/9, 203.128.0.0/10, 203.192.0.0/11, 210.0.0.0/10, 210.64.0.0/11, 210.160.0.0/11, 210.192.0.0/11, 211.64.0.0/10, 211.128.0.0/10, 218.0.0.0/9, 218.160.0.0/11, 218.192.0.0/10, 219.64.0.0/11, 219.128.0.0/11, 219.192.0.0/10, 220.96.0.0/11, 220.128.0.0/9, 221.0.0.0/11, 221.96.0.0/11, 221.128.0.0/9, 222.0.0.0/8, 223.0.0.0/11, 223.64.0.0/10, 223.128.0.0/9, 103.197.252.14/32 +dns-server = 119.29.29.29, 223.5.5.5, 114.114.114.114 +loglevel = notify + +[Proxy] +[Rule] + +// AD Block +// LAN +IP-CIDR,10.0.0.0/8,DIRECT +IP-CIDR,127.0.0.0/8,DIRECT +IP-CIDR,172.16.0.0/12,DIRECT +IP-CIDR,192.168.0.0/16,DIRECT + +FINAL,DIRECT diff --git a/Surf/FlyViewController.swift b/Surf/FlyViewController.swift new file mode 100644 index 0000000..92fc644 --- /dev/null +++ b/Surf/FlyViewController.swift @@ -0,0 +1,133 @@ +// +// FlyViewController.swift +// Surf +// +// Created by 孔祥波 on 8/3/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +class FlyViewController: UIViewController { + + var oriPoint:CGPoint? + @IBOutlet var plane:PlaneView! + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + if let touch = touches.first { + if touch.view === plane { + oriPoint = touch.location(in: self.view) + plane.center = oriPoint! + } + + + } + + } + override func touchesMoved(_ touches: Set, with event: UIEvent?) { + if let touch = touches.first { + + if let _ = oriPoint{ + oriPoint = touch.location(in: self.view) + plane.center = oriPoint! + } + + } + } + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + + if let touch = touches.first { + if let _ = oriPoint{ + oriPoint = touch.previousLocation(in: self.view) + plane.center = oriPoint! + goWith(t: touch) + + } + + } + } + func goWith(t:UITouch) { + let p = t.location(in: self.view) + if p.y < oriPoint!.y{ + print("ok") + let dx = p.x - oriPoint!.x + let dy = p.y - oriPoint!.y + let tt = dx / dy + + + + let dest = CGPoint.init(x: p.x - 800 * tt, y: p.y - 800) + UIView.animate(withDuration: 1.0, animations: { [weak self] in + self?.plane.center = dest + }, completion: { [weak self ](fin) in + if let s = self { + s.dail() + } + }) + }else { + print("failure") + } + } + func dail(){ + if let m = SFVPNManager.shared.manager { + if m.isEnabled { + let selectConf = ProxyGroupSettings.share.config + let _ = try! SFVPNManager.shared.startStopToggled(selectConf) + + }else { + m.isEnabled = true + SFVPNManager.shared.saveVPNManger({ (e) in + print("enabled save done") + }) + } + }else { + let vpnmanager = SFVPNManager.shared + if !vpnmanager.loading { + vpnmanager.loadManager() { + (manager, error) -> Void in + if let _ = manager { + //self!.tableView.reloadData() + //self!.registerStatus() + vpnmanager.xpc() + } + } + }else { + // mylog("vpnmanager loading") + } + + } + Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(FlyViewController.reset(_:)) , userInfo: nil, repeats: false) + } + @objc func reset(_ t:Timer){ + var x = true + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected { + x = false + } + } + if x{ + plane.center = self.view.center + } + } +} diff --git a/Surf/HelpTableViewController.swift b/Surf/HelpTableViewController.swift new file mode 100644 index 0000000..bd1d424 --- /dev/null +++ b/Surf/HelpTableViewController.swift @@ -0,0 +1,393 @@ +// +// HelpTableViewController.swift +// Surf +// +// Created by abigt on 15/12/3. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit +import StoreKit +import SFSocket +import IoniconsSwift +import XRuler +import XFoundation +class HelpTableViewController: SFTableViewController { + + let listmain:[String] = ["\u{f37a}iCloud sync","\u{f37b}Theme","\u{f36c}Advance","\u{f37f}Clean Cache"]//"⌘Proxy Chain", + + let list:[String] = ["\u{f12f}Config Sample View","\u{f12e}Config Manual Chinese Edition","\u{f243}Follow us on Twitter","\u{f388}Rate/Review On AppStore","\u{f141}Acknowledge"] + let funcTitles:[String] = ["Ad Block"] + + @IBOutlet var versionLable:UILabel? + @IBOutlet var logo:UIImageView? + @IBOutlet var logoBackgroundView:UIView? + func tURL() ->URL { + let tURL = "twitter://user?screen_name=Network_ext" + var u = URL.init(string: tURL)! + if UIApplication.shared.canOpenURL(u){ + return u + }else { + u = URL.init(string: "tweetbot://Network_ext/user_profile/Network_ext")! + if UIApplication.shared.canOpenURL(u) { + return u + }else { + let u = URL(string: "http://www.twitter.com/Network_ext")! + return u + } + + + } + } + override func viewDidLoad() { + super.viewDidLoad() + tableView.separatorInset=UIEdgeInsetsMake(0,50, 0, 0); + self.title = "Help".localized + logo?.layer.cornerRadius = 12.0 + logo?.layer.masksToBounds = true + + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + + override func refreshTheme(){ + super.refreshTheme() + if ProxyGroupSettings.share.wwdcStyle { + self.logoBackgroundView?.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + + }else { + self.logoBackgroundView?.backgroundColor = UIColor.groupTableViewBackground + } + + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if UserDefaults.standard.bool(forKey: "iCloudEnable") { + sync() + } + + + versionLable?.text = "Version ".localized + appVersion() + " (Build ".localized + appBuild() + ")" + } + + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + return 2 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + if section == 0 { + return listmain.count + } + return list.count + } + + @IBAction func proxyChainChanged(_ myswitch:UISwitch){ + if let msg = ProxyGroupSettings.share.updateProxyChain(myswitch.isOn){ + alertMessageAction(msg, complete: nil) + myswitch.isOn = false + return + } + + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + + if indexPath.section == 0 { + // let e = UserDefaults.standard.bool(forKey: "iCloudEnable") + let cell = tableView.dequeueReusableCell(withIdentifier: "commonSwitch", for: indexPath) as! SampleSwitchCell + + let txt = listmain[indexPath.row] + + cell.iconlabel?.font = UIFont.init(name: "Ionicons", size: 17)! + cell.iconlabel?.text = txt.to(index: 1) + + let new = txt.from(index: 1) + cell.label?.text = new.localized + //Configure the cell... + cell.updateUI() + + + if indexPath.row == 1 { + cell.sfSwitch?.isHidden = false + cell.sfSwitch?.isOn = ProxyGroupSettings.share.wwdcStyle + cell.sfSwitch?.addTarget(self, action: #selector( HelpTableViewController.iTheme(_:)), for: .valueChanged) + }else if indexPath.row == 0 { + cell.sfSwitch?.isOn = UserDefaults.standard.bool(forKey: "iCloudEnable") + cell.sfSwitch?.addTarget(self, action: #selector( HelpTableViewController.iCloud(_:)), for: .valueChanged) + }else if indexPath.row == 100 { + cell.sfSwitch?.isOn = ProxyGroupSettings.share.proxyChain + cell.sfSwitch?.addTarget(self, action: #selector( HelpTableViewController.proxyChainChanged(_:)), for: .valueChanged) + }else { + cell.sfSwitch?.isHidden = true + } + return cell + + }else { + return configCell(indexPath: indexPath) + } + + + + + + } + @IBAction func iCloud(_ sender:UISwitch){ + if sender.isOn { + UserDefaults.standard.set(true, forKey: "iCloudEnable") + } + let app = UIApplication.shared.delegate as! AppDelegate + app.iCloudEnable = sender.isOn + if sender.isOn { + sync() + } + + + + } + @IBAction func iTheme(_ sender:UISwitch){ + + ProxyGroupSettings.share.updateStyle(sender.isOn) + + let app = UIApplication.shared.delegate as! AppDelegate + app.appAppearance(sender.isOn) + + + NotificationCenter.default.post(name: NSNotification.Name(rawValue: "themeChanged"), object: nil) + + } + func moverToiCloud(url:URL) throws{ + let u = applicationDocumentsDirectory + do { + let fs = try fm.contentsOfDirectory(atPath: (u.path)) + for fp in fs { + if fp.hasSuffix(configExt) { + + let dest = url.appendingPathComponent(fp) + let src = u.appendingPathComponent(fp) + + if FileManager.default.fileExists(atPath: dest.path) { + + }else { + try fm.copyItem(at: src, to: dest) + print("copy \(dest.path)") + } + + } + + } + let sp = groupContainerURL().appendingPathComponent(kProxyGroupFile) + let dp = url.appendingPathComponent("ProxyGroup.json") + if FileManager.default.fileExists(atPath: dp.path) { + try fm.removeItem(at: dp) + } + try fm.copyItem(at: sp, to: dp) + + }catch let e as NSError{ + throw e + + } + + + } + func sync() { + let app = UIApplication.shared.delegate as! AppDelegate + guard app.iCloudToken != nil else { + + alertMessageAction("iCloud Token invalid", complete: nil) + return + } + DispatchQueue.global().async(execute: { [weak self] in + guard let countainer = FileManager.default.url(forUbiquityContainerIdentifier: nil) else { + DispatchQueue.main.async(execute: { + self?.alertMessageAction("Error Enable iCloud sysnc") + }) + return + } + print("countainer:url \(String(describing: countainer))") + + let documentsDirectory = countainer.appendingPathComponent("Documents"); + if !FileManager.default.fileExists(atPath: documentsDirectory.path){ + try! FileManager.default.createDirectory(atPath: documentsDirectory.path, withIntermediateDirectories: false, attributes: nil) + } + do { + try self!.moverToiCloud(url: documentsDirectory) + }catch let e { + DispatchQueue.main.async(execute: { + self?.alertMessageAction("icloud sync:\(e.localizedDescription)") + }) + + } + + + }) + } + func configCell(indexPath:IndexPath) -> UITableViewCell { + print("help configCell") + let cell = tableView.dequeueReusableCell(withIdentifier: "common", for: indexPath as IndexPath) + let c = cell as! SampleCell + let txt = list[indexPath.row] + + + c.iconlabel?.font = UIFont.init(name: "Ionicons", size: 17)! + c.iconlabel?.text = txt.to(index: 1) + c.label?.text = txt.from(index: 1).localized + + c.updateUI() + + + return cell + + } + + + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + +// if indexPath.section == 0 { +// return nil +// } + return indexPath + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat{ + return 48 + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: true) + let cell = tableView.cellForRow(at: indexPath) + if indexPath.section == 0 { + if indexPath.row == 3 { + + self.performSegue(withIdentifier: "showAdavnce", sender: cell) + }else if indexPath.row == 4 { + self.alertMessageAction("Do you want to clean Proxy Cache?", complete: { + ProxyGroupSettings.share.cleanDeleteProxy() + }) + } + }else { + switch indexPath.row{ + + case 0: + self.performSegue(withIdentifier: "showURL", sender: cell) + case 1: + self.performSegue(withIdentifier: "showURL", sender: cell) + case 2: + let u = tURL() + self.openURL(u) + + //self.performSegue(withIdentifier:"showAcknowledge", sender: cell) + case 3: + //self.performSegue(withIdentifier:"showAcknowledge", sender: cell) + if #available(iOS 10.3, *) { + SKStoreReviewController.requestReview() + } else { + + self.openURL(URL.init(string: "itms-apps://itunes.apple.com/cn/app/a.big.t/id1051326718?l=en&mt=8")!) + } + + case 4: + self.performSegue(withIdentifier: "showAcknowledge", sender: cell) + default: + //self.performSegue(withIdentifier: "showProeDition", sender: cell) + break + } + } + + } + func openURL(_ url:URL) { + UIApplication.shared.open(url, options: [:], completionHandler: { fin in + if fin { + print("open finished") + } + }) + } + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + guard let indexpath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + if segue.identifier == "showURL"{ + guard let destController = segue.destination as? SFWebViewController else{return} + if indexpath.row == 0 { + let path = Bundle.main.path(forResource: "surf.conf", ofType: nil) + destController.url = URL.init(fileURLWithPath: path!) + destController.headerInfo = "Config Sample View" + + + }else if indexpath.row == 1 { + + destController.url = URL.init(string: "https://gist.githubusercontent.com/networkextension/069590ba0e95e2fc322f8d10c4212731/raw/d1e34fecb2caaa8704b9aeb789735ad869871415/surf.conf") + destController.headerInfo = "Config Manual Chinese Edition" + }else { + let path = Bundle.main.path(forResource: "ReleaseNote.txt", ofType: nil) + destController.url = URL.init(string: path!) + destController.headerInfo = "Release Note" + } + + }else if segue.identifier == "showProeDition"{ + + }else if segue.identifier == "showAcknowledge"{ + + }else if segue.identifier == "showReleaseNote"{ + + }else if segue.identifier == "showAdavnce"{ + } + } + + +} diff --git a/Surf/HistoryViewController.swift b/Surf/HistoryViewController.swift new file mode 100644 index 0000000..e7ec13a --- /dev/null +++ b/Surf/HistoryViewController.swift @@ -0,0 +1,178 @@ +// +// HistoryViewController.swift +// Surf +// +// Created by 孔祥波 on 21/03/2017. +// Copyright © 2017 abigt. All rights reserved. +// + +import UIKit +import MessageUI +import SFSocket +import XProxy +import XRuler +class HistoryViewController: SFTableViewController,MFMailComposeViewControllerDelegate { + + var resultsFin:[SFRequestInfo] = [] + var dbURL:URL? + var session:String = "" + // MARK: MFMailComposeViewControllerDelegate Method + func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { + controller.dismiss(animated: true, completion: nil) + print("sendmail result \(result)") + } + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Requests".localized + + requests() + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + //let item = UIBarButtonItem.init(image: UIImage.init(named: "760-refresh-3-toolbar"), style: .plain, target: self, action: #selector(RecenetReqViewController.refreshAction(_:))) + + + //self.navigationItem.setRightBarButtonItems([item], animated: false) + let item = UIBarButtonItem.init(image: UIImage(named: "702-share-toolbar"), style: .plain, target: self, action: #selector(HistoryViewController.newShare(_:))) + //item.tintColor = UIColor.blueColor() + + self.navigationItem.rightBarButtonItem = item + } + func configuredMailComposeViewController() -> MFMailComposeViewController { + let mailComposerVC = MFMailComposeViewController() + mailComposerVC.mailComposeDelegate = self // Extremely important to set the --mailComposeDelegate-- property, NOT the --delegate-- property + + mailComposerVC.setToRecipients([supportEmail]) + mailComposerVC.setSubject("Session log file") + let data = try! Data.init(contentsOf: self.dbURL!, options: .alwaysMapped) + let path = self.dbURL!.path + + var appEnv:String = "Surfing env:\n " + let appinfo = appInfo() + for (k,v) in appinfo { + appEnv += k + " " + v + "\n" + } + appEnv += "请输入其他说明" + mailComposerVC.setMessageBody(appEnv, isHTML: false) + let fn = path.components(separatedBy: "/").last + mailComposerVC.addAttachmentData(data, mimeType: "text/plain", fileName: fn!) + return mailComposerVC + } + func showSendMailErrorAlert() { + //UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + let alert = UIAlertController.init(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", preferredStyle: .alert) + let action = UIAlertAction.init(title: "OK", style: .default) { (action:UIAlertAction) -> Void in + + } + alert.addAction(action) + self.present(alert, animated: true) { () -> Void in + + } + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if !verifyReceipt(.Analyze) { + changeToBuyPage() + return + } + } + @objc func newShare(_ sender:AnyObject){ + shareAirDropURL(self.dbURL!, name: self.session+"_db.zip") + } + + func requests() { + //resultsFin.removeAll() + if !session.isEmpty { + dbURL = RequestHelper.shared.openForApp(session) + dbURL = dbURL?.appendingPathComponent("db.zip") + } + resultsFin = RequestHelper.shared.fetchAll() + tableView.reloadData() + } + func test() { + let path = Bundle.main.path(forResource: "1.txt", ofType: nil) + if let _ = NSData.init(contentsOfFile: path!) { + + } + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + override func numberOfSections(in tableView: UITableView) -> Int { + + + + return 1 + } + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + return "HISTORY REQUESTS" + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return resultsFin.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "recent", for: indexPath) + cell.updateStandUI() + + // Configure the cell... + + var request:SFRequestInfo? + + + request = resultsFin[indexPath.row] + + if let request = request{ + cell.detailTextLabel?.textColor = UIColor.lightGray + + cell.textLabel?.text = request.url //+ " " + String(request.reqID) + " " + String(request.subID) + + cell.detailTextLabel?.attributedText = request.detailString() + }else { + cell.textLabel?.text = "Session Not Start".localized + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected { + cell.textLabel?.text = "Session Running".localized + } + } + + cell.detailTextLabel?.text = "" + } + + + return cell + + } + + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + if segue.identifier == "requestDetail" { + guard let detail = segue.destination as? RequestDetailViewController else{return} + guard let indexPath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + var request:SFRequestInfo + + request = resultsFin[indexPath.row] + if request.url.isEmpty { + alertMessageAction("Request url empty", complete: nil) + }else { + detail.request = request + } + + } + + } + +} diff --git a/Surf/HostEditTableViewController.swift b/Surf/HostEditTableViewController.swift new file mode 100644 index 0000000..3722bec --- /dev/null +++ b/Surf/HostEditTableViewController.swift @@ -0,0 +1,143 @@ +// +// HostEditTableViewController.swift +// Surf +// +// Created by 孔祥波 on 16/5/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +@objc protocol HostEditDelegate: class { + func hostDidChange(controller: HostEditTableViewController,new:Bool) + //func cancel(controller: HostEditTableViewController) + +} + + class HostEditTableViewController: SFTableViewController { + + var record:DNSRecord = DNSRecord(name: "", ips: "") + var new:Bool = false + weak var delegate:HostEditDelegate? + override func viewDidLoad() { + super.viewDidLoad() + + let edit = UIBarButtonItem.init(barButtonSystemItem: .done, target: self, action: #selector(HostEditTableViewController.doneAction(_:))) + navigationItem.rightBarButtonItem = edit + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + @objc func doneAction(_ anyObject:AnyObject) { + if let d = delegate { + var indexPath = IndexPath.init(row: 0, section: 0) + var cell = tableView.cellForRow(at: indexPath) as! TextFieldCell + record.name = cell.textField.text! + + indexPath = IndexPath.init(row: 0, section: 1) + cell = tableView.cellForRow(at: indexPath) as! TextFieldCell + record.ips += cell.textField.text! + + d.hostDidChange(controller: self, new: new) + } + _ = navigationController?.popViewController(animated: true) + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 1 + } + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return "Domain Name" + } + return "IP address" + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "hostCell", for: indexPath) as! TextFieldCell + + // Configure the cell... + cell.wwdcStyle() + if indexPath.section == 0 { + if !record.name.isEmpty{ + cell.textField.text = record.name + } + cell.textField.placeholder = "Domain Name" + + }else { + if let t = record.ip(){ + cell.textField.text = t + } + cell.textField.placeholder = "1.2.3.4" + + } + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: true) + let cell = tableView.cellForRow(at: indexPath) as! TextFieldCell + cell.textField.becomeFirstResponder() + } + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/HostsTableViewController.swift b/Surf/HostsTableViewController.swift new file mode 100644 index 0000000..f945a55 --- /dev/null +++ b/Surf/HostsTableViewController.swift @@ -0,0 +1,160 @@ +// +// HostsTableViewController.swift +// +// +// Created by 孔祥波 on 16/5/14. +// +// + +import UIKit +import SFSocket +import XRuler +class HostsTableViewController: SFTableViewController ,HostEditDelegate{ + + var config:SFConfig! + override func viewDidLoad() { + super.viewDidLoad() + self.title = "DNS Map" + //self.tableView.allowsSelectionDuringEditing = true + let edit = UIBarButtonItem.init(barButtonSystemItem: .add, target: self, action: #selector(HostsTableViewController.addEditHost(_:))) + navigationItem.rightBarButtonItem = edit + tableView.delegate = self + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + @objc func addEditHost(_ object:AnyObject){ + self.performSegue(withIdentifier:"AddEditHost", sender: nil) + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return config.hosts.count + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String + { + return "Function like /etc/hosts" + } + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + + return true + } + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){ + + if editingStyle == .delete { + // Delete the row from the data source + + + + if indexPath.row < config.hosts.count{ + config.hosts.remove(at: indexPath.row) + tableView.deleteRows(at: [indexPath as IndexPath], with: .fade) + }else { + tableView.reloadData() + } + + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "hosts", for: indexPath as IndexPath) + + // Configure the cell... + let x :DNSRecord = config.hosts[indexPath.row] + cell.textLabel?.text = x.name + if let ip = x.ip() { + cell.detailTextLabel?.text = ip + } + + return cell + } + + + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + if segue.identifier == "AddEditHost"{ + guard let vc = segue.destination as? HostEditTableViewController else{return} + //barCodeController.useCamera = self.useCamera + if let s = sender{ + guard let indexPath = self.tableView.indexPath(for: s as! UITableViewCell) else {return } + vc.record = config.hosts[indexPath.row] + vc.title = "Record" + }else { + vc.title = "New Record" + vc.new = true + } + + + vc.delegate = self + + + + } + + } + + func hostDidChange(controller: HostEditTableViewController,new:Bool){ + if new{ + config.hosts.insert(controller.record, at: 0) + } + tableView.reloadData() + } + + +} diff --git a/Surf/ImageViewController.swift b/Surf/ImageViewController.swift new file mode 100644 index 0000000..acfb896 --- /dev/null +++ b/Surf/ImageViewController.swift @@ -0,0 +1,81 @@ +// +// ImageViewController.swift +// Surf +// +// Created by 孔祥波 on 10/17/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +class ImageViewController: UIViewController { + @IBOutlet weak var imageView:UIImageView! + // + var image:UIImage! + override func viewDidLoad() { + super.viewDidLoad() + imageView.image = image + let rect = CGRect.init(x: 0, y: 0, width: 30, height: 30) + let btn = UIButton.init(frame: rect) + btn.titleLabel?.font = UIFont.init(name: "Ionicons", size: 20) + btn.setTitle("\u{f3ac}", for: .normal) + if ProxyGroupSettings.share.wwdcStyle { + btn.titleLabel?.textColor = UIColor.white + }else { + btn.titleLabel?.textColor = UIColor.black + } + + btn.addTarget(self, action: #selector(ImageViewController.saveConfigToImage(_:)), for: .touchUpInside) + self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(customView: btn) + //UIBarButtonItem.init(barButtonSystemItem: .save, target: self, action: #selector(ImageViewController.saveConfigToImage(_:))) + + // Do any additional setup after loading the view. + } + @objc func saveConfigToImage(_ sender: AnyObject){ + // + if let png = UIImagePNGRepresentation(image){ + let url = URL.init(fileURLWithPath: NSTemporaryDirectory()+"BarCode.png") + try! png.write(to: url) + let vc = UIActivityViewController(activityItems: [url], applicationActivities: []) + vc.completionWithItemsHandler = { (type,complete,items,error) in + do { + try FileManager.default.removeItem(at: url) + }catch let e { + print(e.localizedDescription) + } + + } + vc.popoverPresentationController?.sourceView = self.view + present(vc, animated: true) + + } + //UIImageWriteToSavedPhotosAlbum(image, self, #selector(ImageViewController.imageCallBack(_:didFinishSavingWithError:contextInfo:)), nil) + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + func imageCallBack(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafeRawPointer) { + if error == nil { + let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert) + ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + present(ac, animated: true, completion: nil) + } else { + let ac = UIAlertController(title: "Save error", message: error?.localizedDescription, preferredStyle: .alert) + ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + present(ac, animated: true, completion: nil) + } + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/Info.plist b/Surf/Info.plist new file mode 100644 index 0000000..4fa98b2 --- /dev/null +++ b/Surf/Info.plist @@ -0,0 +1,155 @@ + + + + + CFBundleDevelopmentRegion + zh_CN + CFBundleDisplayName + A.BIG.T + CFBundleDocumentTypes + + + CFBundleTypeIconFiles + + CFBundleTypeName + A.BIG.T Config + LSItemContentTypes + + run.abigt.conf + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + A.BIG.T + CFBundlePackageType + APPL + CFBundleShortVersionString + 4.0 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + abigt + + + + CFBundleVersion + 805 + Fabric + + APIKey + + Kits + + + KitInfo + + KitName + Crashlytics + + + + ITSAppUsesNonExemptEncryption + + LSApplicationQueriesSchemes + + twitter + tweetbot + + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSCameraUsageDescription + A.BIG.T use Camera Scan QrCode + NSPhotoLibraryUsageDescription + A.BIG.T should load QrCode Image from your PhotoLibrary + NSUbiquitousContainerIsDocumentScopePublic + + NSUbiquitousContainers + + iCloud.com.abigt.Surf + + NSUbiquitousContainerIsDocumentScopePublic + + NSUbiquitousContainerName + Surf + NSUbiquitousContainerSupportedFolderLevels + Any + + + UIAppFonts + + ionicons.ttf + + UIFileSharingEnabled + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarStyle + UIStatusBarStyleLightContent + UIStatusBarTintParameters + + UINavigationBar + + Style + UIBarStyleDefault + Translucent + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UTExportedTypeDeclarations + + + UTTypeConformsTo + + public.utf8-plain-text + + UTTypeDescription + A.BIG.T Config + UTTypeIdentifier + run.abigt.conf + UTTypeTagSpecification + + public.filename-extension + conf + public.mime-type + text/plain + + + + + diff --git a/Surf/KcpTableViewController.swift b/Surf/KcpTableViewController.swift new file mode 100644 index 0000000..0e1e0e8 --- /dev/null +++ b/Surf/KcpTableViewController.swift @@ -0,0 +1,164 @@ +// +// KcpTableViewController.swift +// Surf +// +// Created by 孔祥波 on 16/05/2017. +// Copyright © 2017 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +import Xcon +let kcpName:[String] = ["Crypto","Key","Compress","mode","datashard","parityshard"] +class KcpTableViewController: SFTableViewController { + + var cryptoField:UITextField! + var keyField:UITextField! + var modeField:UITextField! + var datashardField:UITextField! + var parityshardField:UITextField! + var kcpinfo:SFKCPTunConfig! + override func viewDidLoad() { + super.viewDidLoad() + self.title = "KCPTun Settings" + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action:#selector(KcpTableViewController.saveConfig(_:))) + } + + @objc func saveConfig(_ sender:Any){ + + kcpinfo.crypt = self.cryptoField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + kcpinfo.key = self.keyField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + kcpinfo.mode = self.modeField!.text!.trimmingCharacters(in: .whitespacesAndNewlines) + if let x = Int(self.datashardField!.text!.trimmingCharacters(in: .whitespacesAndNewlines)){ + kcpinfo.datashard = x + } + if let y = Int(self.parityshardField!.text!.trimmingCharacters(in: .whitespacesAndNewlines)){ + kcpinfo.parityshard = y + } + self.navigationController?.popViewController(animated: true) + + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MA∫RK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 6 + } + + @objc func comp(_ sender:UISwitch){ + sender.isOn = false + self.showAlert(alertWithTitle("Alert", message: "Compress not Support Currently")) + return + kcpinfo.noComp = sender.isOn + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.row == 2 { + let cell = tableView.dequeueReusableCell(withIdentifier: "Advance", for: indexPath as IndexPath) as! AdvancedCell + cell.wwdcStyle() + + cell.label.text = kcpName[indexPath.row] + cell.s.isOn = kcpinfo.noComp + cell.s.addTarget(self, action: #selector(KcpTableViewController.comp(_:)), for: .valueChanged) + return cell + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "textfield-cell", for: indexPath) as! TextFieldCell + + cell.cellLabel?.text = kcpName[indexPath.row] + switch indexPath.row { + case 0: + cell.textField.text = kcpinfo.crypt + self.cryptoField = cell.textField + case 1: + cell.textField.text = kcpinfo.key + self.keyField = cell.textField + case 3: + cell.textField.text = kcpinfo.mode + self.modeField = cell.textField + case 4: + + cell.textField.text = String(kcpinfo.datashard) + self.datashardField = cell.textField + case 5: + cell.textField.text = String(kcpinfo.parityshard) + self.parityshardField = cell.textField + default: + break + } + // Configure the cell... + cell.wwdcStyle() + return cell + } + + } + + public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return "Crypto only support none, aes/aes-128/aes-192 support soon,Compress currently not suport" + } + public override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { + + return "KCPTun client base https://github.com/xtaci/kcptun; A Secure Tunnel Based On KCP with N:M Multiplexing" + } + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/LogFileViewController.swift b/Surf/LogFileViewController.swift new file mode 100644 index 0000000..a4db1d8 --- /dev/null +++ b/Surf/LogFileViewController.swift @@ -0,0 +1,133 @@ +// +// LogFileViewController.swift +// Surf +// +// Created by abigt on 15/12/7. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit +import MessageUI +import DarwinCore +import SFSocket +class LogFileViewController: SFViewController,MFMailComposeViewControllerDelegate { + + var filePath:URL? + var showRouter:Bool = false + var queue = DispatchQueue(label:"com.abigt.route") + @IBOutlet weak var textView:UITextView? + + override func viewDidLoad() { + super.viewDidLoad() + //self.test() + //fixed a crash bug + + textView?.text = "loading ..." +// let btn = UIButton.init(type: .Custom) +// btn.addTarget(self, action: "shareLog:", forControlEvents: .TouchUpInside) +// btn.setImage(UIImage(named: "702-share-toolbar"), forState: .Normal) +// btn.setImage(UIImage(named: "702-share-toolbar-selected"), forState: .Highlighted) +// btn.sizeToFit() + if !showRouter { + let item = UIBarButtonItem.init(image: UIImage(named: "702-share-toolbar"), style: .plain, target: self, action: #selector(LogFileViewController.newShare(_:))) + //item.tintColor = UIColor.blueColor() + + self.navigationItem.rightBarButtonItem = item + }else { + self.title = "Route Table" + let fontSize = fontsize() + self.textView?.font = UIFont.init(name: "Courier", size: fontSize) + } + + // Do any additional setup after loading the view. + edgesForExtendedLayout = .all //| .Bottom + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if showRouter { + + let txt = Route.currntRouterInet4(true, defaultRouter: false) + self.textView?.text = txt + + + + }else { + if let u = filePath { + if u.path.components(separatedBy: ".").last! != "log"{ + textView?.text = "Can't Open" + return + } + do { + let content = try String.init(contentsOf: u)//File: filePath!, encoding: NSUTF8StringEncoding) + textView?.text = content as String + } catch let e { + self.alertMessageAction("Error:\(e.localizedDescription)", complete: nil) + } + + }else { + self.alertMessageAction("Can't Find File Path", complete: nil) + } + } + + } + func configuredMailComposeViewController() -> MFMailComposeViewController { + let mailComposerVC = MFMailComposeViewController() + mailComposerVC.mailComposeDelegate = self // Extremely important to set the --mailComposeDelegate-- property, NOT the --delegate-- property + + mailComposerVC.setToRecipients([supportEmail]) + mailComposerVC.setSubject("Surf running log file") + let data = try! Data.init(contentsOf: filePath!) + let path = filePath!.path + + var appEnv:String = "Surfing env:\n " + let appinfo = appInfo() + for (k,v) in appinfo { + appEnv += k + " " + v + "\n" + } + appEnv += "请输入其他说明,例如:FaceBook 不能打开等" + mailComposerVC.setMessageBody(appEnv, isHTML: false) + let fn = path.components(separatedBy: "/").last + mailComposerVC.addAttachmentData(data, mimeType: "text/plain", fileName: fn!) + return mailComposerVC + } + func showSendMailErrorAlert() { + //UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + let alert = UIAlertController.init(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", preferredStyle: .alert) + let action = UIAlertAction.init(title: "OK", style: .default) { (action:UIAlertAction) -> Void in + + } + alert.addAction(action) + self.present(alert, animated: true) { () -> Void in + + } + } + + + @objc func newShare(_ sender:AnyObject){ + + shareAirDropURL(self.filePath!,name:"abigt.log") + + } + + // MARK: MFMailComposeViewControllerDelegate Method + func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { + controller.dismiss(animated: true, completion: nil) + print("sendmail result \(result)") + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/LogListTableViewController.swift b/Surf/LogListTableViewController.swift new file mode 100644 index 0000000..780b0e8 --- /dev/null +++ b/Surf/LogListTableViewController.swift @@ -0,0 +1,582 @@ +// +// LogListTableViewController.swift +// Surf +// +// Created by abigt on 15/12/7. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import SwiftyJSON +import XRuler +struct SFFILE { + var name:String + var date:NSDate + var size:Int64 + init(n:String,d:NSDate,size:Int64){ + name = n + date = d + self.size = size + } + var desc:String{ + //print(size) + if size >= 1024 && size < 1024*1024 { + return "size: \(size/1024) KB" + }else if size >= 1024*1024 { + return "size: \(size/(1024*1024)) MB" + }else { + return "size: \(size) byte" + } + + } +} +open class SFVPNStatisticsApp { + //public static let shared = SFVPNStatistics() + public var startDate = Date.init(timeIntervalSince1970: 0) + public var sessionStartTime = Date() + public var reportTime = Date.init(timeIntervalSince1970: 0) + public var startTimes = 0 + public var show:Bool = false + public var totalTraffice:SFTraffic = SFTraffic() + public var currentTraffice:SFTraffic = SFTraffic() + public var lastTraffice:SFTraffic = SFTraffic() + public var maxTraffice:SFTraffic = SFTraffic() + + public var wifiTraffice:SFTraffic = SFTraffic() + public var cellTraffice:SFTraffic = SFTraffic() + + public var directTraffice:SFTraffic = SFTraffic() + public var proxyTraffice:SFTraffic = SFTraffic() + public var memoryUsed:UInt64 = 0 + public var finishedCount:Int = 0 + public var workingCount:Int = 0 + public var runing:String { + get { + //let now = Date() + let second = Int(reportTime.timeIntervalSince(sessionStartTime)) + return secondToString(second: second) + } + } + public func updateMax() { + if lastTraffice.tx > maxTraffice.tx{ + maxTraffice.tx = lastTraffice.tx + } + if lastTraffice.rx > maxTraffice.rx { + maxTraffice.rx = lastTraffice.rx + } + } + public func secondToString(second:Int) ->String { + + let sec = second % 60 + let min = second % (60*60) / 60 + let hour = second / (60*60) + + return String.init(format: "%02d:%02d:%02d", hour,min,sec) + + + } + public func map(j:JSON) { + startDate = Date.init(timeIntervalSince1970: j["start"].doubleValue) as Date + sessionStartTime = Date.init(timeIntervalSince1970: j["sessionStartTime"].doubleValue) + reportTime = NSDate.init(timeIntervalSince1970: j["report_date"].doubleValue) as Date + totalTraffice.mapObject(j: j["total"]) + lastTraffice.mapObject(j: j["last"]) + maxTraffice.mapObject(j: j["max"]) + + cellTraffice.mapObject(j:j["cell"]) + wifiTraffice.mapObject(j: j["wifi"]) + directTraffice.mapObject(j: j["direct"]) + proxyTraffice.mapObject(j: j["proxy"]) +// if let c = j["memory"].uInt64 { +// memoryUsed = c +// } +// if let tcp = j["finishedCount"].int { +// finishedCount = tcp +// } +// if let tcp = j["workingCount"].int { +// workingCount = tcp +// } + } + func resport() ->Data{ + //reportTime = Date() + //memoryUsed = reportMemoryUsed()//reportCurrentMemory() + + var status:[String:AnyObject] = [:] + status["start"] = NSNumber.init(value: startDate.timeIntervalSince1970) + status["sessionStartTime"] = NSNumber.init(value: sessionStartTime.timeIntervalSince1970) + status["report_date"] = NSNumber.init(value: reportTime.timeIntervalSince1970) + //status["runing"] = NSNumber.init(double:runing) + status["total"] = totalTraffice.resp() as AnyObject? + status["last"] = lastTraffice.resp() as AnyObject? + status["max"] = maxTraffice.resp() as AnyObject? + status["memory"] = NSNumber.init(value: memoryUsed) //memoryUsed) + + //let count = SFTCPConnectionManager.manager.connections.count + status["finishedCount"] = NSNumber.init(value: finishedCount) // + //status["workingCount"] = NSNumber.init(value: count) // + + status["cell"] = cellTraffice.resp() as AnyObject? + status["wifi"] = wifiTraffice.resp() as AnyObject? + status["direct"] = directTraffice.resp() as AnyObject? + status["proxy"] = proxyTraffice.resp() as AnyObject? + + let j = JSON(status) + + + + + //print("recentRequestData \(j)") + var data:Data + do { + try data = j.rawData() + }catch let error { + //AxLogger.log("ruleResultData error \(error.localizedDescription)") + //let x = error.localizedDescription + //let err = "report error" + data = error.localizedDescription.data(using: .utf8)!// NSData() + } + return data + } + public func memoryString() ->String { + let f = Float(memoryUsed) + if memoryUsed < 1024 { + return "\(memoryUsed) Bytes" + }else if memoryUsed >= 1024 && memoryUsed < 1024*1024 { + + return String(format: "%.2f KB", f/1024.0) + } + return String(format: "%.2f MB", f/1024.0/1024.0) + + } +} +class LogListTableViewController: SFTableViewController { + + var filePath:String = "" + var fileList:[SFFILE] = [] + var showSession:Bool = false + var reportInfo:SFVPNStatisticsApp? + override func viewDidLoad() { + super.viewDidLoad() + if filePath.isEmpty { + self.title = "Sessions" + }else { + self.title = "Session Detail" + showSession = true + } + + findFiles() + navigationItem.rightBarButtonItem = editButtonItem + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + } + @IBAction func deleteAll(_ sender:AnyObject) { + + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + for file in fileList.dropFirst() { + let url = groupContainerURL().appendingPathComponent("Log/"+file.name) + do { + try fm.removeItem(at: url) + }catch let error as NSError { + alertMessageAction("delete \(url.path) failure: \(error.description)",complete: nil) + return + } + + } + }else { + for file in fileList { + let url = groupContainerURL().appendingPathComponent("Log/"+file.name) + do { + try fm.removeItem(at: url) + }catch let error as NSError { + alertMessageAction("delete \(url.path) failure: \(error.description)",complete: nil) + return + } + + } + } + + findFiles() + } + func findFiles(){ + let q = DispatchQueue(label:"com.abigt.sortlog") + q.async(execute: { [weak self] () -> Void in + + self!.fileList.removeAll() + //let urlContain = FileManager.default.containerURLForSecurityApplicationGroupIdentifier("group.com.abigt.Surf") + let url = groupContainerURL().appendingPathComponent("Log/" + self!.filePath) + + let dir = url.path //NSHomeDirectory().NS.stringByAppendingPathComponent("Documents/applog") + if FileManager.default.fileExists(atPath:dir) { + let files = try! FileManager.default.contentsOfDirectory(atPath: dir) + var tmpArray:[SFFILE] = [] + for file in files { + let url = url.appendingPathComponent(file) + let att = try! fm.attributesOfItem(atPath: url.path) + let d = att[ FileAttributeKey.init("NSFileCreationDate")] as! NSDate + let size = att[FileAttributeKey.init("NSFileSize")]! as! NSNumber + let fn = SFFILE.init(n: file, d: d,size:size.int64Value) + + tmpArray.append(fn) + + } + tmpArray.sort(by: { $0.date.compare($1.date as Date) == ComparisonResult.orderedDescending }) + DispatchQueue.main.async(execute: { + if let strongSelf = self { + strongSelf.fileList.append(contentsOf: tmpArray) + if strongSelf.showSession { + strongSelf.loadReport() + }else { + strongSelf.tableView.reloadData() + } + + } + }) + + + + + }else { + + } + }) + + + //fileList = try! FileManager.default.contentsOfDirectoryAtURL(url, includingPropertiesForKeys keys: [String]?, options mask: NSDirectoryEnumerationOptions) throws -> [NSURL] + + } + func loadReport(){ + let url = groupContainerURL().appendingPathComponent("Log/" + self.filePath + "/db.zip") + let urlJson = groupContainerURL().appendingPathComponent("Log/" + self.filePath + "/session.json") + if FileManager.default.fileExists(atPath: urlJson.path){ + reportInfo = SFVPNStatisticsApp()//.init(name: self.filePath) + do { + let data = try Data.init(contentsOf: urlJson) + let obj = try! JSON.init(data: data) + reportInfo!.map(j: obj) + tableView.reloadData() + return + }catch let e { + alertMessageAction("\(e.localizedDescription)", complete: nil) + } + + } + if FileManager.default.fileExists(atPath: url.path){ + let _ = RequestHelper.shared.openForApp(self.filePath) + let resultsFin = RequestHelper.shared.query() + reportInfo = SFVPNStatisticsApp()//.init(name: self.filePath) + for req in resultsFin { + reportInfo?.totalTraffice.addRx(x:Int(req.traffice.rx) ) + reportInfo?.totalTraffice.addTx(x:Int(req.traffice.tx) ) + if req.interfaceCell == 1 { + reportInfo?.cellTraffice.addRx(x: Int(req.traffice.rx)) + reportInfo?.cellTraffice.addTx(x: Int(req.traffice.tx)) + }else { + reportInfo?.wifiTraffice.addRx(x: Int(req.traffice.rx)) + reportInfo?.wifiTraffice.addTx(x: Int(req.traffice.tx)) + } + + if req.rule.policy == .Direct { + reportInfo?.directTraffice.addRx(x: Int(req.traffice.rx)) + reportInfo?.directTraffice.addTx(x: Int(req.traffice.tx)) + }else { + reportInfo?.proxyTraffice.addRx(x: Int(req.traffice.rx)) + reportInfo?.proxyTraffice.addTx(x: Int(req.traffice.tx)) + } + if req.sTime.compare(reportInfo!.sessionStartTime) == .orderedAscending{ + reportInfo!.sessionStartTime = req.sTime + } + if req.eTime.compare(reportInfo!.reportTime) == .orderedDescending { + reportInfo!.reportTime = req.eTime + } + } + + let data = reportInfo!.resport() + let url = groupContainerURL().appendingPathComponent("Log/" + self.filePath + "/session.json") + do { + try data.write(to:url ) + } catch let e { + alertMessageAction("\(e.localizedDescription)", complete: nil) + } + } + tableView.reloadData() + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if filePath.isEmpty { + let dir = fileList[indexPath.row] + print(dir) + let vc = self.storyboard?.instantiateViewController(withIdentifier: "filelist") as! LogListTableViewController + vc.filePath = dir.name + self.navigationController?.pushViewController(vc, animated: true) + + }else { + let cell = tableView.cellForRow(at: indexPath) + if indexPath.row > fileList.count { + self.performSegue(withIdentifier: "showFile", sender: cell) + }else { + let f = fileList[indexPath.row] + if f.name == "db.zip" { + self.performSegue(withIdentifier: "showDB", sender: cell) + }else { + self.performSegue(withIdentifier: "showFile", sender: cell) + } + + } + + } + + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + if filePath.isEmpty { + if fileList.count == 0 { + return 1 + } + + return 2 + }else { + return 2 + } + + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + if section == 0 { + if fileList.count == 0 { + return 1 + } + return fileList.count + }else { + if showSession { + if let _ = reportInfo{ + return 6 + }else { + return 0 + } + + }else { + return 1 + } + + } + + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + + if indexPath.section == 0 { + let cell = tableView.dequeueReusableCell(withIdentifier: "logidentifier", for: indexPath as IndexPath) + if fileList.count == 0 { + cell.textLabel?.text = "No log files" + cell.detailTextLabel?.text = "" + }else { + // Configure the cell... + //bug + if indexPath.row < fileList.count { + let f = fileList[indexPath.row] + cell.textLabel?.text = f.name + if !filePath.isEmpty { + cell.detailTextLabel?.text = f.desc + }else { + cell.detailTextLabel?.text = "" + } + + } + + } + cell.updateStandUI() + return cell + }else { + + if showSession { + let cell = tableView.dequeueReusableCell(withIdentifier: "StatusCell", for: indexPath as IndexPath) as! StatusCell + + guard let r = self.reportInfo else { + return cell + } + configCell(cell: cell,indexPath: indexPath, report: r) + return cell + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "deleteAll", for: indexPath as IndexPath) + + return cell + } + } + + } + func configCell(cell:StatusCell, indexPath:IndexPath,report:SFVPNStatisticsApp){ + let flag = true + + let f = UIFont.init(name: "Ionicons", size: 20)! + cell.downLabel.text = "\u{f35d}" + cell.downLabel.font = f + cell.upLabel.text = "\u{f366}" + cell.upLabel.font = f + + cell.updateUI() + + switch indexPath.row { + + + case 0: + cell.catLabel.text = "\u{f3b3}" + cell.downInfoLabel.isHidden = true //report.memoryString() + cell.downLabel.isHidden = true + cell.upLabel.isHidden = true + cell.upInfoLabel.text = report.runing + return + + + + case 1: + cell.catLabel.text = "\u{f37c}" + //cell.textLabel?.text = "Total: \(report.totalTraffice.reportTraffic())" + cell.upInfoLabel.text = report.totalTraffice.toString(x: report.totalTraffice.tx,label: "",speed: false) + cell.downInfoLabel.text = report.totalTraffice.toString(x: report.totalTraffice.rx,label: "",speed: false) + case 2: + cell.upInfoLabel.text = report.directTraffice.toString(x: report.directTraffice.tx,label: "",speed: false) + cell.downInfoLabel.text = report.directTraffice.toString(x: report.directTraffice.rx,label: "",speed: false) + cell.catLabel.text = "\u{f394}"//cell.textLabel?.text = "DIRECT: \(report.directTraffice.reportTraffic())" + case 3: + //cell.textLabel?.text = "PROXY: \(report.proxyTraffice.reportTraffic())" + cell.catLabel.text = "\u{f4a8}" + cell.upInfoLabel.text = report.proxyTraffice.toString(x: report.proxyTraffice.tx,label: "",speed: false) + cell.downInfoLabel.text = report.proxyTraffice.toString(x: report.proxyTraffice.rx,label: "",speed: false) + case 4: + //cell.textLabel?.attributedText = report.wifi() + cell.upInfoLabel.text = report.wifiTraffice.toString(x: report.wifiTraffice.tx,label: "",speed: false) + cell.downInfoLabel.text = report.wifiTraffice.toString(x: report.wifiTraffice.rx,label: "",speed: false) + cell.catLabel.text = "\u{f25c}" + case 5: + //cell.textLabel?.text = "CELL: \(report.cellTraffice.reportTraffic())" + cell.upInfoLabel.text = report.cellTraffice.toString(x: report.cellTraffice.tx,label: "",speed: false) + cell.downInfoLabel.text = report.cellTraffice.toString(x: report.cellTraffice.rx,label: "",speed: false) + cell.catLabel.text = "\u{f274}" + + default: + break + } + /* + if flag { + + + //print("TCP Connection: \(report.connectionCount) memory:\(report.memoryUsed) ") + }else { + cell.textLabel?.text = "Session Not Start" + cell.catLabel.isHidden = true + cell.downLabel.isHidden = true + cell.downInfoLabel.isHidden = true + cell.upLabel.isHidden = true + cell.upInfoLabel.isHidden = true + }*/ + cell.downLabel.isHidden = false + cell.upLabel.isHidden = false + } + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + + if indexPath.section == 0 && fileList.count == 0 { + return nil + } + if indexPath.section == 1 { + return nil + } + return indexPath + + + } + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + + if indexPath.row == 0 { + guard let m = SFVPNManager.shared.manager else {return true} + if m.connection.status == .connected { + return false + }else { + if fileList.count == 0 { + return false + } + return true + } + + } + return true + } + override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { + + if indexPath.item < fileList.count { + return .delete + } + + return .delete + } + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + + if editingStyle == .delete{ + let f = fileList[indexPath.row] + let url = groupContainerURL().appendingPathComponent("Log/" + self.filePath + "/" + f.name) + //saveProxys() + do { + try fm.removeItem(at: url) + fileList.remove(at: indexPath.row) + } catch _ { + + } + + + tableView.reloadData() + } + + } + + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + if segue.identifier == "showFile"{ + + guard let addEditController = segue.destination as? LogFileViewController else{return} + let cell = sender as? UITableViewCell + guard let indexPath = tableView.indexPath(for: cell!) else {return } + + + let f = fileList[indexPath.row] + addEditController.navigationItem.title = f.name + + let url = groupContainerURL().appendingPathComponent("Log/" + self.filePath + "/" + f.name) + + addEditController.filePath = url + // addEditController.delegate = self + }else if segue.identifier == "showDB" { + guard let vc = segue.destination as? HistoryViewController else{return} + vc.session = self.filePath + } + } + + +} diff --git a/Surf/LoglevelTableViewController.swift b/Surf/LoglevelTableViewController.swift new file mode 100644 index 0000000..5c3041a --- /dev/null +++ b/Surf/LoglevelTableViewController.swift @@ -0,0 +1,56 @@ +// +// LoglevelTableViewController.swift +// Surf +// +// Created by abigt on 16/1/25. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +@objc protocol LoglevelDelegate:class { + func didSelectLogLevel(controller: LoglevelTableViewController)// file name + +} +let lableTexts = ["Error","Warning" ,"Info","Notify","Trace"] +class LoglevelTableViewController: SFTableViewController{ + var delegate:LoglevelDelegate? + //var general:XRuler.General! + var loglevel:String = "" + override func viewDidLoad() { + //Fixme +// if let g = general { +// loglevel = g.loglevel +// } + super.viewDidLoad() + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: true) + let cell = tableView.cellForRow(at: indexPath) as! ActionsCell + loglevel = cell.myLabel.text! +// if let g = general { +// //loglevel = g.loglevel +// if g.loglevel != loglevel { +// g.loglevel = loglevel +// delegate?.didSelectLogLevel(controller: self) +// } +// } + _ = self.navigationController?.popViewController(animated: true) + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 5 + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "action") as! ActionsCell + cell.myLabel.text = lableTexts[indexPath.row] + if ProxyGroupSettings.share.wwdcStyle { + cell.myLabel.textColor = UIColor.white + }else { + cell.myLabel.textColor = UIColor.black + } + return cell + } +} diff --git a/Surf/NetworkActivityIndicatorManager.swift b/Surf/NetworkActivityIndicatorManager.swift new file mode 100755 index 0000000..fc8140e --- /dev/null +++ b/Surf/NetworkActivityIndicatorManager.swift @@ -0,0 +1,51 @@ +// +// NetworkActivityIndicatorManager.swift +// SwiftyStoreKit +// +// Created by Andrea Bizzotto on 28/09/2015. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import UIKit + +class NetworkActivityIndicatorManager: NSObject { + + private static var loadingCount = 0 + + class func networkOperationStarted() { + + #if os(iOS) + if loadingCount == 0 { + UIApplication.shared.isNetworkActivityIndicatorVisible = true + } + loadingCount += 1 + #endif + } + + class func networkOperationFinished() { + #if os(iOS) + if loadingCount > 0 { + loadingCount -= 1 + } + if loadingCount == 0 { + UIApplication.shared.isNetworkActivityIndicatorVisible = false + } + #endif + } +} diff --git a/Surf/OndemandController.swift b/Surf/OndemandController.swift new file mode 100644 index 0000000..e59386e --- /dev/null +++ b/Surf/OndemandController.swift @@ -0,0 +1,320 @@ +// +// OndemandController.swift +// Surf +// +// Created by abigt on 16/2/22. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +let default_domains = ["twitter.com","twimg.com","t.co","google.com","ggpht.com","googleapis.com","instagram.com","cdninstgram","facebook.com","fb.com","fbcdn.net","tumblr.com","yahoo.com" +] + +class OndemandController: SFTableViewController,UITextFieldDelegate { + + var wifiEnable:Bool = true + //var onDemandEnable:Bool = false + var domains:[String] = [] + func wifiStatus() ->Bool{ + if let m = SFVPNManager.shared.manager { + if let rule = m.onDemandRules?.first{ + if rule.interfaceTypeMatch == .any { + wifiEnable = true + }else { + wifiEnable = false + } + return wifiEnable + //onDemandEnable = m.onDemandEnabled + } + } + return false + } + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Advance" + + +// let done = UIBarButtonItem.init(title: "Done", style: .Plain, target: self, action: #selector(OndemandController.doneAction(_:))) +// +// self.navigationItem.rightBarButtonItem = done + } + @IBAction func valueChangedWIFI(_ sender:UISwitch){ + self.wifiEnable = sender.isOn + doneAction(true) + } + @IBAction func valueChanged(_ sender:UISwitch){ + if let m = SFVPNManager.shared.manager { + if let _ = m.onDemandRules?.first{ +// if rule.interfaceTypeMatch == .Any { +// wifiEnable = true +// }else { +// wifiEnable = false +// } + m.isOnDemandEnabled = sender.isOn + } + }//= sender.on + doneAction(sender.isOn) +// SFVPNManager.shared.addOnDemandRule(domains,enable: onDemandEnable,wifiEnable:wifiEnable) {[weak self] (error) -> Void in +// if let e = error { +// self!.alertMessageAction("Error:\(e.description)",complete: nil) +// }else { +// self!.alertMessageAction("Success!",complete: nil) +// } +// } + } + func doneAction(_ enable:Bool){ + UserDefaults.standard.set(domains, forKey: onDemandKey) + UserDefaults.standard.synchronize() + SFVPNManager.shared.addOnDemandRule(domains,wifiEnable:wifiEnable,enable:enable) {[weak self] (error) -> Void in + if let e = error { + self!.alertMessageAction("\(e.localizedDescription)",complete: nil) + }else { +// self!.alertMessageAction("On demand Rule add Success!") { () -> Void in +// if let strongSelf = self,let nvc = strongSelf.navigationController { +// nvc.popViewController(animated:(true) +// } +// } + } + } + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + loadDomains() + } + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + if section == 0{ + return "MISC" + }else if section == 1{ + return "On Demand" + }else if section == 2{ + return "Add New domain" + }else { + + return "On Demand domains " + } + + } + func loadDomains(){ + //fm. + if let x = UserDefaults.standard.stringArray(forKey: onDemandKey) { + for xx in x { + var found = false + for i in domains { + if xx == i { + found = true + } + } + if !found{ + domains.append(xx) + } + + } + + }else { + if domains.isEmpty { + domains.append(contentsOf: default_domains) + } + + } + tableView.reloadData() + } + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + return 4 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + if section == 0 { + return 4 + }else if section == 1 { + return 3 + } else if section == 2 { + return 1 + } + return domains.count + } + func textFieldDidEndEditing(_ textField: UITextField) { + + addDomain(domain: textField.text!) + doneAction(true) + textField.text = "" + //valueChanged?(textField) + } + func addDomain(domain:String){ + domains.insert(domain, at: 0) + let indexPath = IndexPath(row: 0, section: 3) + tableView.insertRows(at: [indexPath], with: .automatic) + } + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + //valueChanged?(textField) + return true + } + @objc func valueChangedSleep(_ send:UISwitch) { + if let mangager = SFVPNManager.shared.manager { + if let config = mangager.protocolConfiguration { + config.disconnectOnSleep = send.isOn + mangager.saveToPreferences(completionHandler: { [weak self ](error) -> Void in + //print(error) + if let e = error { + self!.alertMessageAction("save config error: \(e)",complete: nil) + } + }) + } + } + } + @objc func adBlockAction(_ sender:UISwitch){ + ProxyGroupSettings.share.historyEnable = sender.isOn + try! ProxyGroupSettings.share.save() + } + @objc func widgetAction(_ sender:UISwitch){ + ProxyGroupSettings.share.disableWidget = sender.isOn + try! ProxyGroupSettings.share.save() + } + @objc func widgetFlowAction(_ sender:UISwitch){ + if let defaults = UserDefaults(suiteName:groupIdentifier) { + defaults.set(sender.isOn, forKey: "widgetFlow") + defaults.synchronize() + } + + ProxyGroupSettings.share.widgetFlow = sender.isOn + try! ProxyGroupSettings.share.save() + } + @objc func countryFlagChanged(_ sender:UISwitch){ + + ProxyGroupSettings.share.showCountry = sender.isOn + try! ProxyGroupSettings.share.save() + + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + if indexPath.section == 0 { + + let cell = tableView.dequeueReusableCell(withIdentifier: "switchCell") as! SwitchCell + if indexPath.row == 0 { + cell.label?.text = "Request History".localized + cell.enableSwitch?.isOn = ProxyGroupSettings.share.historyEnable + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.adBlockAction(_:)), for: .valueChanged) + } else if indexPath.row == 1 { + cell.label?.text = "Today Widget Select".localized + cell.enableSwitch.isHidden = true + cell.enableSwitch?.isOn = ProxyGroupSettings.share.disableWidget + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.widgetAction(_:)), for: .valueChanged) + }else if indexPath.row == 2 { + cell.label?.text = "Today Widget Flow".localized + cell.enableSwitch.isHidden = false + cell.enableSwitch?.isOn = ProxyGroupSettings.share.widgetFlow + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.widgetFlowAction(_:)), for: .valueChanged) + }else { + cell.label?.text = "Show Country Flag".localized + cell.enableSwitch.isHidden = false + cell.enableSwitch?.isOn = ProxyGroupSettings.share.showCountry + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.countryFlagChanged(_:)), for: .valueChanged) + } + + cell.wwdc() + + return cell + }else if indexPath.section == 1 { + let cell = tableView.dequeueReusableCell(withIdentifier: "switchCell") as! SwitchCell + if indexPath.row == 0 { + if let manager = SFVPNManager.shared.manager { + cell.enableSwitch.setOn(manager.isOnDemandEnabled, animated: false) + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.valueChanged(_:)), for: .valueChanged) + } + }else if indexPath.row == 1 { + if let _ = SFVPNManager.shared.manager { + let s = wifiStatus() + cell.enableSwitch.setOn(s, animated: false) + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.valueChangedWIFI(_:)), for: .valueChanged) + } + cell.label.text = "WI-FI" + }else { + if let mangager = SFVPNManager.shared.manager { + cell.enableSwitch.setOn((mangager.protocolConfiguration?.disconnectOnSleep)!, animated: false) + cell.enableSwitch.addTarget(self, action: #selector(OndemandController.valueChangedSleep(_:)), for: .valueChanged) + } + cell.label.text = "Disconnect On Sleep".localized + } + + cell.wwdc() + return cell + }else if indexPath.section == 2 { + let cell = tableView.dequeueReusableCell(withIdentifier: "onDemandAdd") as! TextFieldCell + cell.textField.delegate = self + cell.wwdcStyle() + + let color:UIColor = UIColor.cyan + + let title = "Input Domain Name" + let s = NSMutableAttributedString(string:title) + _ = (title as NSString) + s.addAttributes([NSAttributedStringKey.foregroundColor:color], range: NSMakeRange(0, title.count)) + cell.textField?.attributedPlaceholder = s +// cell.valueChanged = {[weak self] (textfield:UITextField) -> Void in +// //self!.proxy.proxyName = textfield.text!{ +// print(textfield.text) +// +// } + + return cell + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "onDemand") + cell!.textLabel!.text = domains[indexPath.row] + cell?.updateStandUI() + + return cell! + } + } + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + + // Return false if you do not want the specified item to be editable. + if indexPath.section == 0 { + return false + } + return true + } + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + + + + if editingStyle == .delete{ + domains.remove(at: indexPath.row) + doneAction(true) + tableView.deleteRows(at: [indexPath as IndexPath], with: .automatic) + }else if editingStyle == .insert { + } + } + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + + return indexPath + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath as IndexPath, animated: true) + let cell = tableView.cellForRow(at: indexPath as IndexPath) + + switch indexPath.section{ + // case 0: + // self.performSegue(withIdentifier:"showURL", sender: cell) + case 0: + if indexPath.row == 1 { + self.performSegue(withIdentifier:"WidgetSegue", sender: cell) + } + + default: + + break + } + } +} diff --git a/Surf/PlaneView.swift b/Surf/PlaneView.swift new file mode 100644 index 0000000..f49d948 --- /dev/null +++ b/Surf/PlaneView.swift @@ -0,0 +1,51 @@ +// +// PlaneView.swift +// Surf +// +// Created by 孔祥波 on 8/3/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit +func DegreesToRadians(degrees:CGFloat) ->CGFloat +{ + return degrees * CGFloat(Float.pi) / 180; +}; +class PlaneView: UIView { + + var image:UIImage + required init?(coder aDecoder: NSCoder) { + image = UIImage.init(named: "plane")! + super.init(coder: aDecoder) + self.backgroundColor = UIColor.clear + + } + + // Only override draw() if you perform custom drawing. + // An empty implementation adversely affects performance during animation. + + override func draw(_ rect: CGRect) { + + //image.drawAtPoint(self.center) + let ctx:CGContext = UIGraphicsGetCurrentContext()! + ctx.saveGState(); + ctx.translateBy(x: 0, y: rect.height) + ctx.scaleBy(x: 1.0, y: -1.0); + // CGContextRotateCTM(ctx, DegreesToRadians(45)); + + let myShadowOffset = CGSize (width:0, height: 10); + //CGContextSetShadow (ctx, myShadowOffset, 10); + ctx.setShadow (offset: myShadowOffset, blur: 5, color: UIColor.gray.cgColor); + //image.drawInRect(rect) + + ctx.setFillColor(UIColor.white.cgColor); + ctx.clip(to: rect, mask: image.cgImage!); + ctx.fill(self.bounds); + + + ctx.restoreGState(); + + } + + +} diff --git a/Surf/PolicyViewController.swift b/Surf/PolicyViewController.swift new file mode 100644 index 0000000..21abc0b --- /dev/null +++ b/Surf/PolicyViewController.swift @@ -0,0 +1,123 @@ +// +// PolicyViewController.swift +// Surf +// +// Created by abigt on 16/2/16. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XSocket +import Xcon +import XRuler +protocol PolicyDelegate:class { + func editPolicyConfig(controller: PolicyViewController, policy:String)// +} +class PolicyViewController: SFTableViewController { + var oladValue:String! + var proxys:[SFProxy]! + var policys:[String] = ["DIRECT","REJECT","Proxy"] + weak var delegate:PolicyDelegate? + override func viewDidLoad() { + self.title = "Select Policy" + super.viewDidLoad() + for p in proxys { + policys.append(p.proxyName) + } + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return policys.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "policy", for: indexPath ) + + // Configure the cell... + let v = policys[indexPath.row] + cell.textLabel?.text = v + + if v == oladValue { + cell.textLabel?.textColor = UIColor.green + }else { + cell.updateStandUI() + + } + return cell + } + + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: false) + guard let d = self.delegate else {return} + d.editPolicyConfig(controller: self, policy: policys[indexPath.row]) + _ = self.navigationController?.popViewController(animated: true) + } + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/ProxyCell.swift b/Surf/ProxyCell.swift new file mode 100644 index 0000000..3ba8203 --- /dev/null +++ b/Surf/ProxyCell.swift @@ -0,0 +1,38 @@ +// +// ProxyCell.swift +// Surf +// +// Created by 孔祥波 on 16/4/1. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import XRuler +class ProxyCell: CountryCustomProxyCell { + + @IBOutlet weak var enableSwitch:UISwitch! + var valueChanged: ((UISwitch) -> Void)? + @IBOutlet weak var starImageView:UIImageView! + @IBAction func enableAction(sender:UISwitch){ + valueChanged?(enableSwitch) + } + func updateUI(){ + super.wwdcStyle() + if ProxyGroupSettings.share.wwdcStyle { + proxyLabel.textColor = UIColor.white + countryLabel.textColor = UIColor.white + }else { + proxyLabel.textColor = UIColor.darkText + countryLabel.textColor = UIColor.darkText + countryLabel.textColor = UIColor.init(red: 0x0b/255.0, green: 0x60/255.0, blue: 0xb1/255.0, alpha: 1.0) + } + } + /* + // Only override drawRect: if you perform custom drawing. + // An empty implementation adversely affects performance during animation. + override func drawRect(rect: CGRect) { + // Drawing code + } + */ + +} diff --git a/Surf/ProxyGroupViewController.swift b/Surf/ProxyGroupViewController.swift new file mode 100644 index 0000000..a1f9942 --- /dev/null +++ b/Surf/ProxyGroupViewController.swift @@ -0,0 +1,1387 @@ +// +// ProxyGroupViewController.swift +// Surf +// +// Created by 孔祥波 on 16/4/1. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import Darwin +import SFSocket +import NetworkExtension +import Alamofire +import SwiftyStoreKit +import Fabric +import Xcon +import XRuler +import IoniconsSwift +func version() ->Int{ + return 10 +} +import SafariServices +import ObjectMapper + extension String { + public func to(index:Int) ->String{ + return String(self[..String{ +// return String(self[..String{ + return String(self[self.index(self.startIndex, offsetBy:index)...]) + + } +// public func from(index:String.Index) ->String{ +// return String(self[index...]) +// +// } + func validateIpAddr2() ->SOCKS5HostType{ + var sin = sockaddr_in() + var sin6 = sockaddr_in6() + + if self.withCString({ cstring in inet_pton(AF_INET6, cstring, &sin6.sin6_addr) }) == 1 { + // IPv6 peer. + return .IPV6 + } + else if self.withCString({ cstring in inet_pton(AF_INET, cstring, &sin.sin_addr) }) == 1 { + // IPv4 peer. + return .IPV4 + } + + return .DOMAIN + + } +} +class abigtCloud:CommonModel{ + var proxys:[SFProxy] = [] + public override func mapping(map: Map) { + proxys <- map["proxys"] + } +} +class ProxyGroupViewController: SFTableViewController,BarcodeScanDelegate,AddEditProxyDelegate + //UIImagePickerControllerDelegate,UINavigationControllerDelegate +{ + + let dnsqueue:DispatchQueue = DispatchQueue(label:"com.abigt.dns") + let coreFuncs = ["Aid","start"] + let coreFuncsTitles = ["Connect"] + var titleView:TitleView? + var lastStartStopDate = Date() + let funcs = ["Ping","Config On demand Rule"]//,"Manual Add Proxy","Scan QrCode Add Proxy"] + var showServerIP = false + + var registedNoti:Bool = false + var widgetProfile:Bool = false + var d30found = false + @IBOutlet weak var buyRecordLabel:UILabel! + @IBOutlet var debugButton:UIButton! + + override func beginRequest(with context: NSExtensionContext) { + + } + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat{ + return 48 + } + @IBAction func showConfigEdit(_ sender:AnyObject){ + self.performSegue(withIdentifier: "showConfigEdit", sender: sender) + } + func testInapp(){ + let vc = UIStoryboard.init(name: "buy", bundle: nil).instantiateInitialViewController()! + self.navigationController?.pushViewController(vc, animated: true) + + } + @objc func downloadProxy(){ + let url = "https://swiftai.us/proxys.json" + Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil) + .responseJSON { (JSON) in + self.tableView.refreshControl?.endRefreshing() + switch JSON.result{ + case .success(let resp): + + + + if let m = Mapper().map(JSONObject:resp) { + for p in m.proxys { + var found = false + for pp in ProxyGroupSettings.share.proxys { + //print(pp.editEnable) + //print("\(p.proxyName) \(pp.proxyName)") + if pp.editEnable == false && p.proxyName == pp.proxyName { + pp.serverAddress = p.serverAddress + pp.serverPort = p.serverPort + pp.serverIP = "" + pp.password = p.password + pp.method = p.method + pp.tlsEnable = p.tlsEnable + pp.editEnable = false + found = true + } + } + if !found{ + _ = ProxyGroupSettings.share.addProxy(p) + } + + } + } + do { + try ProxyGroupSettings.share.save() + }catch let e { + print(e.localizedDescription) + } + self.tableView.reloadData() + + + case .failure(let x): + + self.alertMessageAction("Update A.BIG.T Cloud error,please try again".localized + " " + x.localizedDescription) + + } + + + } + } + + func purchase(_ product:RegisteredPurchase,quantity:Int) { + + NetworkActivityIndicatorManager.networkOperationStarted() + SwiftyStoreKit.purchaseProduct(appBundleId + "." + product.rawValue,quantity:quantity, atomically: false) { result in + NetworkActivityIndicatorManager.networkOperationFinished() + + if case .success(let purchase) = result { + // Deliver content from server, then: + if purchase.needsFinishTransaction { + SwiftyStoreKit.finishTransaction(purchase.transaction) + } + NetworkActivityIndicatorManager.networkOperationStarted() + self.verifyReceipt { appresult in + NetworkActivityIndicatorManager.networkOperationFinished() + //self.showAlert(self.alertForVerifyReceipt(result)) + switch appresult { + case .success(let receipt): + print(receipt) + if let r = Mapper().map(JSON: receipt), let re = r.receipt{ + do { + try ProxyGroupSettings.share.saveReceipt(re) + }catch let e { + print("\(e.localizedDescription)") + } + for rr in re.in_app { + if rr.product_id == self.appBundleId + "." + product.rawValue { + //buy veryfy + self.downloadProxy() + } + } + } + + case .error(let error): + print(error) + } + } + + } + if let alert = self.alertForPurchaseResult(result) { + self.showAlert(alert) + } + } + } + func addSafari(){ + let tap = UITapGestureRecognizer.init(target: self, action: #selector(openSafari(_:))) + tap.numberOfTapsRequired = 1 + tap.numberOfTouchesRequired = 2 + self.view.addGestureRecognizer(tap) + } + @objc func openSafari(_ sender:UITapGestureRecognizer){ + let u = "https://twitter.com" + let sf = SFSafariViewController.init(url:URL.init(string: u)!) + sf.delegate = self + self.present(sf, animated: true) { + + } + } + func updateLeftButton(){ + var image:UIImage + if self.isEditing { + image = Ionicons.checkmark.image(18, color: .white) + }else { + image = UIImage(named: "1180-align-justify-toolbar")! + } + let item = UIBarButtonItem.init(image: image, style: .plain, target: self, action: #selector(ProxyGroupViewController.reOrderProxy(_:))) + navigationItem.leftBarButtonItem = item + } + override func viewDidLoad() {//"Export to iCloud Driver","Import from iCloud Driver" + super.viewDidLoad() + addSafari() + self.tableView.refreshControl = UIRefreshControl() + self.tableView.refreshControl?.backgroundColor = UIColor.gray + self.tableView.refreshControl?.tintColor = UIColor.white + self.tableView.separatorInset = UIEdgeInsetsMake(0,50, 0, 0); + self.tableView.refreshControl?.addTarget(self, action: #selector(self.downloadProxy) + , for: UIControlEvents.valueChanged) + //self.testInapp() + if let p = ProxyGroupSettings.share.receipt { + print(p) + } + if self.verifyReceipt(.Pro) { + print("Run as Pro" ) + } + + //#if DEBUG + // #else + // debugButton.hidden = true + // #endif + self.title = "Switch".localized + NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "ProxyIndexChanged"), object: nil, queue: OperationQueue.main) { noti in + self.tableView.reloadData() + } + self.updateLeftButton() + titleView = TitleView.init(frame: CGRect.init(x: 0, y: 0, width: 240, height: 60)); + //titleView?.backgroundColor = UIColor.cyanColor() + navigationItem.titleView = titleView + let edit = UIBarButtonItem.init(barButtonSystemItem: .add, target: self, action: #selector(ProxyGroupViewController.addProxy(_:))) + + + navigationItem.rightBarButtonItem = edit + + self.tableView.allowsMultipleSelectionDuringEditing = false + + profileStatus() + + + + NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "applicationDidBecomeActive"), object: nil, queue: OperationQueue.main) { [weak self] (noti) in + if let s = self { + s.tableView.reloadData() + } + + } + NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "shouldSaveConfNotification"), object: nil, queue: OperationQueue.main) { [weak self](noti) in + if let userinfo = noti.userInfo , let url = userinfo["url"]{ + if let s = self { + s.updateWithURL(url: url as! NSURL) + } + } + } + + + } + + func updateWithURL(url:NSURL) { + if let p = url.path, let fileName = p.components(separatedBy:"/").last{ + let urldoc = applicationDocumentsDirectory.appendingPathComponent(fileName) + let urlgroup = groupContainerURL().appendingPathComponent(fileName) + try! fm.copyItem(at: url as URL, to: urldoc) + try! fm.copyItem(at:url as URL, to: urlgroup) + SFConfigManager.manager.loadConfigs() + ProxyGroupSettings.share.config = fileName + try! ProxyGroupSettings.share.save() + updateTitleView(config: fileName) + } + + } + @objc func reOrderProxy(_ sender:AnyObject){ + if ProxyGroupSettings.share.proxys.count == 0 { + alertMessageAction("Please add Proxy".localized, complete: nil) + + }else { + let edit = !self.isEditing + self.setEditing(edit, animated: true) + updateLeftButton() + } + + } + + func updateTitleView(config:String){ + + if let config = SFConfigManager.manager.selectConfig{ + + self.titleView?.subLabel.text = config.description() + self.titleView?.titleLabel.text = config.configName + }else { + self.titleView?.subLabel.text = "Config not Found,Please Add" + alertMessageAction("Config not Found,Please Add", complete: nil) + } + + + + + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + try! ProxyGroupSettings.share.loadProxyFromFile() + let config = ProxyGroupSettings.share.config + updateTitleView(config: config) + showScanXXX() + + if let re = ProxyGroupSettings.share.receipt { + for item in re.in_app { + if item.product_id == "com.abigt.Surf.30D"{ + let now = Date().timeIntervalSince1970 + let x = Double(item.original_purchase_date_ms)!/1000 + 30 * 24*3600 + let df = DateFormatter() + df.dateFormat = "yyyy/MM/dd HH:mm:ss" + df.timeZone = NSTimeZone.system + if now < x { + let buy_date = Date.init(timeIntervalSince1970:TimeInterval(Int64(item.original_purchase_date_ms)!/1000)) + self.buyRecordLabel.text = "Expire Data: \(df.string(from: buy_date))" + self.buyRecordLabel.isHidden = false + d30found = true + + break + } + } + } + } + + if d30found == false { + //store version + if (Int(appBuild())! % 2) == 0 { + var indexs:[Int] = [] + var index:Int = ProxyGroupSettings.share.proxys.count - 1 + let temp = ProxyGroupSettings.share.proxys.reversed() + for p in temp{ + if p.editEnable == false { + indexs.append(index) + } + index -= 1 + } + if !indexs.isEmpty{ + //ProxyGroupSettings.share.proxys.rem + for idx in indexs { + ProxyGroupSettings.share.proxys.remove(at: idx) + + } + do { + try ProxyGroupSettings.share.save() + }catch let e { + print("delete proxy error:\(e.localizedDescription)") + } + + } + } + + self.buyRecordLabel.isHidden = true + } + + ProxyGroupSettings.share.editing = true + tableView.reloadData() + + } + func profileStatus() { + NETunnelProviderManager.loadAllFromPreferences() { [weak self ](managers, error) -> Void in + if let managers = managers { + if managers.count > 0 { + + if let m = managers.first { + SFVPNManager.shared.manager = m + self!.registerStatus() + self!.tableView.reloadData() + SFVPNManager.shared.xpc() + } + NSLog("profile status #### \(managers)") + //self!.refresh() + } + + } + + } + } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + } + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + + if indexPath.section == 0 { + return false + }else { + return true + } + + } + override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { + let s = IndexPath.init(row: sourceIndexPath.row, section: sourceIndexPath.section-1) + let d = IndexPath.init(row: destinationIndexPath.row, section: destinationIndexPath.section-1) + //有个status section pass + ProxyGroupSettings.share.changeIndex(s, destPath: d) + + } + func showProxyGroup(_ send:AnyObject) { + if let vc = self.storyboard?.instantiateViewController(withIdentifier: "proxgroup"){ + self.present(vc, animated: true) { + + } + } + + } + + func showScan(){ + let queue = DispatchQueue.init(label: ".", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil) + //let queue = DispatchQueue(label: "com.abigt.socket")// DISPATCH_QUEUE_CONCURRENT) + + for p in ProxyGroupSettings.share.proxys { + if p.kcptun { + continue + } + queue.async(execute: { + + let start = Date() + + + // Look up the host... + let socketfd: Int32 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) + let remoteHostName = p.serverAddress + //let port = Intp.serverPort + + guard let remoteHost = gethostbyname2(remoteHostName, AF_INET)else { + return + } + + + let d = Date() + + + + p.dnsValue = d.timeIntervalSince(start) + var remoteAddr = sockaddr_in() + remoteAddr.sin_family = sa_family_t(AF_INET) + bcopy(remoteHost.pointee.h_addr_list[0], &remoteAddr.sin_addr.s_addr, Int(remoteHost.pointee.h_length)) + if let port = UInt16(p.serverPort) { + remoteAddr.sin_port = port.bigEndian + + }else { + _ = p.serverPort + print("\(p.serverPort) error") + close(socketfd) + p.tcpValue = -1 + return + } + + + + // Now, do the connection... + let rc = withUnsafePointer(to: &remoteAddr) { + // Temporarily bind the memory at &addr to a single instance of type sockaddr. + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + connect(socketfd, $0, socklen_t(MemoryLayout.stride)) + } + } + + + if rc < 0 { + print("\(p.serverAddress):\(p.serverPort) socket connect failed") + //throw BlueSocketError(code: BlueSocket.SOCKET_ERR_CONNECT_FAILED, reason: self.lastError()) + p.tcpValue = -1 + }else { + let end = Date() + p.tcpValue = end.timeIntervalSince(d ) + close(socketfd) + } + + DispatchQueue.main.async(execute: { [weak self] in + if let StrongSelft = self { + StrongSelft.tableView.reloadData() + } + //保存IP/ping value + try! ProxyGroupSettings.share.save() + + }) + + }) + } + } + + func showScanXXX(){ + let queue = DispatchQueue.init(label: "test.http", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil) + //let queue = DispatchQueue(label: "com.abigt.socket")// DISPATCH_QUEUE_CONCURRENT) + queue.async(execute: { + + + + + // Look up the host... + let socketfd: Int32 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) + let remoteHostName = "127.0.0.1" + //let port = Intp.serverPort + + guard let remoteHost = gethostbyname2(remoteHostName, AF_INET)else { + return + } + + + + + + + + var remoteAddr = sockaddr_in() + remoteAddr.sin_family = sa_family_t(AF_INET) + bcopy(remoteHost.pointee.h_addr_list[0], &remoteAddr.sin_addr.s_addr, Int(remoteHost.pointee.h_length)) + + let p:UInt16 = 10081 + + remoteAddr.sin_port = p.bigEndian + + // Now, do the connection... + let rc = withUnsafePointer(to: &remoteAddr) { + // Temporarily bind the memory at &addr to a single instance of type sockaddr. + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + connect(socketfd, $0, socklen_t(MemoryLayout.stride)) + } + } + + + if rc < 0 { + let str = String.init(cString: strerror(errno)) + print("socket connect failed " + str ) + + }else { + + close(socketfd) + } + + }) + + + + } + func addAction(_ sender:UIButton) { + self.performSegue(withIdentifier: "addProxy", sender: sender) + } + + @IBAction func editAction(_ sender:UIBarButtonItem){ + let edit = self.isEditing + if edit { + navigationItem.rightBarButtonItem = UIBarButtonItem.init(barButtonSystemItem: .edit, target: self, action: #selector(ProxyGroupViewController.editAction(_:))) + do { + try ProxyGroupSettings.share.save() + //freshProxy() + }catch let e as NSError{ + print("\(e)") + } + + }else { + navigationItem.rightBarButtonItem = UIBarButtonItem.init(barButtonSystemItem: .done, target: self, action: #selector(ProxyGroupViewController.editAction(_:))) + } + ProxyGroupSettings.share.editing = !isEditing + self.setEditing(!edit, animated: true) + tableView.reloadData() + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + if ProxyGroupSettings.share.proxyChain { + return 3 + } + return 2 + } + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + if section == 1 { + var count = 0 + count = ProxyGroupSettings.share.proxys.count + if count == 0{ + return 1 + }else { + return count + } + + } else if section == 2 { + let x = ProxyGroupSettings.share.chainProxys.count + print("proxy chain \(x)") + return x + }else { + + return 1 + } + + } + + func hostToIP(proxy:SFProxy) { + dnsqueue.async(execute:{ [weak self ] in + //update from gethostbyname to gethostbyname2 API + guard let hostInfo = gethostbyname2((proxy.serverAddress as NSString).utf8String, AF_INET)else { + return + } + + + + let len = hostInfo.pointee.h_length + let aa = hostInfo.pointee.h_addr_list[0] + var ip = "" + + for i in 0 ..< len { + let x = (aa! + Int(i)).pointee + if i == (len - 1) { + ip += "\(toUint(signed: x))" + break + } + ip += "\(toUint(signed: x))." + + } + proxy.serverIP = ip + DispatchQueue.main.async(execute: { + self!.tableView.reloadData() + }) + + }) + + + //return ip + } + override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { + + if indexPath.section != 0 { + if ProxyGroupSettings.share.proxys.count != 0 { + self.performSegue(withIdentifier: "showProxy", sender: tableView.cellForRow(at: indexPath)) + } + } + + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + var iden = "" + + if indexPath.section == 1 || indexPath.section == 2{ + iden = "proxy-group" + + let cell = tableView.dequeueReusableCell(withIdentifier: iden, for: indexPath) as! ProxyCell + cell.updateUI() + + cell.accessoryType = .detailButton + var count = 0 + let group = ProxyGroupSettings.share + count = group.proxys.count + if indexPath.row < count { + var proxy:SFProxy + + if indexPath.section == 1 { + proxy = group.proxys[indexPath.row] + + if indexPath.row == ProxyGroupSettings.share.selectIndex{ + //cell.starImageView.hidden = false + cell.countryLabel.text = "\u{f383}" + } else { + //cell.starImageView.hidden = true + //cell.countryLabel.hidden = false + + cell.countryLabel.text = "" + } + }else { + if indexPath.row == ProxyGroupSettings.share.proxyChainIndex{ + //cell.starImageView.hidden = false + cell.countryLabel.text = "\u{f383}" + } else { + //cell.starImageView.hidden = true + //cell.countryLabel.hidden = false + + cell.countryLabel.text = "" + } + proxy = SFProxy.createProxyWithLine(line: "", pname: "xx")! + // proxy = group.chainProxys[indexPath.row] + } + + cell.enableSwitch.isHidden = true + //cell.countryLabel.backgroundColor = UIColor.white + + //} + + if proxy.editEnable == false { + cell.accessoryType = .none + } + cell.enableSwitch.isOn = proxy.enable + cell.valueChanged = { (s:UISwitch) -> Void in + proxy.enable = s.isOn + } + + let host = proxy.serverAddress + + let type = host.validateIpAddr2() + if type == .DOMAIN { + if proxy.serverIP.isEmpty { + self.hostToIP(proxy: proxy) + }else { + + //print(host) + } + }else if type == .IPV4 { + proxy.serverIP = host + + } + if !proxy.serverIP.isEmpty { + + + if proxy.isoCode.isEmpty { + let rusult = Country.setting.geoIPRule(ipString: proxy.serverIP) + + proxy.countryFlag = rusult.emoji + proxy.isoCode = rusult.isoCode + print("\(proxy.countryFlag):\(rusult.isoCode)") + do { + try ProxyGroupSettings.share.save() + }catch let e as NSError { + print("ProxyGroupSettings save error:\(e)") + } + } + + } + + if showServerIP { + var info:String = proxy.serverAddress + ":" + proxy.serverPort + if !proxy.isoCode.isEmpty{ + if proxy.editEnable { + if group.showCountry { + info = proxy.serverAddress + ":" + proxy.serverPort + }else { + info = proxy.isoCode + " " + proxy.serverAddress + ":" + proxy.serverPort + } + }else { + info = proxy.countryFlag + " " + proxy.proxyName + } + + + } + cell.proxyLabel.text = info + + //cell.enableSwitch.hidden = false + cell.enableSwitch.isOn = proxy.enable + if cell.valueChanged == nil { + cell.valueChanged = { (s:UISwitch) -> Void in + //self!.proxy.proxyName = textfield.text! + proxy.enable = s.isOn + try! ProxyGroupSettings.share.save() + } + + } + + }else { + if group.showCountry { + cell.proxyLabel.text = proxy.countryFlag + " " + proxy.proxyName + }else { + cell.proxyLabel.text = proxy.proxyName + } + + + + + } + + + + + + if proxy.tcpValue != 0 { + var ts = "" + if proxy.tcpValue > 0.0 { + ts = String(format: " TCP Ping: %.0f ms", proxy.tcpValue*1000) + cell.subLabel.textColor = UIColor.lightGray + }else { + + if proxy.kcptun { + cell.subLabel.textColor = UIColor.lightGray + }else { + ts = " TCP Ping: Error" + cell.subLabel.textColor = UIColor.red + } + + } + + cell.subLabel.text = proxy.typeDesc() + ts + }else { + cell.subLabel.text = proxy.typeDesc() + } + }else { + cell.countryLabel.text = "" + cell.proxyLabel.text = "No Proxy Found".localized + cell.subLabel.text = "Please Manual/QrCode Add Proxy".localized + cell.enableSwitch.isHidden = true + cell.starImageView.isHidden = true + } + if let m = SFVPNManager.shared.manager{ + if m.connection.status == .invalid { + //cell.enableSwitch.isOn = showStart() + } + }else { + //cell.enableSwitch.isOn = showStart() + } + // Configure the cell... + + return cell + }else if indexPath.section == 0{ + + iden = "commonSwitch"//"mainFunc" + let cell = tableView.dequeueReusableCell(withIdentifier: iden, for: indexPath) as! SampleSwitchCell + cell.updateUI() + + + + if cell.valueChanged == nil { + cell.valueChanged = { [unowned self] (s:UISwitch) -> Void in + + self.startStopToggled() + } + + } + + //cell.label?.text = "Status" + + updateStatus(cell: cell) + + return cell + }else { + + iden = "common" + let cell = tableView.dequeueReusableCell(withIdentifier: iden, for: indexPath) as! SampleCell + cell.updateUI() + + return cell + + } + + } + + override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { + + if indexPath.section != 0{ + if ProxyGroupSettings.share.proxys.count == 0 { + return .none + }else { + return .delete + } + + } + return .none + + } +// override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { +// if indexPath.section == 0{ +// return nil +// } +// return indexPath +// +// } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: true) + if indexPath.section == 1 || indexPath.section == 2{ + + if indexPath.section == 1 { + if ProxyGroupSettings.share.selectIndex == indexPath.row { + showScan() + showServerIP = !showServerIP + }else { + ProxyGroupSettings.share.selectIndex = indexPath.row + let p = ProxyGroupSettings.share.proxys[indexPath.row] + p.enable = true + try! ProxyGroupSettings.share.save() + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected { + + + changeProxy(index: indexPath.row) + } + } + + } + }else { + if ProxyGroupSettings.share.proxyChainIndex == indexPath.row { + showScan() + showServerIP = !showServerIP + }else { + ProxyGroupSettings.share.proxyChainIndex = indexPath.row + let p = ProxyGroupSettings.share.chainProxys[indexPath.row] + p.enable = true + try! ProxyGroupSettings.share.save() + + } + } + + + tableView.reloadData() + + }else { + //utilityFunc(indexPath.row) + //self.performSegue(withIdentifier:"showOndemand", sender: nil) + showScan() + } + } + func changeProxy(index:Int) { + let me = SFVPNXPSCommand.CHANGEPROXY.rawValue + "|\(index)" + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8) + { + do { + try session.sendProviderMessage(message) { [weak self] response in + if let r = String.init(data: response!, encoding: .utf8) , r == proxyChangedOK{ + + self!.alertMessageAction(r) + + } else { + self!.alertMessageAction("Failed to Change Proxy",complete: nil) + } + } + } catch let e as NSError{ + alertMessageAction("Failed to Change Proxy,reason \(e.description)",complete: nil) + } + + } + } + + } + func coreFuncs(Index:Int){ + switch Index { + case 1: + //let iden = "showOndemand" + // self.performSegue(withIdentifier:iden, sender: tableView.cellForRowAtIndexPath(indexPath)) + showScan() + case 0: + if let _ = SFVPNManager.shared.manager{ + startStopToggled() + }else { + SFVPNManager.shared.loadManager({ [unowned self](manager, error) in + if let e = error { + self.alertMessageAction("Load Profile Error:".localized + " \(e.localizedDescription)", complete: nil) + }else { + if manager!.connection.status == .invalid { + print("SFVPNManager connection status == .invalid") + SFNETunnelProviderManager.loadOrCreateDefaultWithCompletionHandler({ (m, e) in + if let e = e { + print("load error:" + e.localizedDescription) + } + SFVPNManager.shared.manager = m + self.registerStatus() + self.startStopToggled() + }) + }else { + self.registerStatus() + self.startStopToggled() + } + + } + + }) + } + default: + break + } + } + func utilityFunc(Index:Int) { + + switch Index { + case 0: + showScan() + case 1: + self.performSegue(withIdentifier: "showOndemand", sender: nil) + case 2: + self.performSegue(withIdentifier: "addProxy", sender: nil) + case 3: + self.performSegue(withIdentifier: "showBarCode", sender: nil) + case 4: break + //scanbarCodeFromPhotoLibrary() + default: + break + } + + } + @objc func addProxy(_ sender:AnyObject) { + self.performSegue(withIdentifier: "addProxy", sender: nil) + } + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + + // Return false if you do not want the specified item to be editable. + if indexPath.section == 0 { + return false + } + return true + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + switch section { + case 0: + return nil + case 1: + return ""//"Proxy Server".localized + case 2: + return "Chain Proxy".localized + default: + return nil + } + } + + + func addProxyConfig(_ controller: AddEditProxyController, proxy:SFProxy){ + _ = ProxyGroupSettings.share.addProxy(proxy) + try! ProxyGroupSettings.share.save() + tableView.reloadData() + + } + func editProxyConfig(_ controller: AddEditProxyController, proxy:SFProxy){ + + ProxyGroupSettings.share.updateProxy(proxy) + try! ProxyGroupSettings.share.save() + tableView.reloadData() + } + + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + + if editingStyle == .delete { + // Delete the row from the data source + + + if ProxyGroupSettings.share.proxys.count == 0 { + return + }else { + if indexPath.section == 1{ + ProxyGroupSettings.share.removeProxy(indexPath.row) + if ProxyGroupSettings.share.proxys.count != 0{ + tableView.deleteRows(at: [indexPath], with: .fade) + }else { + tableView.reloadData() + } + }else { + ProxyGroupSettings.share.removeProxy(indexPath.row,chain:true) + //FIXME: maybe crash + if ProxyGroupSettings.share.chainProxys.count != 0{ + tableView.deleteRows(at: [indexPath], with: .fade) + }else { + tableView.reloadData() + } + } + + + + } + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + + + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + if segue.identifier == "showBarCode"{ + guard let barCodeController = segue.destination as? BarcodeScanViewController else{return} + //barCodeController.useCamera = self.useCamera + barCodeController.delegate = self + //barCodeController.navigationItem.title = "Add Proxy" + + }else if segue.identifier == "showProxy" { + guard let c = segue.destination as? AddEditProxyController else {return} + guard let indexPath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + if indexPath.section == 1 { + if indexPath.row < ProxyGroupSettings.share.proxys.count{ + c.proxy = ProxyGroupSettings.share.proxys[indexPath.row] + + } + + }else { + //FIXME: maybe crash + if indexPath.row < ProxyGroupSettings.share.chainProxys.count{ + c.proxy = ProxyGroupSettings.share.chainProxys[indexPath.row] + } + } + + c.delegate = self + }else if segue.identifier == "addProxy" { + guard let c = segue.destination as? AddEditProxyController else {return} + + c.delegate = self + }else if segue.identifier == "showConfigEdit" { + guard let c = segue.destination as? ConfigEditViewController else {return} + + guard let config = SFConfigManager.manager.selectConfig else {return} + c.url = SFConfigManager.manager.urlForConfig(config) + } + + } + + + func updateStatus(cell:SampleSwitchCell?){ + + var status = "Disconnect".localized + var stat = false + if let m = SFVPNManager.shared.manager, m.isEnabled { + mylog("status:\(m.connection.status)") + + + switch m.connection.status{ + case .disconnected: + + status = "Disconnect".localized + stat = false + + case .invalid: + + status = "Please Try Again".localized + stat = false + case .connected: + + status = "Connected".localized + + stat = true + case .connecting: + + status = "Connecting".localized + stat = true + case .disconnecting: + + status = "Disconnecting".localized + stat = false + case .reasserting: + status = "Reasserting".localized + stat = false + + + } + + + }else { + +// stat = showStart() +// if stat { +// status = "Connected" +// }else { +// status = "Disconnect" +// } + + } + if let cell = cell { + cell.statuslabel?.text = status + cell.sfSwitch?.isOn = stat + } + + } + + + + internal func barcodeScanDidScan(controller: BarcodeScanViewController, configString:String){ + + if self.presentedViewController == controller { + self.dismiss(animated: true, completion: { () -> Void in + + }) + + } + + convertConfigString(configString: configString) + + + } + internal func barcodeScanCancelScan(controller: BarcodeScanViewController){ + if self.presentedViewController == controller { + self.dismiss(animated: true, completion: { () -> Void in + + }) + + } + + } + func convertConfigString(configString: String){ + // http://base64str + //"aes-256-cfb:fb4b532cb4180c9037c5b64bb3c09f7e@108.61.126.194:14860" + //mayflower://xx:xx@108.61.126.194:14860 + + if let u = NSURL.init(string: configString){ + guard let proxy:SFProxy = SFProxy.create(name: "", type: .SS, address: "", port: "", passwd: "", method: "", tls: false) else { + return + } + + guard let scheme = u.scheme else {return} + + + let t = scheme.uppercased() + if t == "HTTP" { + proxy.type = .HTTP + }else if t == "HTTPS" { + proxy.type = .HTTPS + proxy.tlsEnable = true + }else if t == "SOCKS5" { + proxy.type = .SOCKS5 + }else if t == "SS" { + proxy.type = .SS + }else { + alertMessageAction("\(scheme) Invilad", complete: nil) + return + } + let result = u.host! + + if let query = u.query { + let x = query.components(separatedBy: "&") + for xy in x { + let x2 = xy.components(separatedBy: "=") + if x2.count == 2 { + if x2.first! == "remark" { + proxy.proxyName = x2.last!.removingPercentEncoding! + } + //print(x.first! + "### " + x.last!.removingPercentEncoding!) + } + } + } + if let data = Data.init(base64Encoded: result , options: .ignoreUnknownCharacters) { + if let resultString = String.init(data: data, encoding: .utf8) { + let items = resultString.components(separatedBy: ":") + if items.count == 3 { + proxy.method = items[0] + proxy.serverPort = items[2] + let x = items[1].components(separatedBy:"@") + if x.count >= 2 { + _ = items[1] + proxy.serverAddress = x.last! + //let end = tempString.startIndex.advancedBy() + _ = proxy.serverAddress.count +// let r = Range(0 ..< (tempString.characters.count - ps - 1)) +// +// +// let pass = tempString.substring(with: r) // substringWithRange(r) +// proxy.password = pass + _ = ProxyGroupSettings.share.addProxy(proxy) + }else { + alertMessageAction("\(resultString) Invilad,Format is http://base64(hostname)", complete: nil) + } + }else { + alertMessageAction("\(resultString) Invilad,Format is http://base64(hostname)", complete: nil) + } + }else{ + alertMessageAction("\(configString) Invilad,Format is http://base64(hostname)", complete: nil) + } + + }else { + alertMessageAction("\(configString) Invilad,Format is http://base64(hostname)", complete: nil) + } + + + + }else { + alertMessageAction("\(configString) Invilad,Format is http://base64(hostname)", complete: nil) + } + + //freshProxy() + tableView.reloadData() + + + } + func loadManager() { + //print("loadManager") + let vpnmanager = SFVPNManager.shared + if !vpnmanager.loading { + vpnmanager.loadManager() { + [weak self] (manager, error) -> Void in + if let _ = manager { + self!.tableView.reloadData() + self!.registerStatus() + vpnmanager.xpc() + } + } + }else { + //mylog("vpnmanager loading") + } + + } + //VPN mangment + // MARK: Interface + + + + /// Register for configuration change notifications. + @objc func registerStatus(){ + if let m = SFVPNManager.shared.manager { + // Register to be notified of changes in the status. + if registedNoti { + return + } + NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: m.connection, queue: OperationQueue.main, using: { [weak self] notification in + //self?.vpnStatus = self!.targetManager.connection.status + // self.statusLabel.text = self.targetManager.connection.status.description + // self.startStopToggle.on = (self.targetManager.connection.status != .Disconnected && self.targetManager.connection.status != .Disconnecting && self.targetManager.connection.status != .Invalid) + + self!.tableView.reloadData() + self!.registedNoti = true + //mylog("\(notification)") + }) + }else { + self.loadManager() + } + + } + func stopObservingStatus() { + if let m = SFVPNManager.shared.manager { + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: m.connection) + } + + } + + @IBAction func startStopToggled() { + if ProxyGroupSettings.share.saveDBIng { + alertMessageAction(NSLocalizedString("Save Config,Please wait...",comment:""), complete: nil) + return + } + do { + let selectConf = ProxyGroupSettings.share.config + let now = Date() + let exp = Int(now.timeIntervalSince(lastStartStopDate)) + if let m = SFVPNManager.shared.manager, m.connection.status == .connected { + + Answers.logCustomEvent(withName: "Stop", + customAttributes: [ + "Time Interval": exp, + + ]) + }else { + Answers.logCustomEvent(withName: "Start", + customAttributes: [ + + "Time Interval": exp, + ]) + + } + lastStartStopDate = now + let result = try SFVPNManager.shared.startStopToggled(selectConf) + + + if !result { + Timer.scheduledTimer(timeInterval: 5.0, target: self + , selector: #selector(ProxyGroupViewController.registerStatus), userInfo: nil, repeats: false) + SFVPNManager.shared.loadManager({[unowned self] (manager, error) in + if let error = error { + self.alertMessageAction("\(error.localizedDescription)",complete: nil) + }else { + self.startStopToggled() + } + }) + } + + } catch let error as NSError{ + SFVPNManager.shared.xpc() + alertMessageAction("\(error.localizedDescription)",complete: nil) + } + + } + +} + +extension ProxyGroupViewController:SFSafariViewControllerDelegate{ + func safariViewController(_ controller: SFSafariViewController, activityItemsFor URL: URL, title: String?) -> [UIActivity] { + return [] + } +} diff --git a/Surf/RecentReqViewController.swift b/Surf/RecentReqViewController.swift new file mode 100644 index 0000000..ae1b8d1 --- /dev/null +++ b/Surf/RecentReqViewController.swift @@ -0,0 +1,284 @@ +// +// RecnetReqViewController.swift +// Surf +// +// Created by abigt on 16/2/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import NetworkExtension +import SwiftyJSON +import SFSocket +import XRuler +import Xcon +import XProxy +class RecenetReqViewController: SFTableViewController { + var results:[SFRequestInfo] = [] + var resultsFin:[SFRequestInfo] = [] + var dbURL:URL? + + var session:String = "" + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Recent Requests" + + recent() + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + let item = UIBarButtonItem.init(image: UIImage.init(named: "760-refresh-3-toolbar"), style: .plain, target: self, action: #selector(RecenetReqViewController.refreshAction(_:))) + + + self.navigationItem.setRightBarButtonItems([item], animated: false) + + } + //sharedb feature 废弃,使用session 中的share + @objc func refreshAction(_ sender:AnyObject){ + recent() + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if !verifyReceipt(.Analyze) { + changeToBuyPage() + return + } + } + + func requests() { + + if ProxyGroupSettings.share.historyEnable{ + //resultsFin.removeAll() + if !session.isEmpty { + dbURL = RequestHelper.shared.openForApp(session) + } + resultsFin = RequestHelper.shared.fetchAll() + } + + } + func test() { + let path = Bundle.main.path(forResource: "1.txt", ofType: nil) + if let _ = NSData.init(contentsOfFile: path!) { + + } + } + func recent(){ + // Send a simple IPC message to the provider, handle the response. + //AxLogger.log("send Hello Provider") + //var rpc = false + if let m = SFVPNManager.shared.manager { + let date = Date() + let me = SFVPNXPSCommand.RECNETREQ.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8), m.connection.status == .connected + { + do { + //rpc = true + try session.sendProviderMessage(message) {[weak self] response in + guard let s = self else {return} + if response != nil { + //let responseString = NSString(data: response!, encoding: NSUTF8StringEncoding) + //mylog("Received response from the provider: \(responseString)") + s.processData(data: response!) + //self.registerStatus() + } else { + s.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + alertMessageAction("Failed to send a message to the provider",complete: nil) + } + } + } + + } + func processData(data:Data) { + results.removeAll() + //let responseString = NSString(data: response!, encoding: NSUTF8StringEncoding) + let obj = try! JSON.init(data: data) + if obj.error == nil { + + let count = obj["count"] + self.session = obj["session"].stringValue + //print("recent request count:\(count.stringValue)") + if count.intValue != 0 { + //alertMessageAction("Don't have Record yet!",complete: nil) + //return + let result = obj["data"] + if result.type == .array { + for item in result { + + let json = item.1 + let r = SFRequestInfo.init(rID: 0) + r.map(json) + + results.append(r) + } + } + if results.count > 0 { + results.sort(by: { $0.sTime.compare($1.sTime as Date) == ComparisonResult.orderedDescending }) + + } + + } + + + } + requests() + tableView.reloadData() + //mmlog("Received response from the provider: \(responseString)") + //self.registerStatus() + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + override func numberOfSections(in tableView: UITableView) -> Int { + + + // #warning Incomplete implementation, return the number of sections + if ProxyGroupSettings.share.historyEnable{ + return 2 + } + return 1 + } + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + if ProxyGroupSettings.share.historyEnable{ + if section == 0 { + return "Active REQUESTS" + } + return "RENCENT REQUESTS" + }else { + return "Active REQUESTS" + } + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + if section == 0 { + if results.count == 0 { + return 1 + } + return results.count + }else { + return resultsFin.count + } + + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "recent", for: indexPath) + cell.updateStandUI() + + // Configure the cell... + + var request:SFRequestInfo? + if indexPath.section == 0 { + if indexPath.row < results.count { + request = results[indexPath.row] + } + + }else { + request = resultsFin[indexPath.row] + + } + + + + if let request = request{ + cell.detailTextLabel?.textColor = UIColor.lightGray + + cell.textLabel?.text = request.url //+ " " + String(request.reqID) + " " + String(request.subID) + + cell.detailTextLabel?.attributedText = request.detailString() + }else { + cell.textLabel?.text = "Session Not Start".localized + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected { + cell.textLabel?.text = "Session Running" + } + } + + cell.detailTextLabel?.text = "" + } + + + return cell + + } + + + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + if segue.identifier == "requestDetail" { + guard let detail = segue.destination as? RequestDetailViewController else{return} + guard let indexPath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + var request:SFRequestInfo + if indexPath.section == 0 { + if results.count == 0 { + return + }else { + request = results[indexPath.row] + } + + }else { + request = resultsFin[indexPath.row] + + } + if request.url.isEmpty { + alertMessageAction("Request url empty", complete: nil) + }else { + detail.request = request + } + + } + + } + +} diff --git a/Surf/RequestDetailViewController.swift b/Surf/RequestDetailViewController.swift new file mode 100644 index 0000000..6bfd871 --- /dev/null +++ b/Surf/RequestDetailViewController.swift @@ -0,0 +1,453 @@ +// +// RequestDetailViewController.swift +// Surf +// +// Created by abigt on 16/2/15. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SwiftyJSON +import SFSocket +import XRuler +import Xcon +import XProxy +extension UITableViewCell { + func updateStandUI(){ + if ProxyGroupSettings.share.wwdcStyle { + textLabel?.textColor = UIColor.white + detailTextLabel?.textColor = UIColor.white + }else { + textLabel?.textColor = UIColor.black + detailTextLabel?.textColor = UIColor.black + } + } +} +class HeaderCell: UITableViewCell { + @IBOutlet weak var titleLabel:UILabel! + @IBOutlet weak var headerLabel:UILabel! + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + } + func wwdcStyle(){ + let style = ProxyGroupSettings.share.wwdcStyle + if style { + titleLabel.textColor = UIColor.white + headerLabel.textColor = UIColor.white + }else { + titleLabel.textColor = UIColor.black + headerLabel.textColor = UIColor.black + } + + + } +} +class TrafficCell: UITableViewCell { + @IBOutlet weak var titleLabel:UILabel! + @IBOutlet weak var rxLabel:UILabel! + @IBOutlet weak var txLabel:UILabel! + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + } + func wwdcStyle(){ + let style = ProxyGroupSettings.share.wwdcStyle + if style { + rxLabel.textColor = UIColor.white + txLabel.textColor = UIColor.white + titleLabel.textColor = UIColor.init(red: 0.36, green: 0.65, blue: 0.76, alpha: 1.0) + }else { + rxLabel.textColor = UIColor.black + txLabel.textColor = UIColor.black + titleLabel.textColor = UIColor.init(red: 0.36, green: 0.65, blue: 0.76, alpha: 1.0) + } + + } +} +class TimingCell: UITableViewCell { + @IBOutlet weak var titleLabel:UILabel! + @IBOutlet weak var ruleLabel:UILabel! + @IBOutlet weak var estLabel:UILabel! + @IBOutlet weak var transferLabel:UILabel! + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + } + func wwdcStyle(){ + + let style = ProxyGroupSettings.share.wwdcStyle + if style { + titleLabel.textColor = UIColor.init(red: 0.36, green: 0.65, blue: 0.76, alpha: 1.0) + ruleLabel.textColor = UIColor.white + estLabel.textColor = UIColor.white + transferLabel.textColor = UIColor.white + }else { + titleLabel.textColor = UIColor.init(red: 0.36, green: 0.65, blue: 0.76, alpha: 1.0) + ruleLabel.textColor = UIColor.black + estLabel.textColor = UIColor.black + transferLabel.textColor = UIColor.black + } + + + } +} +//class TimingCell: UITableViewCell { +// @IBOutlet weak var ruleLabel:UILabel! +// @IBOutlet weak var estLabel:UILabel! +// @IBOutlet weak var transferLabel:UILabel! +// override func setSelected(selected: Bool, animated: Bool) { +// super.setSelected(selected, animated: animated) +// +// } +//} +class RequestDetailViewController: SFTableViewController { + + var request:SFRequestInfo! + + override func viewDidLoad() { + super.viewDidLoad() + if request == nil { + return + } + self.title = request.url + //_;Int = -1 + let items = UIBarButtonItem.init(image: UIImage(named: "702-share-toolbar"), style: .plain, target: self, action: #selector(RequestDetailViewController.shareRequestAction(_:))) + self.navigationItem.rightBarButtonItem = items + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + @objc func shareRequestAction(_ sender:AnyObject){ + + var style:UIAlertControllerStyle = .actionSheet + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Share Request", message: "share request", preferredStyle: style) + if request.mode == .HTTP { + + let action = UIAlertAction.init(title: "Share curl command", style: .default) { [unowned self] (action:UIAlertAction) -> Void in + self.shareRequest(true,copy:false) + } + alert.addAction(action) + } + + let action3 = UIAlertAction.init(title: "Share", style: .default) {[unowned self] (action:UIAlertAction) -> Void in + //let srcPath = self.filePath? + // + + self.shareRequest(false,copy:false) + } + let actionCopy = UIAlertAction.init(title: "Copy as curl command", style: .default) {[unowned self] (action:UIAlertAction) -> Void in + //let srcPath = self.filePath? + // + + self.shareRequest(true, copy: true) + } + alert.addAction(actionCopy) + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction) -> Void in + + } + + + alert.addAction(action3) + alert.addAction(cancelAction) + + self.present(alert, animated: true) { () -> Void in + + } + } + + func shareRequest(_ curl:Bool,copy:Bool){ + + var str:String = "" + if curl{ + guard let h = request.reqHeader else {return} + str += "curl '\(request.url)' " + for (k,v) in h.parmas() { + str += " --header '\(k):\(v)' " + } + if copy { + let p = UIPasteboard.general + p.string = str + alertMessageAction("Info copyed as curl command", complete: nil) + } + }else { + let result = request.respObj() + let j = JSON(result) + do { + let data = try j.rawData() + //let obj = SFData() + //obj.data = data + if let x = String.init(data: data, encoding: .utf8){ + str = x + } + + }catch let error as NSError { + //AxLogger.log("ruleResultData error \(error.localizedDescription)") + //let x = error.localizedDescription + alertMessageAction("JSON error: \(error.localizedDescription)", complete:nil) + return + } + + } + + if !str.isEmpty{ + let url = URL.init(fileURLWithPath: NSTemporaryDirectory()+"curl.sh") + try! str.write(to: url, atomically: false, encoding: .utf8) + let controller = UIActivityViewController(activityItems: [str],applicationActivities:nil) + + if let actv = controller.popoverPresentationController { + actv.barButtonItem = self.navigationItem.rightBarButtonItem // if it is a UIBarButtonItem + + // Or if it is a view you can get the view rect + actv.sourceView = self.view + // actv.sourceRect = someView.frame // you can also specify the CGRect + } + + + controller.completionWithItemsHandler = { (type,complete,items,error) in + do { + try FileManager.default.removeItem(at: url) + }catch let e { + print(e.localizedDescription) + } + + } + self.present(controller, animated: true, completion: { + + }) + + } + + + + + + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + + // #warning Incomplete implementation, return the number of sections + if request == nil { + return 0 + } + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + //head, status ,req ,policy, resp,timing,traffic + return 8 + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + + switch indexPath.row { + case 0,1,3: + return 44.0 + case 2,4: + if request.mode == .TCP { + return 44.0 + }else { + let font = UIFont(name: "Helvetica", size: 11.0) + var x:CGFloat = 10 + + var headerString:String + if indexPath.row == 2{ + if let req = request.reqHeader { + headerString = req.headerString(nil) + x = 30 + }else { + headerString = "HTTP Request Header Error" + } + + + }else { + if let req = request.respHeader { + headerString = req.headerString(nil) + }else { + headerString = "HTTP Response Header Error" + } + + + } + if headerString.isEmpty { + return 44 + }else { + let result = x + heightForView(text: headerString, font: font!, width: self.view.frame.size.width-20) + if result < 44.0 { + return 44 + }else { + return result + } + } + + } + + + case 5: + return 90 + case 6,7: + return 70 + default: + return 44.0 + } + + } + func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{ + let label:UILabel = UILabel(frame: CGRect(x:0, y:0, width:width, height: CGFloat.greatestFiniteMagnitude)) + label.numberOfLines = 0 + label.lineBreakMode = NSLineBreakMode.byWordWrapping + label.font = font + label.text = text + + label.sizeToFit() + return label.frame.height + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + //let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) + + // Configure the cell... + + switch indexPath.row { + case 0: + let cell = tableView.dequeueReusableCell(withIdentifier: "subTitle", for: indexPath) + cell.textLabel?.text = request.url + cell.updateStandUI() + let t = request.dataDesc(request.sTime) + let agent = SFAppIden.shared.appDesc(agent: request.app) + if request.mode == .TCP{ + cell.detailTextLabel?.text = "[TCP] \(t)" + }else { + cell.detailTextLabel?.text = "[\(agent)] \(t)" + } + + return cell + case 1: + let cell = tableView.dequeueReusableCell(withIdentifier: "subTitle", for: indexPath) + cell.textLabel?.text = "Status \(request.reqID): \(request.subID)" + cell.updateStandUI() + if request.closereason == .noError { + cell.detailTextLabel?.text = request.status.description + }else { + cell.detailTextLabel?.text = request.status.description + " " + request.closereason.description + } + + return cell + case 3: + let cell = tableView.dequeueReusableCell(withIdentifier: "subTitle", for: indexPath) + cell.textLabel?.text = "Policy" + cell.updateStandUI() + + let rule = request.rule + + cell.detailTextLabel?.text = "\(rule.policy.description) (\(rule.type.description):\(rule.name) ProxyName:\(rule.proxyName))" + return cell + case 2,4: + let cell:HeaderCell = tableView.dequeueReusableCell(withIdentifier: "req", for: indexPath) as! HeaderCell + if indexPath.row == 2 { + cell.titleLabel.text = "Request Header" + if request.mode == .TCP { + cell.headerLabel.text = "TCP Connection no header" + }else { + if let req = request.reqHeader{ + let result = req.headerString(nil) + cell.headerLabel.text = result + print(result) + }else { + cell.headerLabel.text = "HTTP Request Header Error\r\n" + } + } + + + }else { + cell.titleLabel.text = "Response Header" + if request.mode == .TCP { + cell.headerLabel.text = "TCP Connection no header" + }else { + if let resp = request.respHeader{ + let result = resp.headerString(nil) + cell.headerLabel.text = result + //print(result) + }else { + cell.headerLabel.text = "HTTP Response Header Error\r\n" + } + + } + + } + cell.wwdcStyle() + return cell + case 5: + let cell:TimingCell = tableView.dequeueReusableCell(withIdentifier: "timing", for: indexPath) as! TimingCell + cell.ruleLabel.text = "Rule Testing (\(Int(request.rule.timming*1000)) ms)" + + cell.estLabel.text = "Establish (\(Int(request.connectionTiming*1000)) ms)" + cell.transferLabel.text = "Transfer (\(Int(request.transferTiming*1000)) ms)" + cell.wwdcStyle() + return cell + case 6: + let cell:TrafficCell = tableView.dequeueReusableCell(withIdentifier: "traffic", for: indexPath) as! TrafficCell + cell.txLabel.text = request.traffice.txString() + cell.rxLabel.text = request.traffice.rxString() + cell.wwdcStyle() + return cell + case 7: + let cell:TrafficCell = tableView.dequeueReusableCell(withIdentifier: "ipCell", for: indexPath) as! TrafficCell + if request.interfaceCell == 1 { + cell.txLabel.text = "Local WWAN " + request.localIPaddress + }else { + cell.txLabel.text = "Local WI-FI " + request.localIPaddress + } + cell.wwdcStyle() + cell.rxLabel.text = "Remote " + request.remoteIPaddress + return cell + default: + return UITableViewCell() + } + + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + + + tableView.deselectRow(at: indexPath , animated: true) + if indexPath.row == 0{ + let ux = request.url + var host = "" + if let u = URL(string:ux),let h = u.host{ + host = h + }else { + host = ux + } + alertMessageAction("\(host) copyed ", complete: { + let p = UIPasteboard.general + p.string = host + }) + + } + _ = UIMenuController.shared + + } + func copyAction(sender:AnyObject){ + + } + +} diff --git a/Surf/RuleResultsViewController.swift b/Surf/RuleResultsViewController.swift new file mode 100644 index 0000000..3a9346c --- /dev/null +++ b/Surf/RuleResultsViewController.swift @@ -0,0 +1,284 @@ +// +// RuleResultsViewController.swift +// Surf +// +// Created by abigt on 16/2/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import NetworkExtension +import SwiftyJSON +import SFSocket +class RuleResultsViewController: SFTableViewController { + + var results:[SFRuleResult] = [] + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Rule Test Results" + recent() + //test() + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + let item = UIBarButtonItem.init(image: UIImage.init(named: "760-refresh-3-toolbar"), style: .plain, target: self, action: #selector(RuleResultsViewController.refreshAction(_:))) + self.navigationItem.rightBarButtonItem = item + } + func refreshAction(_ sender:AnyObject){ + recent() + } +// func test() { +// let path = Bundle.main.path(forResource: "1.txt", ofType: nil) +// if let data = try! Data.init(contentsOf: path) { +// processData(data: data) +// } +// } + func recent(){ + // Send a simple IPC message to the provider, handle the response. + //AxLogger.log("send Hello Provider") + if let m = SFVPNManager.shared.manager, m.isEnabled{ + let date = NSDate() + let me = SFVPNXPSCommand.RULERESULT.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8), m.connection.status == .connected + { + do { + try session.sendProviderMessage(message) { [weak self] response in + if response != nil { + self!.processData(data: response!) + } else { + self!.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + alertMessageAction("Failed to Get result ",complete: nil) + } + }else { + alertMessageAction("Connection not Started",complete: nil) + } + }else { + + alertMessageAction("VPN not running",complete: nil) + } + + } + func processData(data:Data) { + results.removeAll() + //let responseString = NSString(data: response!, encoding: NSUTF8StringEncoding) + let obj = JSON.init(data: data) + if obj.error == nil { + if obj.type == .array { + for item in obj { + //{"api.smoot.apple.com":{"Name":"apple.com","Type":"DOMAIN-SUFFIX","Proxy":"jp","Policy":"Proxy"}} + let json = item.1 + + for (k,v) in json { + let rule = SFRuler() + rule.mapObject(v) + //let policy = v["Policy"].stringValue + + let result = SFRuleResult.init(request: k, r: rule) + results.append(result) + } + } + } + if results.count > 0 { + tableView.reloadData() + }else { + alertMessageAction("Don't have Record yet!",complete: nil) + } + + } + //mylog("Received response from the provider: \(responseString)") + //self.registerStatus() + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return results.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "rule", for: indexPath as IndexPath) + + // Configure the cell... + let x = results[indexPath.row] + cell.textLabel?.text = x.req + var proxyName = "" + if x.result.proxyName == "" { + proxyName = x.result.name + }else { + proxyName = x.result.proxyName + } + let timing = String.init(format: " timing: %.04f sec", x.result.timming) + if x.result.type == .final { + + cell.detailTextLabel?.text = x.result.type.description + " " + x.result.policy.description + "->" + proxyName + timing + }else { + cell.detailTextLabel?.text = x.result.type.description + " " + x.result.name + "->" + proxyName + timing + } + cell.updateUI() + + return cell + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + + changeRule() + } + func changeRule() { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + style = .actionSheet + break + + } + guard let indexPath = tableView.indexPathForSelectedRow else {return} + + let result = results[indexPath.row] + let alert = UIAlertController.init(title: "Alert", message: "Please Select Policy", preferredStyle: style) + + let action = UIAlertAction.init(title: "PROXY", style: .default) {[unowned self ] (action:UIAlertAction) -> Void in + + result.result.proxyName = "Proxy" + self.updateResult(rr: result) + self.tableView.deselectRow(at: indexPath, animated: true) + } + let action1 = UIAlertAction.init(title: "REJECT", style: .default) { [unowned self ] (action:UIAlertAction) -> Void in + + result.result.proxyName = "REJECT" + self.updateResult(rr: result) + self.tableView.deselectRow(at: indexPath, animated: true) + + } + let action2 = UIAlertAction.init(title: "DIRECT", style: .default) { [unowned self ] (action:UIAlertAction) -> Void in + + result.result.proxyName = "DIRECT" + self.updateResult(rr: result) + self.tableView.deselectRow(at: indexPath, animated: true) + } + let cancle = UIAlertAction.init(title: "Cancel", style: .cancel) { [unowned self ] (action:UIAlertAction) -> Void in + + self.tableView.deselectRow(at: indexPath, animated: true) + } + alert.addAction(action) + alert.addAction(action1) + alert.addAction(action2) + alert.addAction(cancle) + self.present(alert, animated: true) { () -> Void in + + } + } + func updateResult(rr:SFRuleResult){ + var r:[String:AnyObject] = [:] + r["request"] = rr.req as AnyObject? + r["ruler"] = rr.result.resp() as AnyObject? + + let j = JSON(r) + + + + var data:Data + do { + try data = j.rawData() + }catch let error as NSError { + //AxLogger.log("ruleResultData error \(error.localizedDescription)") + //let x = error.localizedDescription + //data = error.localizedDescription.dataUsingEncoding(NSUTF8StringEncoding)!// NSData() + alertMessageAction("error :\(error.localizedDescription)", complete: { + + }) + return + } + + + + let me = SFVPNXPSCommand.UPDATERULE.rawValue + "|" + var message = Data.init() + message.append(me.data(using: .utf8)!) + + + if let m = SFVPNManager.shared.manager, m.connection.status == .connected { + if let session = m.connection as? NETunnelProviderSession + { + do { + try session.sendProviderMessage(message) { [weak self] response in + if let r = String.init(data: response!, encoding: String.Encoding.utf8) { + print("change policy : \(r)") + //self!.alertMessageAction(r,complete: nil) + + } else { + self!.alertMessageAction("Failed to Change Policy",complete: nil) + } + } + } catch let e as NSError{ + alertMessageAction("Failed to Change Proxy,reason \(e.description)",complete: nil) + } + + } + } + } + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ +} diff --git a/Surf/RuleTableViewController.swift b/Surf/RuleTableViewController.swift new file mode 100644 index 0000000..37600ed --- /dev/null +++ b/Surf/RuleTableViewController.swift @@ -0,0 +1,374 @@ +// +// RuleTableViewController.swift +// Surf +// +// Created by abigt on 16/2/16. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +protocol AddEditRulerDelegate:class { + func addRulerConfig(controller: RuleTableViewController, rule:SFRuler)// + func editRulerConfig(controller: RuleTableViewController, rule:SFRuler,newType:SFRulerType)// +} +class AdvancedCell: UITableViewCell { + @IBOutlet weak var label: UILabel! + @IBOutlet weak var s: UISwitch! + func wwdcStyle(){ + if ProxyGroupSettings.share.wwdcStyle { + label.textColor = UIColor.white + }else { + label.textColor = UIColor.black + } + } +} +let headers:[String] = ["TYPE","VALUE","POLICY","ADVANCE"] +let footersA:[String] = ["","use http user-agent keyword","","test feature"] +let footersB:[String] = ["","Rule matches if the domain of request have suffix,For example: 'google.com' matchs 'google.com','www.google.com'\n Notes: if have two rule: itunes.apple.com,apple.com, request itunes.apple.com will match first because full match higher priority ","","Default remote proxy send dns requst"] +let footersC:[String] = ["","Rule matches if the domain of request contain keyword","","Default remote proxy send dns requst"] +let footersD:[String] = ["","Rule match if the IP address of request in set network","",""] +let footersE:[String] = ["","Rule test use GeoIP Country result","",""] +class RuleTableViewController: SFTableViewController,UITextFieldDelegate,PolicyDelegate,CountryDelegate { + + var config:SFConfig! + var rule:SFRuler? + var type:SFRulerType = .domainkeyword + weak var segControl:UISegmentedControl? + var needAdd:Bool = false + weak var delegate:AddEditRulerDelegate? + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Rule" + self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(barButtonSystemItem: .done, target: self, action: #selector(RuleTableViewController.DoneAction(_:))) + if rule == nil { + rule = SFRuler() + if let p = config.proxys.first { + //rule?.configPolicy(p.proxyName) + rule?.name = p.proxyName + } + needAdd = true + } + type = (rule?.type)! + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + @IBAction func valueChanged2(sender: UISwitch) { + alertMessageAction("not finish",complete: nil) + } + func textFieldDidEndEditing(_ textField: UITextField) { + //valueChanged?(textField) + self.rule?.name = textField.text! + textField.resignFirstResponder() + } + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + self.rule?.name = textField.text! + return true + } + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + + @objc func DoneAction(_ sender:AnyObject) { + + var type:SFRulerType + let index = self.segControl!.selectedSegmentIndex + switch index { + case 0://.DOMAINKEYWORD: + type = .agent + case 1://.IPCIDR: + type = .domainsuffix + case 2://.DOMAINSUFFIX: + type = .domainkeyword + case 3://.GEOIP: + type = .ipcidr + case 4://.AGENT: + type = .geoip + default: + type = .final + break + } + guard let rule = self.rule else{ return} + + if needAdd { + + + rule.type = type + var indexPath = IndexPath.init(row: 0, section: 2) + let cell = tableView.cellForRow(at: indexPath)! as! TwoLableCell + rule.proxyName = cell.cellLabel.text! + + + indexPath = IndexPath.init(row: 0, section: 1) + //crash + if segControl?.selectedSegmentIndex == 4 { + if let cell2 = tableView.cellForRow(at: indexPath){ + rule.name = (cell2.textLabel?.text!)! + + } + }else { + let cell2 = tableView.cellForRow(at: indexPath)! as! TextFieldCell + rule.name = cell2.textField.text! + } + + if rule.name.isEmpty || rule.proxyName.isEmpty { + alertMessageAction("VALUE should not empty",complete: nil) + return + } + delegate?.addRulerConfig(controller: self, rule: rule) + _ = self.navigationController?.popViewController(animated:true) + }else { + rule.type = type + var indexPath = IndexPath.init(row: 0, section: 2) + let cell = tableView.cellForRow(at: indexPath)! as! TwoLableCell + rule.proxyName = cell.cellLabel.text! + + + indexPath = IndexPath.init(row: 0, section: 1) + + if segControl?.selectedSegmentIndex == 4 { + if let cell2 = tableView.cellForRow(at: indexPath){ + rule.name = (cell2.textLabel?.text!)! + + } + }else { + let cell2 = tableView.cellForRow(at: indexPath)! as! TextFieldCell + rule.name = cell2.textField.text! + } + + if rule.name.isEmpty || rule.proxyName.isEmpty { + alertMessageAction("VALUE should not empty",complete: nil) + return + } + delegate?.editRulerConfig(controller: self, rule: rule,newType:type) + _ = self.navigationController?.popViewController(animated:true) + } + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + func modeChanged(sender:UISegmentedControl){ + + } + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + return 3 + } + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 1 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?{ + return headers[section] + } + override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String?{ + //guard let r = rule else {return ""} + var foot:[String] + + switch self.type { + case .domainkeyword: + foot = footersC + case .ipcidr: + foot = footersD + case .domainsuffix: + foot = footersB + case .geoip: + foot = footersE + case .agent: + foot = footersA + default: + foot = footersA + break + } + return foot[section] + } + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + + if indexPath.section == 2 { + return indexPath + }else if indexPath.section == 1 { + if segControl?.selectedSegmentIndex == 4 { + return indexPath + } + } + + return nil + } + @objc func valueChanged(_ sender:UISegmentedControl) { + let index = sender.selectedSegmentIndex + switch index { + case 0://.DOMAINKEYWORD: + type = .agent + case 1://.IPCIDR: + type = .domainsuffix + case 2://.DOMAINSUFFIX: + type = .domainkeyword + case 3://.GEOIP: + type = .ipcidr + case 4://.AGENT: + type = .geoip + default: + break + } + tableView.reloadData() + } + func configSegment(control:UISegmentedControl){ + if control.allTargets.count == 0 { + guard let r = rule else {return} + var index = 0 + switch r.type { + case .domainkeyword: + index = 2 + case .ipcidr: + index = 3 + case .domainsuffix: + index = 1 + case .geoip: + index = 4 + case .agent: + index = 0 + default: + break + } + control.selectedSegmentIndex = index + if control.isEnabled == false { + control.isEnabled = true + control.addTarget(self, action: #selector(RuleTableViewController.valueChanged(_:)), for: .valueChanged) + self.segControl = control + } + tableView.reloadData() + } + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + switch indexPath.section{ + case 0: + let cell = tableView.dequeueReusableCell(withIdentifier: "segment", for: indexPath) as! SegmentCell + configSegment(control: cell.segement) + return cell + case 1: + if segControl?.selectedSegmentIndex == 4 { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) + cell.textLabel?.text = self.rule?.name + cell.textLabel?.textColor = UIColor.white + return cell + }else { + let cell = tableView.dequeueReusableCell(withIdentifier: "textfield-cell", for: indexPath) as! TextFieldCell + cell.textField.text = self.rule?.name + // if cell.valueChanged == nil { + // cell.valueChanged = { [weak self] (textfield:UITextField) -> Void in + // self?.rule?.name = textfield.text! + // } + // } + cell.wwdcStyle() + return cell + } + + case 2: + let cell = tableView.dequeueReusableCell(withIdentifier: "policy", for: indexPath) as! TwoLableCell + if let r = rule { +// if r.proxyName.isEmpty { +// cell.cellLabel.text = r.policy.description +// }else { +// cell.cellLabel.text = r.proxyName +// } + cell.cellLabel.text = r.desc() + + } + cell.wwdcStyle() + return cell + case 3: + let cell = tableView.dequeueReusableCell(withIdentifier: "Advance", for: indexPath) as! AdvancedCell + cell.label.text = "Adv" + cell.label.textColor = UIColor.white + cell.s.isOn = false + return cell + default: + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) + return cell + } + + } + +//selectPolicy + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: IndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: IndexPath, toIndexPath: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // Get the new view controller using segue.destination. + if segue.identifier == "selectPolicy" { + guard let vc = segue.destination as? PolicyViewController else { return } + //guard let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell) else {return } + vc.proxys = config.proxys + vc.delegate = self + vc.oladValue = rule?.proxyName + }else if segue.identifier == "selectCountry" { + guard let vc = segue.destination as? CountrySelectController else { return } + //guard let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell) else {return } + //vc.proxys = config.proxys + vc.delegate = self + //vc.oladValue = rule?.desc() + } + // Pass the selected object to the new view controller. + } + func countrySelected(controller: CountrySelectController, code:String){ + self.rule?.name = code + tableView.reloadData() + } + func editPolicyConfig(controller: PolicyViewController, policy:String){ + rule?.proxyName = policy + tableView.reloadData() + } + +} diff --git a/Surf/RulesTableViewController.swift b/Surf/RulesTableViewController.swift new file mode 100644 index 0000000..4210fdb --- /dev/null +++ b/Surf/RulesTableViewController.swift @@ -0,0 +1,413 @@ +// +// RulesTableViewController.swift +// Surf +// +// Created by 孔祥波 on 16/1/26. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +class RulesTableViewController: SFTableViewController,AddEditRulerDelegate { + var config:SFConfig? + var selectIndex:Int = -1 + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Config rules" + self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(barButtonSystemItem: .add, target: self, action: #selector(RulesTableViewController.AddAction(_:))) + } + @objc func AddAction(_ sender:AnyObject){ + self.performSegue(withIdentifier: "AddRule", sender: sender) + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?{ + + switch section { + case 1: return "DOMAIN-KEYWORD" + case 3: return "IP-CIDR" + case 2: return "DOMAIN-SUFFIX" + case 4: return "GEOIP" + case 5: return "FINAL" + case 0: return "AGENT" + default: + break + } + if section <= 5 { + //let type = SFRulerType(rawValue: section) + //return type?.description + + } + + return "" + } + override func numberOfSections(in tableView: UITableView) -> Int { + return 6 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + + var count = 0 + + if let config = self.config { + switch section{ + case 0: + count = config.agentRuler.count + case 1: + count = config.keyworldRulers.count + case 2: + count = config.sufixRulers.count + case 3: + count = config.ipcidrRulers.count + case 4: + count = config.geoipRulers.count + case 5: + count = 1 + default: + break + } + } + + if count == 0 { + count = 1 + } + + + return count + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + var iden = "rule" + if indexPath.section == 5 { + iden = "ruleFinal" + } + let cell = tableView.dequeueReusableCell(withIdentifier: iden) + cell?.updateStandUI() + + var ruler:SFRuler? + if let config = self.config { + switch indexPath.section{ + case 0: + if config.agentRuler.count <= indexPath.row { + cell?.textLabel?.text = "No user-agent base rule" + return cell! + }else { + ruler = config.agentRuler[indexPath.row] + } + + case 1: + if config.keyworldRulers.count <= indexPath.row { + cell?.textLabel?.text = "No keyword base rule" + return cell! + }else { + ruler = config.keyworldRulers[indexPath.row] + } + + case 2: + if config.sufixRulers.count <= indexPath.row { + cell?.textLabel?.text = "No domain suffix base rule" + return cell! + }else { + ruler = config.sufixRulers[indexPath.row] + } + + case 3: + if config.ipcidrRulers.count <= indexPath.row { + cell?.textLabel?.text = "No ip-cidr base rule" + return cell! + }else { + ruler = config.ipcidrRulers[indexPath.row] + } + + case 4: + if config.geoipRulers.count <= indexPath.row { + cell?.textLabel?.text = "No geoip base rule" + return cell! + }else { + ruler = config.geoipRulers[indexPath.row] + } + + case 5: + ruler = config.finalRuler + default: + + break + } + } + + if let r = ruler { + if r.name.count == 0 { + cell?.textLabel?.text = r.proxyName + + if indexPath.section == 5 { + if r.proxyName == "DIRECT" || r.proxyName == "REJECT" { + cell?.detailTextLabel?.text = r.proxyName + }else { + cell?.detailTextLabel?.text = "PROXY" + } + }else { + if r.proxyName.isEmpty { + cell?.detailTextLabel?.text = r.policy.description + }else { + cell?.detailTextLabel?.text = r.proxyName + } + + } + + }else { + cell?.textLabel?.text = r.name + if indexPath.section == 5 { + cell?.detailTextLabel?.text = r.proxyName + }else { + if r.proxyName.isEmpty { + cell?.detailTextLabel?.text = r.policy.description + }else { + cell?.detailTextLabel?.text = r.proxyName + } + } + + } +// if config!.verifyRules(r) == false { +// cell?.textLabel?.textColor = UIColor.redColor() +// cell?.detailTextLabel?.text = "Don't found \(r.proxyName) in proxy setting,please fixed" +// } + }else { + cell?.textLabel?.text = "rule error" + } + + return cell! + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + if indexPath.section == 5 { + finaleRuleAction() + } + tableView.deselectRow(at: indexPath, animated: true) + } + func finaleRuleAction() { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: "Please Select", preferredStyle: style) + let action = UIAlertAction.init(title: "PROXY", style: .default) {[unowned self ] (action:UIAlertAction) -> Void in +// if let callback = complete { +// callback() +// } + self.config!.finalRuler.proxyName = "PROXY" + self.tableView.reloadSections(NSIndexSet(index:5) as IndexSet, with: .fade) + } + let action1 = UIAlertAction.init(title: "REJECT", style: .default) { [unowned self ] (action:UIAlertAction) -> Void in + // if let callback = complete { + // callback() + // } + self.config!.finalRuler.proxyName = "REJECT" + self.tableView.reloadSections(NSIndexSet(index:5) as IndexSet, with: .fade) + } + let action2 = UIAlertAction.init(title: "DIRECT", style: .default) { [unowned self ] (action:UIAlertAction) -> Void in + // if let callback = complete { + // callback() + // } + self.config!.finalRuler.proxyName = "DIRECT" + //self.config!.finalRuler.proxyName = self.config!.finalRuler.policy.description + self.tableView.reloadSections(NSIndexSet(index:5) as IndexSet, with: .fade) + } + alert.addAction(action) + alert.addAction(action1) + alert.addAction(action2) + self.present(alert, animated: true) { () -> Void in + + } + } + func deleteRuleAtIndexPath(indexPath:IndexPath){ + guard let config = config else {return } + switch indexPath.section { +// ruler = config.agentRuler[indexPath.row] +// case 1: +// ruler = config.keyworldRulers[indexPath.row] +// case 2: +// ruler = config.sufixRulers[indexPath.row] +// case 3: +// ruler = config.ipcidrRulers[indexPath.row] +// case 4: +// ruler = config.geoipRulers[indexPath.row] + case 0: + config.agentRuler.remove(at: indexPath.row) + case 1: + config.keyworldRulers.remove(at: indexPath.row) + case 2: + config.sufixRulers.remove(at: indexPath.row) + case 3: + config.ipcidrRulers.remove(at: indexPath.row) + case 4: + config.geoipRulers.remove(at: indexPath.row) + default: + break + } + tableView.reloadData() + } + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete{ + + //saveProxys() + + deleteRuleAtIndexPath(indexPath: indexPath) + //removeConf(indexPath.row) + //tableView.reloadData() + } + else if editingStyle == .insert{ + + //self.performSegue(withIdentifier:"show-add-controller", sender: nil) + + } + } + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + + guard let config = config else {return false} + switch indexPath.section { + case 5: + return false + case 0: + if config.agentRuler.count > 0 { + return true + } + case 1: + if config.keyworldRulers.count > 0 { + return true + } + case 2: + if config.sufixRulers.count > 0 { + return true + } + case 3: + if config.ipcidrRulers.count > 0 { + return true + } + case 3: + if config.geoipRulers.count > 0 { + return true + } + default: + break + } + return false + } + + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + if let config = self.config { + switch indexPath.section{ + case 0: + if config.agentRuler.count <= indexPath.row { + + return nil + } + + case 1: + if config.keyworldRulers.count <= indexPath.row { + return nil + } + + case 2: + if config.sufixRulers.count <= indexPath.row { + return nil + } + + case 3: + if config.ipcidrRulers.count <= indexPath.row { + return nil + } + + case 4: + if config.geoipRulers.count <= indexPath.row { + return nil + } + + default: + + break + } + } + return indexPath + } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if segue.identifier == "showRule" { + guard let c = segue.destination as? RuleTableViewController else {return} + guard let indexPath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + guard let config = self.config else {return } + var rule:SFRuler + switch indexPath.section{ + case 0: + rule = config.agentRuler[indexPath.row] + case 1: + rule = config.keyworldRulers[indexPath.row] + case 2: + rule = config.sufixRulers[indexPath.row] + case 3: + rule = config.ipcidrRulers[indexPath.row] + case 4: + rule = config.geoipRulers[indexPath.row] + default: + rule = config.finalRuler + + } + selectIndex = indexPath.row + c.rule = rule + c.config = self.config + c.delegate = self + + }else if segue.identifier == "AddRule" { + guard let c = segue.destination as? RuleTableViewController else {return} + c.config = self.config + c.delegate = self + c.delegate = self + } + } + func addRulerConfig(controller: RuleTableViewController, rule:SFRuler){ + self.addRule(rule: rule) + tableView.reloadData() + } + func editRulerConfig(controller: RuleTableViewController, rule:SFRuler, newType:SFRulerType){ + if rule.type != newType { + switch rule.type { + case .domainkeyword: + config!.keyworldRulers.remove(at: selectIndex) + case .ipcidr: + config!.ipcidrRulers.remove(at: selectIndex) + case .domainsuffix: + config!.sufixRulers.remove(at: selectIndex) + case .geoip: + config!.geoipRulers.remove(at: selectIndex) + case .agent: + config!.agentRuler.remove(at: selectIndex) + default: + break + } + selectIndex = -1 + rule.type = newType + self.addRule(rule: rule) + } + tableView.reloadData() + } + func addRule(rule:SFRuler){ + switch rule.type { + case .domainkeyword: + config!.keyworldRulers.append(rule) + case .ipcidr: + config!.ipcidrRulers.append(rule) + case .domainsuffix: + config!.sufixRulers.append(rule) + case .geoip: + config!.geoipRulers.append(rule) + case .agent: + config!.agentRuler.append(rule) + default: + break + } + } +} diff --git a/Surf/SFConfigManager.swift b/Surf/SFConfigManager.swift new file mode 100644 index 0000000..d8c56b4 --- /dev/null +++ b/Surf/SFConfigManager.swift @@ -0,0 +1,259 @@ +// +// SFConfigManager.swift +// Surf +// +// Created by 孔祥波 on 8/20/16. +// Copyright © 2016 abigt. All rights reserved. +// +//这个类给主app 使用 +import Foundation +import SFSocket +import XRuler +class SFConfigManager { + static let manager:SFConfigManager = SFConfigManager() + func loadSettings() { + //加载磁盘上的配置 + } + init(){ + copyConfig() + } + var configs:[SFConfig] = [] + + var selectConfig:SFConfig? { + get { + let c = ProxyGroupSettings.share.config + for cc in configs { + if cc.configName + configExt == c { + return cc + } + } + return nil + + } + set { + + ProxyGroupSettings.share.config = newValue!.configName + configExt + writeToGroup(newValue!.configName) + + try! ProxyGroupSettings.share.save() + + } + } + var icloudSyncEnabled:Bool = false + var storageURL:URL{ + if icloudSyncEnabled { + return applicationDocumentsDirectory + }else { + return applicationDocumentsDirectory + } + } + func copyConfig(){ + let firstOpen = UserDefaults.standard.bool(forKey: "firstOpen") + if firstOpen == false { + let c = ["surf.conf","Default.conf"]//逗比极客精简版.json","逗比极客全能版.json","abclite普通版.json","abclite去广告版.json","surf_main.json" + for f in c { + if let p = Bundle.main.path(forResource: f, ofType: nil){ + //let u = groupContainerURL.appendingPathComponent(f) + let u2 = applicationDocumentsDirectory.appendingPathComponent(f) + do { + // try fm.copyItemAtPath(p, toPath: u.path!) + try fm.copyItem(atPath: p, toPath: u2.path) + }catch let e as NSError { + print("copy config file error \(e)") + } + + } + } + + do { + let surf = "surf" + let p = Bundle.main.path(forResource:surf + ".conf", ofType: nil) + let u2 = groupContainerURL().appendingPathComponent("surf.conf") + // try fm.copyItemAtPath(p, toPath: u.path!) + try fm.copyItem(atPath: p!, toPath: u2.path) + }catch let e as NSError { + print("copy config file error \(e)") + } + + ProxyGroupSettings.share.config = "surf.conf" + UserDefaults.standard.set(true, forKey: "firstOpen") + UserDefaults.standard.synchronize() + }else { + + } + } + + func loadConfigs() { + + if configs.count > 0 { + configs.removeAll() //防止多次进入 + } + let settings = ProxyGroupSettings.share + print(settings.proxys) + //加载配置 + let u = storageURL + + do { + let fns = try fm.contentsOfDirectory(atPath: u.path) + for f in fns { + if f.hasSuffix(".conf") { + let dest = u.appendingPathComponent(f) + let c = SFConfig.init(path:dest.path , loadRule: true) + configs.append(c) + + if f == ProxyGroupSettings.share.config { + selectConfig = c + } + } + } + + } catch let e as NSError { + print(e.localizedDescription) + } + } + + + func reloadConfig(_ name:String){ + // + //重新加载配置,刷新Proxy 信息 + + let fn = name + configExt + let u = storageURL.appendingPathComponent(fn) + let config = SFConfig.init(path:u.path , loadRule: true) + + var found = false + var idx = 0 + for i in 0 ..< configs.count{ + let c = configs[i] + if c.configName == name { + found = true + idx = i + break + + } + } + if found { + //let fn = c.configName + configExt + //removeConfigFile(fn) + configs.remove(at: idx) + configs.insert(config, at: idx) + }else { + configs.append(config) + } + if let s = selectConfig { + if s.configName == name { + selectConfig = config + } + } + //print("\(ProxyGroupSettings.share.config):\(f)") + //if f == ProxyGroupSettings.share.config { + // selectConfig = c + //} + } + func addConfig(_ config:SFConfig) { + configs.append(config) + } + var configCount:Int { + return configs.count + } + func configAtInde(_ index:Int) ->SFConfig { + return configs[index] + } + func delConfig(_ config:SFConfig) { + for i in 0 ..< configs.count{ + let c = configs[i] + if c == config { + let fn = c.configName + configExt + removeConfigFile(fn) + configs.remove(at: i) + } + } + } + func delConfigAtIndex(_ index:Int) { + if index < configs.count { + let c = configs[index] + let fn = c.configName + configExt + removeConfigFile(fn) + configs.remove(at: index) + } + } + func removeConfigFile(_ fn:String){ + let u = storageURL.appendingPathComponent(fn) + do { + + try fm.removeItem(at: u) + }catch let e as NSError { + print("error :\(e.localizedDescription)") + } + } + func writeConfig(_ config:SFConfig) { + //将某个config 写入文件 + } + func urlForConfig(_ config:SFConfig) ->URL { + let fn = config.configName + configExt + let u = storageURL.appendingPathComponent(fn) + return u + } + + func writeToGroup(_ configName:String) { + + let fn = configName + configExt + do { + let p = storageURL.appendingPathComponent(fn) + let u2 = groupContainerURL().appendingPathComponent(fn) + + + // try fm.copyItemAtPath(p, toPath: u.path!) + if fm.fileExists(atPath: u2.path) { + try fm.removeItem(atPath: u2.path) + } + + try fm.copyItem(atPath: p.path, toPath: u2.path) + + }catch let e as NSError { + print("copy config file error \(e)") + } + } + func selectedIndex() ->Int{ + //缺省0 + var r = 0 + + let fn = ProxyGroupSettings.share.config + if !fn.isEmpty { + for x in configs { + let fnx = x.configName + configExt + if fnx == fn { + break + } + r += 1 + } + } + + + + + return r + } + func addRule(_ r:SFRuler) ->Bool{ + //从rule test result 添加 + var result = false + if let s = selectConfig{ + if r.type == .ipcidr { + s.ipcidrRulers.append(r) + result = true + }else if r.type == .domainsuffix { + + s.sufixRulers.append(r) + result = true + }else { + + } + + if result { + writeConfig(s) + } + } + + return result + } +} diff --git a/Surf/SFConfigViewController.swift b/Surf/SFConfigViewController.swift new file mode 100644 index 0000000..c56e2e2 --- /dev/null +++ b/Surf/SFConfigViewController.swift @@ -0,0 +1,989 @@ +// +// FirstViewController.swift +// Surf +// +// Created by abigt on 15/11/20. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit +import Alamofire +import NetworkExtension +import Darwin +import SFSocket +import XRuler +/// Make NEVPNStatus convertible to a string +func toUint(signed: Int8) -> UInt8 { + + let unsigned = signed >= 0 ? + UInt8(signed) : + UInt8(signed - Int8.min) + UInt8(Int8.max) + 1 + + return unsigned +} +class SFConfigListViewController : SFTableViewController ,ConfigTableViewControllerDelegate,AddFileDelegate,BarcodeScanDelegate{ + + //var proxyArray = [NSDictionary]() + /// The target VPN configuration. + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + self.navigationController?.tabBarItem.title = "Rules".localized + self.title = "Rules".localized + } + open override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { + let v = view as! UITableViewHeaderFooterView + if ProxyGroupSettings.share.wwdcStyle { + v.contentView.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + }else { + v.contentView.backgroundColor = UIColor.groupTableViewBackground + } + + } + open override func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int){ + let v = view as! UITableViewHeaderFooterView + if ProxyGroupSettings.share.wwdcStyle { + v.contentView.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + }else { + v.contentView.backgroundColor = UIColor.groupTableViewBackground + } + + } + + + //weak var startStopButton:UIButton? + //var proxyList:NSMutableArray = NSMutableArray() + //var proxyServerList:[String:SFProxy] = [:] + var selectPath:IndexPath? + //var hostIP:[String:String] = [:] + //var configFiles:[String:SFConfig] = [:] //filename,desc + //var files:[String] = [] + + //var selectConf:String = "" + var importList = ["New Empty Configuration","New Configuration with Default rules","Copy from iTunes File sharing","Download From URL","Import Config use iCloud"] + //var proVersion:Bool = false + + var proxyGroupEnable:Bool = false + + + func copyiTunsShareing(config:String) ->Bool { + + let url = applicationDocumentsDirectory.appendingPathComponent(config) + let urlDst = groupContainerURL().appendingPathComponent(config) + // 需要验证格式吗? + if fm.fileExists(atPath: urlDst.path){ + try! fm.removeItem(atPath: urlDst.path) + } + + do { + try fm.copyItem(atPath: url.path, toPath: urlDst.path) + try fm.removeItem(atPath: url.path) + + }catch let error { + mylog("copy \(error)") + return false + } + return true + } + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat{ + return 48 + } + func copyExampleConfigAndDefault() throws { + let path = Bundle.main.path(forResource: sampleConfig, ofType: nil) + let url = applicationDocumentsDirectory.appendingPathComponent(sampleConfig) + + + _ = Bundle.main.path(forResource: DefaultConfig, ofType: nil) + let urlDst = groupContainerURL().appendingPathComponent(DefaultConfig) + + do { + try copyFile(URL.init(fileURLWithPath: path!) , dst: urlDst , forceCopy: false) + } catch let error { + //mylog("copy \(error)") + throw error + } + + do { + try copyFile(URL.init(fileURLWithPath: path!) , dst: url, forceCopy: true) + } catch let error { + //mylog("copy \(error)") + throw error + } + + + } + +// func loadConfigSummery(fName:String){ +// let q = dispatch_queue_create("com.abigt.config", nil) +// dispatch_async(q){[weak self] in +// if let StrongSelf = self{ +// let configURL = applicationDocumentsDirectory.appendingPathComponent(fName) +// let config:SFConfig = SFConfig.init(path: configURL!.path!,loadRule:false) +// //let count = config.keyworldRulers.count + config.ipcidrRulers.count + config.sufixRulers.count + config.geoipRulers.count + config.agentRuler.count + 1 +// //var flag = "" +// if let p = config.proxys.first { +// +// //StrongSelf.proxyServerList[fName] = p +// //print("### \(flag) \(p.serverAddress)") +// } +// +// for p in config.proxys { +// ProxyGroupSettings.share.addProxy(p) +// } +// +// +// //StrongSelf.configFiles[fName] = config +// dispatch_async(dispatch_get_main_queue()){ [weak self ] in +// if let StrongSelf = self{ +// StrongSelf.tableView.reloadData() +// +// } +// +// } +// +// +// } +// +// } +// +// } + + func loadConfigs() { + //when add,edit,del need refresh + + + + } + /// Unwind segue handler. + @IBAction func handleUnwind(sender: UIStoryboardSegue) { + } + + + /// Handle the event where the view is being hidden. + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + // Stop watching for status change notifications. + //removeObserver() + } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + tableView.reloadData() + //registerStatus() + // Re-load all of the configurations. + + } + func removeObserver() { + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: SFVPNManager.shared.manager?.connection) + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + } + override func viewDidLoad() { + super.viewDidLoad() + //copySampleConfig() + self.title = "Rules".localized + + + //self.tableView.allowsSelectionDuringEditing = true + self.tableView.allowsMultipleSelectionDuringEditing = false + tableView.separatorInset=UIEdgeInsetsMake(0,50, 0, 0); + //navigationItem.rightBarButtonItem = editButtonItem() + tableView.delegate = self + + + + + let btn = UIButton.init(type: .custom) + btn.frame = CGRect(x:0,y: 0, width:22, height: 22) + btn.tintColor = UIColor.blue + btn.setImage(UIImage.init(named: "704-compose-selected")?.withRenderingMode(.alwaysTemplate), for: .highlighted) + btn.setImage(UIImage.init(named: "704-compose-toolbar")?.withRenderingMode(.alwaysTemplate), for: .normal) + btn.addTarget(self, action: #selector(SFConfigListViewController.textMode(_:)), for: .touchUpInside) + btn.tintColor = UIColor.white + navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView: btn) + // let scan = UIBarButtonItem.init(title: "Check", style: .Plain, target: self, action: #selector(ProxyGroupViewController.showScan(_:))) + // let ritems:[UIBarButtonItem] = [scan,done] + + + + + + //NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "testrpc", userInfo: nil, repeats: true) + + + // Do any additional setup after loading the view, typically from a nib. + + proxyGroupEnable = UserDefaults.standard.bool(forKey: kProxyGroup) + + + let edit = UIBarButtonItem.init(barButtonSystemItem: .add, target: self, action: #selector(SFConfigListViewController.showAlertCC(_:))) + navigationItem.rightBarButtonItem = edit + } + @objc func textMode(_ sender:AnyObject) { + let vc = self.storyboard!.instantiateViewController(withIdentifier: "editView") + self.navigationController?.pushViewController(vc, animated: true) + //self.performSegue(withIdentifier: "showConfigEdit", sender: sender) + } + @objc func showAlertCC(_ sender:AnyObject) { + if !verifyReceipt(.Rule) { + changeToBuyPage() + } + + var style:UIAlertControllerStyle = .actionSheet + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + + + //let str = importList[index] + //["New Empty Configuration","New Empty Configuration with Default rules","Copy from iTunes File sharing",] + // switch index { + +// case 0: +// let iden = "showConfig" +// self.performSegue(withIdentifier:iden, sender: tableView.cellForRowAtIndexPath(indexPath)) +// case 1: +// let iden = "showConfig" +// self.performSegue(withIdentifier:iden, sender: tableView.cellForRowAtIndexPath(indexPath)) +// case 2: +// showiTunesFileSelector() +// case 3: +// activeBarCodeScan() +// case 4: +// showIcloudmenu() + + + + + let alert = UIAlertController.init(title: "Select", message: nil, preferredStyle: style) + let action = UIAlertAction.init(title: "New Empty Configuration", style: .default) { [weak self ](action:UIAlertAction) -> Void in + let iden = "showConfig" + self!.performSegue(withIdentifier:iden, sender: "Default") + } + alert.addAction(action) + let action1 = UIAlertAction.init(title: "New Configuration with Default rules", style: .default) {[weak self] (action:UIAlertAction) -> Void in + let iden = "showConfig" + self!.performSegue(withIdentifier: iden, sender: nil) + } + alert.addAction(action1) + + + let action2 = UIAlertAction.init(title: "Copy from iTunes File sharing", style: .default) { [weak self ](action:UIAlertAction) -> Void in + + self!.showiTunesFileSelector() + } + alert.addAction(action2) + let action3 = UIAlertAction.init(title: "Download From URL", style: .default) {[weak self] (action:UIAlertAction) -> Void in + + self!.activeBarCodeScan() + } + alert.addAction(action3) + + + let action4 = UIAlertAction.init(title: "Import Config use iCloud", style: .default) {[weak self] (action:UIAlertAction) -> Void in + + self!.showIcloudmenu() + } + alert.addAction(action4) + + let action5 = UIAlertAction.init(title: "Cancel", style: .cancel) {(action:UIAlertAction) -> Void in + + //self!.showIcloudmenu() + } + alert.addAction(action5) + + self.present(alert, animated: true) { () -> Void in + + } + + } + @IBAction func done(_ sender:AnyObject?){ + self.dismiss(animated: true){ + + } + + } + func testrpc() { + SFVPNManager.shared.xpc() + } + + + + /// Handle the event of the view being displayed. + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + +// override func setEditing(editing: Bool, animated: Bool) { +// super.setEditing(editing, animated: animated) +// tableView.setEditing(editing, animated: animated) +// +// tableView.reloadData() +// +// } + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if section == 0 { + let count = SFConfigManager.manager.configCount + if count > 0 { + + return count + }else { + return 1 //alert cell + } + + }else{ +// if tableView.editing == true { +// return importList.count +// } +// return 1; + return importList.count + } + + } + +// @IBAction func startConnect(sender: AnyObject) { +// startStopButton = sender as? UIButton +// startStopToggled(sender) +// } + @IBAction func proxyGroupAction(_ sender:UISwitch){ + self.proxyGroupEnable = sender.isOn + UserDefaults.standard.set(sender.isOn, forKey: kProxyGroup) + do { + try ProxyGroupSettings.share.save() + UserDefaults.standard.synchronize() + }catch let e as NSError{ + alertMessageAction(e.description, complete: nil) + } + + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + + switch indexPath.section{ +// case 0: +// if indexPath.row == 0 { +// let itemCell = tableView.dequeueReusableCellWithIdentifier("mode-select") +// return itemCell! +// }else { +// let itemCell = tableView.dequeueReusableCellWithIdentifier("proxy-group") as! ProxyCell +// itemCell.enableSwitch.on = proxyGroupEnable +// return itemCell +// } + case 0: + //let s = proxyList.objectAtIndex(indexPath.row) as! Socks + + guard let itemCell = tableView.dequeueReusableCell(withIdentifier: "proxy-group") else{ + let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "citem-cell") + cell.textLabel?.text = "Load cell error" + + cell.updateStandUI() + cell.accessoryType = UITableViewCellAccessoryType.detailButton + + + return cell + } + let proxyCell = itemCell as! CountryCustomProxyCell + proxyCell.accessoryType = UITableViewCellAccessoryType.detailButton + let count = SFConfigManager.manager.configCount + proxyCell.wwdcStyle() + + if count > 0 { + let config = SFConfigManager.manager.configAtInde(indexPath.row) + //mylog(fp) + proxyCell.proxyLabel?.text = config.configName + + proxyCell.countryLabel?.text = "" + + + proxyCell.subLabel?.text = config.description() + + + + //todo display much info + //itemCell.checkMarkView.hidden = true + //let selectConfig = ProxyGroupSettings.share.config + + var isSelect:Bool = false + if selectPath == indexPath { + isSelect = true + }else{ + let idx = SFConfigManager.manager.selectedIndex() + if indexPath.row == idx{ + selectPath = indexPath + isSelect = true + } + } + if isSelect { + print("isSelect") + proxyCell.countryLabel?.text = "\u{f383}" + //proxyCell.proxyLabel.textColor = UIColor.cyanColor() + //proxyCell.subLabel.textColor = UIColor.cyanColor() + //updateStatus(proxyCell) + }else { + //proxyCell.proxyLabel.textColor = UIColor.blackColor() + //proxyCell.subLabel.textColor = UIColor.blackColor() + } + }else { + let alertMessage = "No Valid Configration found please add" + proxyCell.proxyLabel?.text = alertMessage + proxyCell.countryLabel?.text = "" + proxyCell.subLabel?.text = "" + } + return itemCell + + + case 1: + if !tableView.isEditing{ + let row = indexPath.row + let desc = importList[row] + guard let addItemCell = tableView.dequeueReusableCell(withIdentifier: "add-item") else{ + let cell = UITableViewCell(style: .default, reuseIdentifier: "add-item") + cell.textLabel?.text = desc + cell.accessoryType = UITableViewCellAccessoryType.detailButton + return cell + } + let c = addItemCell as! ActionsCell + c.myLabel.text = desc + return c; + + }else { + guard let _ = tableView.dequeueReusableCell(withIdentifier: "start-item") else { + return UITableViewCell(style: .default, reuseIdentifier: "start-item") + } + + //self.startStopButton = startItemCell.contentView.viewWithTag(1) as? UIButton + //updateStatus(nil) + //return startItemCell + } + + default: + break + + } + + + return UITableViewCell() + } + + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + + // if self.editing { +// return true +// }else { +// return false +// } + + return true + } + override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { + + if indexPath.section == 0 { + let count = SFConfigManager.manager.configCount + if count > 0 { + + let iden = "show-add-controller" + + self.performSegue(withIdentifier: iden, sender: tableView.cellForRow(at: indexPath)) + + } + } + + } + override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { + + if indexPath.section == 0 { + return .delete + }else { + return .none + } + + + + } + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?{ + if section == 0{ + return "" + }else { + if tableView.isEditing { + return "Add Config Method" + } + + } + return nil + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + + tableView.deselectRow(at: indexPath as IndexPath, animated: true) + let count = SFConfigManager.manager.configCount + if indexPath.section == 0 { + if count > 0 { + let last = selectPath + selectPath = indexPath + let config = SFConfigManager.manager.configs[indexPath.row] + SFConfigManager.manager.selectConfig = config + + + if let _ = SFVPNManager.shared.manager { + //SFVPNManager.shared.enabledToggled(false) + //registerStatus() + }else { + //self.loadManager() + } + self.dismiss(animated: true){ + + } + if let l = last { + tableView.reloadRows(at: [l,indexPath], with: .none) + }else { + tableView.reloadRows(at: [indexPath], with: .none) + } + + + + }else { + //configActions(indexPath) + alertMessageAction("Please Add Config Use below Choices",complete: nil) + } + + }else{ + configActions(indexPath: indexPath) + } + } + func configActions(indexPath:IndexPath) { + let index = indexPath.row + //let str = importList[index] + //["New Empty Configuration","New Empty Configuration with Default rules","Copy from iTunes File sharing",] + switch index { + + case 0: + let iden = "showConfig" + self.performSegue(withIdentifier: iden, sender: tableView.cellForRow(at: indexPath )) + case 1: + let iden = "showConfig" + self.performSegue(withIdentifier: iden, sender: tableView.cellForRow(at: indexPath)) + case 2: + showiTunesFileSelector() + case 3: + activeBarCodeScan() + case 4: + showIcloudmenu() + default: + break + } + } + func downloadFile(urlBase64:String) ->Bool{ + + //let utf8str = urlBase64.dataUsingEncoding(NSUTF8StringEncoding) + var urlString:String = "" + if urlBase64.range(of: "http") != nil { + urlString = urlBase64 + let r = urlString.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) + + var fn:String + if let url = URL.init(string: r!){ + fn = url.lastPathComponent + if !fn.hasSuffix(".conf"){ + fn += ".conf" + } + }else { + fn = "20070109.conf" + } + let tempURL = applicationDocumentsDirectory.appendingPathComponent(fn) + //alertMessageAction("fixme", complete: nil) + Alamofire.request(r!, method: .get, parameters: nil, encoding:URLEncoding.default , headers: nil) + //request(.GET, r, parameters: nil) + .validate(statusCode: 200..<300) + //.validate(contentType: ["application/txt"]) + + .response { [weak self ] response in + //print(response) + + + if let d = response.data { + if fm.fileExists(atPath:tempURL.path) { + try! fm.removeItem(at: tempURL) + } + try! d.write(to:tempURL) + + DispatchQueue.main.async(){ + + SFConfigManager.manager.loadConfigs() + self!.tableView.reloadData() + } + } + + + } + }else { + if let data = Data.init(base64Encoded: urlBase64, options: .ignoreUnknownCharacters) { + if let str = String.init(data: data , encoding: String.Encoding.utf8) { + urlString = str + + let r = urlString.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) + + Alamofire.request(r!, method: .get, parameters: nil, encoding:URLEncoding.default , headers: nil) + .responseData{[weak self ] response in + + if let _ = response.result.value { + + var fn:String + if let url = NSURL.init(string: r!){ + fn = url.lastPathComponent! + }else { + fn = "20070109" + } + if fn.range(of:configExt) == nil { + fn = fn + configExt + } + self!.writeJSONData(data: response.data!,withName:fn) + self!.alertMessageAction("\(String(describing: r)) Downlowd success!",complete: nil) + }else { + self!.alertMessageAction("\(String(describing: r)) Downlowd failure! reason \(response.result.error.debugDescription)",complete: nil) + } + } + + } + + } + } + + //let resultString = + + //print("url \(resultString)") + //let x = "http://192.168.2.125/jp.json" + + + return true + } + func writeJSONData(data:Data, withName name:String){ + let dest = groupContainerURL().appendingPathComponent(name) + try! data.write(to: dest) + SFConfigManager.manager.loadConfigs() + tableView.reloadData() + } + func activeBarCodeScan() { + + + var style:UIAlertControllerStyle = .actionSheet + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: "Select", preferredStyle: style) + let action = UIAlertAction.init(title: "Use QrCode", style: .default) { [weak self ](action:UIAlertAction) -> Void in + self!.performSegue(withIdentifier: "showBarCode", sender: nil) + } + alert.addAction(action) + let action1 = UIAlertAction.init(title: "Input URL", style: .default) {[weak self] (action:UIAlertAction) -> Void in + self!.inputURL() + } + alert.addAction(action1) + self.present(alert, animated: true) { () -> Void in + + } + + + } + func inputURL(){ + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Input URL:", message: "http(s)://domainname.com/abigt.conf", preferredStyle: style) + + let action = UIAlertAction.init(title: "OK", style: .default) { [weak self ](action:UIAlertAction) -> Void in + if let field = alert.textFields?.first, !field.text!.isEmpty { + + _ = self!.downloadFile(urlBase64: field.text!) + }else { + + } + + } + alert.addTextField { (textfield) -> Void in + + } + alert.addAction(action) + let action1 = UIAlertAction.init(title: "Cancel", style: .default) {(action:UIAlertAction) -> Void in + + } + alert.addAction(action1) + self.present(alert, animated: true) { () -> Void in + + } + + } + func barcodeScanDidScan(controller: BarcodeScanViewController, configString:String){ + if self.presentedViewController == controller { + self.dismiss(animated: true, completion: { () -> Void in + + }) + + } + + if downloadFile(urlBase64: configString) == false { + alertMessageAction("\(configString) Invilad,Base64 Decode Error", complete: nil) + } + } + func barcodeScanCancelScan(controller: BarcodeScanViewController){ + if self.presentedViewController == controller { + self.dismiss(animated: true, completion: { () -> Void in + + }) + + } + } + func showiTunesFileSelector(){ + let iden = "showiTunesFiles" + self.performSegue(withIdentifier: iden, sender: nil) + } + + + func removeConf(index:Int) { + + if let s = selectPath { + if s.row == index{ + selectPath = nil + } + } + + SFConfigManager.manager.delConfigAtIndex(index) + + + } + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + + if editingStyle == .delete{ + + //saveProxys() + + removeConf(index: indexPath.row) + tableView.reloadData() + } + else if editingStyle == .insert{ + + self.performSegue(withIdentifier: "show-add-controller", sender: nil) + + } + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if segue.identifier == "show-add-controller"{ + guard let addEditController = segue.destination as? ConfigTableViewController else{return} + guard let indexPath = self.tableView.indexPath(for: sender as! UITableViewCell) else {return } + addEditController.navigationItem.title = "Edit Config" + let config = SFConfigManager.manager.configs[indexPath.row] + addEditController.config = config + addEditController.mode = .Edit + addEditController.delegate = self + }else if segue.identifier == "showConfig"{ + + guard let addEditController = segue.destination as? ConfigTableViewController else{return} +// guard let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell) else {return } +// if indexPath.row == 0 { +// addEditController.mode = .NewDefault +// }else { +// addEditController.mode = .NewDefaultRule +// } + if let _ = sender{ + addEditController.mode = .NewDefault + }else { + addEditController.mode = .NewDefaultRule + } + + addEditController.delegate = self + + addEditController.navigationItem.title = "Add Config" + + }else if segue.identifier == "showiTunesFiles" { + guard let nvc = segue.destination as? UINavigationController else {return } + let vc = nvc.viewControllers.first as! iTunesFileTableViewController + vc.delegate = self + }else if segue.identifier == "showBarCode"{ + guard let barCodeController = segue.destination as? BarcodeScanViewController else{return} + + barCodeController.delegate = self + //barCodeController.navigationItem.title = "Add Proxy" + + }else if segue.identifier == "showOndemand" { + guard let _ = segue.destination as? OndemandController else{return} + + } + + } + func importFileConfig(controller: iTunesFileTableViewController, config:String){ + self.dismiss(animated: true) { () -> Void in + + } + if copyiTunsShareing(config: config) { + SFConfigManager.manager.loadConfigs() + tableView.reloadData() + + } + } + func cancelSelect(controller: iTunesFileTableViewController){ + self.dismiss(animated: true) { () -> Void in + + } + } + func saveConfig(controller: ConfigTableViewController, config:String,edit:Bool){ + if !edit { + SFConfigManager.manager.loadConfigs() + //loadConfigSummery(config + configExt) + //files.append(config+configExt) +// loadConfigSummery(config + configExt) + }else { + SFConfigManager.manager.loadConfigs() + //loadConfigSummery(config + configExt) + } + self.tableView.reloadData() + } +} +extension SFConfigListViewController: UIDocumentPickerDelegate{//UIDocumentMenuDelegate + func showIcloudmenu() { +// let importMenu = UIDocumentMenuViewController.init(documentTypes: [configExt], inMode: .Import) +// importMenu.delegate = self +// self.present(importMenu, animated: true) { () -> Void in +// +// } + //kUTTypeJSON + let picker = UIDocumentPickerViewController.init(documentTypes: ["public.item","public.text"], in: .import) + picker.delegate = self + self.present(picker, animated: true) { () -> Void in + + } + } +// internal func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) +// { +// self.dismissViewControllerAnimated(true) { () -> Void in +// +// } +// } +// +// +// internal func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController){ +// self.dismissViewControllerAnimated(true) { () -> Void in +// +// } +// } + internal func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL){ + +// self.dismissViewControllerAnimated(false) { () -> Void in +// } + let path = url.path + if path.hasSuffix(".conf"){ + let fn = path.components(separatedBy: "/").last! + let tempURL = applicationDocumentsDirectory.appendingPathComponent(fn) + do { + try fm.copyItem(at: url, to: tempURL) + } catch let e { + alertMessageAction("Copy File Error:\(e.localizedDescription)", complete: nil) + } + + SFConfigManager.manager.loadConfigs() + self.tableView.reloadData() + + }else { +// let fn = path.components(separatedBy: "/").last! +// let config = SFConfig.init(path: path, loadRule: false) +// if config.loadResult { +// do { +// try copyFile(url, dst: groupContainerURL().appendingPathComponent(fn), forceCopy: true) +// self.loadConfigs() +// self.tableView.reloadData() +// }catch let error as NSError{ +// +// self.alertMessageAction(error.debugDescription,complete: nil) +// } +// +// +// }else { +// self.alertMessageAction("Config File format Invalid",complete: nil) +// } + + } + + } + + + internal func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController){ +// self.dismissViewControllerAnimated(true) { () -> Void in +// +// } + } + +} +class CustomProxyCell: UITableViewCell{ + + @IBOutlet weak var checkMarkView: UIImageView! + @IBOutlet weak var myLabel:UILabel! + override func awakeFromNib() { + super.awakeFromNib() + self.checkMarkView.isHidden = true + + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + } +} +class ActionsCell :UITableViewCell{ + @IBOutlet weak var myLabel:UILabel! + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + } + override func willTransition(to s: UITableViewCellStateMask) { + super.willTransition(to: s) + //self.state = s; + } +} +class ImageActionCell: UITableViewCell { + @IBOutlet weak var btnImageView:UIImageView! +} +class CountryCustomProxyCell: UITableViewCell{ + @IBOutlet weak var proxyLabel:UILabel! + @IBOutlet weak var countryLabel:UILabel! + @IBOutlet weak var subLabel:UILabel! + + func wwdcStyle(){ + if ProxyGroupSettings.share.wwdcStyle { + proxyLabel.textColor = UIColor.white + countryLabel.textColor = UIColor.white + subLabel.textColor = UIColor.lightGray + }else { + proxyLabel.textColor = UIColor.darkText + + subLabel.textColor = UIColor.lightGray + countryLabel.textColor = UIColor.init(red: 0x0b/255.0, green: 0x60/255.0, blue: 0xb1/255.0, alpha: 1.0) + } + } +} diff --git a/Surf/SFCountry.swift b/Surf/SFCountry.swift new file mode 100644 index 0000000..778d9c6 --- /dev/null +++ b/Surf/SFCountry.swift @@ -0,0 +1,98 @@ +// +// SFCountry.swift +// Surf +// +// Created by abigt on 16/3/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation +import SwiftyJSON +import MMDB +import AxLogger +class CData { + var code = "" + var emoji = "" + init(c:String,e:String){ + code = c + emoji = e + } +} + +class Country { + var db:MMDB? + //var data:JSON? + var list:[String:CData] = [:] + static let setting:Country = { + let c = Country() + if let path = Bundle.main.path(forResource:"data.json", ofType: nil) { + let d = try! Data.init(contentsOf: URL.init(fileURLWithPath: path)) + let data = try! JSON(data: d) + if data.error == nil { + for (k,v) in data { + let code = v["code"].stringValue + let e = v["emoji"].stringValue + let x = CData.init(c: code, e: e) + c.list[code] = x + //print("\(code),\(e)") + } + }else { + //fatalError() + if let error = data.error { + print("\(error)") + } + + } + + + + }else { + fatalError() + } + + return c + }() + func createdb()->Bool{ + //return false + //for main app + #if os(iOS) + let p = Bundle.main.bundlePath + "/Frameworks/MMDB.framework/" + #else + let p = Bundle.main.bundlePath + "/Contents/Frameworks/MMDB.framework/" + #endif + guard let b = Bundle.init(path: p) else {return false } + guard let path = b.path(forResource:"GeoLite2-Country.mmdb", ofType: nil) else {return false} + + // + + + guard let d = MMDB(path) else { + AxLogger.log("failed to open Geo db",level: .Error) + return false + } + db = d + return true + + } + + func geoIPRule(ipString:String) -> (emoji:String,isoCode:String){ + var haveDB = true + if db == nil { + if !createdb(){ + haveDB = false + } + } + if haveDB{ + if let country:MMDBCountry = db!.lookup(ipString){ + let isoCode = country.isoCode + if let result = list[isoCode] { + return (result.emoji,isoCode) + } + return ("",isoCode) + }else { + return ("","") + } + } + return ("","") + } +} diff --git a/Surf/SFDocumentPickerViewController.swift b/Surf/SFDocumentPickerViewController.swift new file mode 100644 index 0000000..6d494ee --- /dev/null +++ b/Surf/SFDocumentPickerViewController.swift @@ -0,0 +1,20 @@ +// +// File.swift +// Surf +// +// Created by abigt on 16/2/5. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation +import UIKit +class SFDocumentPickerViewController:UIDocumentPickerViewController { + override init(documentTypes allowedUTIs: [String], in mode: UIDocumentPickerMode) { + super.init(documentTypes: allowedUTIs, in: mode) + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + //fatalError("init(coder:) has not been implemented") + } +} diff --git a/Surf/SFInterfaceTraffic.swift b/Surf/SFInterfaceTraffic.swift new file mode 100644 index 0000000..12a7d73 --- /dev/null +++ b/Surf/SFInterfaceTraffic.swift @@ -0,0 +1,164 @@ +// +// SFInterfaceTraffic.swift +// Surf +// +// Created by 孔祥波 on 7/7/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import Foundation +import CFNetwork +import Darwin +import SFSocket +import XRuler +//if let p = ipaddr where p == "240.7.1.9" { + +//} +struct SFInterfaceTraffic { + + var WiFiSent:UInt = 0; + var WiFiReceived:UInt = 0; + var WWANSent:UInt = 0; + var WWANReceived:UInt = 0; + var TunSent:UInt = 0; + var TunReceived:UInt = 0; + +} +func getIFAddresses() -> [NetInfo] { + var addresses = [NetInfo]() + //let d0 = NSDate() + // Get list of all interfaces on the local machine: + var ifaddr : UnsafeMutablePointer? = nil + if getifaddrs(&ifaddr) == 0 { + + // For each interface ... + var ptr = ifaddr + while( ptr != nil) { + + let flags = Int32((ptr?.pointee.ifa_flags)!) + var addr = ptr?.pointee.ifa_addr.pointee + + // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. + if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { + if addr?.sa_family == UInt8(AF_INET) || addr?.sa_family == UInt8(AF_INET6) { + + // Convert interface address to a human readable string: + var hostname = [CChar](repeating: 0, count: Int(256))//NI_MAXHOST + if (getnameinfo(&addr!, socklen_t((addr?.sa_len)!), &hostname, socklen_t(hostname.count), + nil, socklen_t(0), NI_NUMERICHOST) == 0) { + if let address = String.init(cString: hostname, encoding: .utf8) { + + + let name = ptr?.pointee.ifa_name + let ifname = String.init(cString: name!, encoding: .utf8) + + // var x = NSMutableData.init(length: Int(strlen(name))) + // let p = UnsafeMutablePointer.init((x?.bytes)!) + // memcpy(p, name, Int(strlen(name))) + //print(ifname) + var net = ptr?.pointee.ifa_netmask.pointee + var netmaskName = [CChar](repeating: 0, count: Int(NI_MAXHOST)) + getnameinfo(&net!, socklen_t((net?.sa_len)!), &netmaskName, socklen_t(netmaskName.count), + nil, socklen_t(0), NI_NUMERICHOST) + if let netmask = String.init(cString: netmaskName, encoding: .utf8) { + if address.count > 15 { + let net = NetInfo(ip: "2001:470:4a34:ee00:d80a:882c:100:0", netmask: netmask,ifName:ifname!) + addresses.append(net) + }else { + let net = NetInfo(ip: address, netmask: netmask,ifName:ifname!) + addresses.append(net) + } + + //addresses[ifname!] = address + } + } + } + } + } + ptr = ptr?.pointee.ifa_next + } + freeifaddrs(ifaddr) + } + //let d1 = NSDate() + //print("\(d1.timeIntervalSinceDate(d0))") + return addresses +} +func showStart() ->Bool{ + let x = getIFAddresses() + for xx in x { + if xx.ip == "240.7.1.9" { + return true + } + } + return false + +} +func abigtTunIP() ->String?{ + let x = getIFAddresses() + for xx in x { + if xx.ip == "240.7.1.9" { + return xx.ifName + } + } + return nil + +} +//last:SFInterfaceTraffic +func getInterfaceTraffic() -> SFInterfaceTraffic { + var ifaddr : UnsafeMutablePointer? = nil + var t = SFInterfaceTraffic() + guard let tunName = abigtTunIP() else {return t} + if getifaddrs(&ifaddr) == 0 { + + // For each interface ... + var ptr = ifaddr + while( ptr != nil) { + + let flags = Int32((ptr?.pointee.ifa_flags)!) + let addr = ptr?.pointee.ifa_addr.pointee + + // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. + if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { + if addr?.sa_family == UInt8(AF_LINK) { + + // Convert interface address to a human readable string: + let name = ptr?.pointee.ifa_name + let ifname = String.init(cString: name!) + let networkData: UnsafeMutablePointer = unsafeBitCast(ptr!.pointee.ifa_data,to: UnsafeMutablePointer.self) + + //var ipaddr:String? +// var hostname = [CChar](count: Int(256), repeatedValue: 0)//NI_MAXHOST +// if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count), +// nil, socklen_t(0), NI_NUMERICHOST) == 0) { +// if let address = String.fromCString(hostname){ +// ipaddr = address +// } +// } + + + + if ifname.hasPrefix("en") { + t.WiFiReceived = UInt(networkData.pointee.ifi_ibytes) + t.WiFiSent = UInt(networkData.pointee.ifi_obytes) + }else if ifname.hasPrefix("pdp_ip") { + t.WWANReceived = UInt(networkData.pointee.ifi_ibytes) + t.WWANSent = UInt(networkData.pointee.ifi_obytes) + }else if ifname == tunName {//hasPrefix("utun") + + t.TunReceived = UInt(networkData.pointee.ifi_ibytes) + t.TunSent = UInt(networkData.pointee.ifi_obytes) + } + + + + } + } + ptr = ptr?.pointee.ifa_next + } + freeifaddrs(ifaddr) + } + //let d1 = NSDate() + + //print("\(d1.timeIntervalSinceDate(d0))") + return t +} diff --git a/Surf/SFLog.swift b/Surf/SFLog.swift new file mode 100644 index 0000000..2e04142 --- /dev/null +++ b/Surf/SFLog.swift @@ -0,0 +1,18 @@ +// +// SFLog.swift +// Surf +// +// Created by 孔祥波 on 16/2/9. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation + +//public func mylog(object: T, _ file: String = #file, _ function: String = #function, _ line: Int = #line) { +// //let fn = file.split { $0 == "/" }.last +// let fn = file.characters.split { $0 == "/" }.map(String.init).last +// if let f = fn { +// let info = "\(f).\(function)[\(line)]:\(object)" +// NSLog(info) +// } +//} diff --git a/Surf/SFMethodViewController.swift b/Surf/SFMethodViewController.swift new file mode 100644 index 0000000..691964a --- /dev/null +++ b/Surf/SFMethodViewController.swift @@ -0,0 +1,109 @@ +// +// SFMethodViewController.swift +// Surf +// +// Created by 孔祥波 on 8/24/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +protocol SFMethodDelegate:class { + func didSelectMethod(controller: SFMethodViewController, method:String)// +} +class SFMethodViewController: SFTableViewController { + weak var delegate:SFMethodDelegate? + override func viewDidLoad() { + super.viewDidLoad() + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return supported_ciphers.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + // Configure the cell... + let cell = tableView.dequeueReusableCell(withIdentifier: "method", for: indexPath) + cell.updateStandUI() + + cell.textLabel?.text = supported_ciphers[indexPath.row] + return cell + } + + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: false) + let method = supported_ciphers[indexPath.row] + self.delegate?.didSelectMethod(controller: self, method: method) + + _ = self.navigationController?.popViewController(animated: true) + } + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/SFNavigationController.swift b/Surf/SFNavigationController.swift new file mode 100644 index 0000000..c441fcd --- /dev/null +++ b/Surf/SFNavigationController.swift @@ -0,0 +1,37 @@ +// +// SFNavigationController.swift +// Surf +// +// Created by 孔祥波 on 21/02/2017. +// Copyright © 2017 abigt. All rights reserved. +// + +import UIKit + +class SFNavigationController: UINavigationController { + open override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/SFRuleHelper.swift b/Surf/SFRuleHelper.swift new file mode 100644 index 0000000..6ba30be --- /dev/null +++ b/Surf/SFRuleHelper.swift @@ -0,0 +1,298 @@ +// +// SFRuleHelper.swift +// Surf +// +// Created by 孔祥波 on 16/5/4. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation + + +import Foundation +//import SQLite + + + + + +class SFRuleHelper{ + static let shared = SFRuleHelper() + var db:Connection? + func testimport(){ + let p = Bundle.main.path(forResource:"rules_public.conf", ofType: nil) + open("rule8.db", readonly: false) + if let path = p { + let content = try! NSString.init(contentsOfFile: path, encoding: NSUTF8StringEncoding) + let x = content.components(separatedBy: "\n") + for item in x { + let r = SFRuler() + if item.hasPrefix("DOMAIN-KEYWORD"){ + //print("Keyword rule") + r.type = .DOMAINKEYWORD + let x2 = item.components(separatedBy: ",") + r.name = x2[1].trimmingCharacters(in: .whitespacesAndNewlines) + r.proxyName = x2[2].trimmingCharacters(in: .whitespacesAndNewlines) + + }else if item.hasPrefix("DOMAIN-SUFFIX") || item.hasPrefix("DOMAIN"){ + //print(" DOMAIN Keyword rule") + let x2 = item.components(separatedBy: ",") + r.name = x2[1].trimmingCharacters(in: .whitespacesAndNewlines) + + r.proxyName = x2[2].trimmingCharacters(in: .whitespacesAndNewlines) + + r.type = .DOMAINSUFFIX + }else if item.hasPrefix("GEOIP"){ + //print("GEOIP Keyword rule") + r.type = .GEOIP + let x2 = item.components(separatedBy: ",") + r.name = x2[1].trimmingCharacters(in: .whitespacesAndNewlines) + + r.proxyName = x2[2].trimmingCharacters(in: .whitespacesAndNewlines) + + }else if item.hasPrefix("IP-CIDR"){ + //print(" IP-CIDR Keyword rule") + r.type = .IPCIDR + let x2 = item.components(separatedBy: ",") + r.name = x2[1].trimmingCharacters(in: .whitespacesAndNewlines) + + r.proxyName = x2[2].trimmingCharacters(in: .whitespacesAndNewlines) + + }else if item.hasPrefix("FINAL"){ + //print("Final Keyword rule") + r.type = .FINAL + let x2 = item.components(separatedBy: ",") + r.name = FINAL//x2[1].stringByTrimmingCharactersInSet( + //NSCharacterSet.whitespaceAndNewlineCharacterSet()) + + r.proxyName = x2[1].trimmingCharacters(in: .whitespacesAndNewlines) + + } + + if !r.name.isEmpty && !r.proxyName.isEmpty{ + print("RULE: " + r.name + " \(r.type.description) " + r.proxyName) + saveRuler(r) + } + } + } + } + func open(path:String,readonly:Bool){ + + // if let d = db { + // //db. + // } +// let t = NSDate().timeIntervalSince1970 +// var fn:String +// if path.isEmpty { +// fn = String.init(format:"%.0f.sqlite", t) +// }else { +// fn = path +// } + + //let url0 = applicationDocumentsDirectory.appendingPathComponent(fn) + let url = groupContainerURL().appendingPathComponent(path) +// do{ +// try fm.copyItemAtURL(url0, toURL: url) +// }catch let e as NSError{ +// print(e) +// } + + if let p = url.path { + do { + db = try Connection(p,readonly: readonly) + + //initDatabase(db!) + }catch let e as NSError{ + logStream.write("open db error \(e.description)") + + } + } + + } + + func initDatabase(db:Connection) { + let bId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String + if bId == "com.abigt.Surf" { +// let rules = Table("rules") +// + +// let name = Expression("name")//domain or IP/mask +// +// let type = Expression("type") +// let policy = Expression("policy") +// +// let proxyName = Expression("proxyName") + + do { + try db.run(rules.create { t in + t.column(id, primaryKey: .Autoincrement) + t.column(name,unique: true)//, + t.column(type) + t.column(policy) + t.column(proxyName) + }) + }catch let e as NSError { + print(e.description) + } + + }else { + debugLog("don't need init db") + } + } + func saveRuler(ruler:SFRuler) { + if ruler.name.isEmpty { + return + } + if let d = db { + do { + let rules = Table("rules") + + //let id = Expression("id") +// let name = Expression("name")//domain or IP/mask +// +// let type = Expression("type") +// let policy = Expression("policy") +// let proxyName = Expression("proxyName") + + + try d.run( + rules.insert( + name <- ruler.name, + type <- ruler.typeId, + policy <- ruler.policyId, + proxyName <- ruler.proxyName + + ) + //"INSERT OR REPLACE INTO rules (name, type, policy) " + + //"VALUES (?, ?, ?)", ruler.name, ruler.typeId, ruler.policyId + ) + } catch let _ as NSError { + AxLogger.log("insert error ") + } + + }else { + //logStream.write("open db error \(e.description)") + AxLogger.log("insert error no db") + } + } + func openForApp(){ + var fns:[String] = [] + //if db == nil { + let p = groupContainerURL().path + let files = try! FileManager.default.contentsOfDirectoryAtPath(p!) + + for file in files { + if file.containsString(".sqlite") { + // let url = groupContainerURL.appendingPathComponent(file) + // fns.append(url.path!) + fns.append(file) + } + // let url = groupContainerURL.appendingPathComponent("Log/"+file) + // let att = try! fm.attributesOfItemAtPath(url.path!) + // let d = att["NSFileCreationDate"] as! NSDate + // let size = att["NSFileSize"]! as! NSNumber + // let fn = SFFILE.init(n: file, d: d,size:size.longLongValue) + // self!.fileList.append(fn) + // self!.fileList.sortInPlace({ $0.date.compare($1.date) == NSComparisonResult.OrderedDescending }) + } + + //} + let x = fns.removeLast() + if !x.isEmpty { + open(x,readonly: true) + } + for fx in fns { + let url = groupContainerURL().appendingPathComponent(fx) + let destURL = applicationDocumentsDirectory.appendingPathComponent(fx) + do { + try fm.moveItemAtURL(url, toURL: destURL) + }catch let e as NSError { + print(e.description) + } + } + + } + func query(t:Int64,nameFilter:String) -> [SFRuler] { + var result:[SFRuler] = [] + + + + var dbx:Connection! + if let db = db { + dbx = db + }else { + return result + } + do { + //requests.order([start.asc]) + //rules.filter(type == 1) + var query:AnySequence //= try dbx.prepare(rules.filter(type == t)) + if nameFilter.isEmpty { + query = try dbx.prepare(rules.filter(type == t)) + }else { + query = try dbx.prepare(rules.filter(type == t).filter( name == nameFilter)) + } + for row in query { + let req = SFRuler() + req.name = row[name] + //print(row[url]) + //print(row[url]) + if let t = SFRulerType(rawValue:Int(row[type])) { + req.type = t + } + + req.pWith(row[policy]) + req.proxyName = row[proxyName] + AxLogger.log("###### host:\(req.name) ip:\(req.proxyName) \(req.type.description) \(nameFilter)") + result.append(req) + + } + }catch let e as NSError{ + print(e) + } + + return result + } + + func query(domainName:String) -> [SFRuler] { + var result:[SFRuler] = [] + +// let rules = Table("rules") +// let name = Expression("name")//domain or IP/mask +// +// let type = Expression("type") +// let policy = Expression("policy") + + + var dbx:Connection! + if let db = db { + dbx = db + }else { + return result + } + do { + //requests.order([start.asc]) + //rules.filter(type == 1) + let query = try dbx.prepare(rules.filter(type == 2).filter( name == domainName)) + for row in query { + let req = SFRuler() + req.name = row[name] + //print(row[url]) + //print(row[url]) + if let t = SFRulerType(rawValue:Int(row[type])) { + req.type = t + } + + req.pWith(row[policy]) + print("###### \(req.name) \(req.proxyName) \(req.type.description)") + result.append(req) + + } + }catch let e as NSError{ + print(e) + } + + return result + } + +} diff --git a/Surf/SFRuleWriter.swift b/Surf/SFRuleWriter.swift new file mode 100644 index 0000000..2c6ea13 --- /dev/null +++ b/Surf/SFRuleWriter.swift @@ -0,0 +1,28 @@ +// +// SFRuleWriter.swift +// Surf +// +// Created by 孔祥波 on 16/5/8. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation + +//import SQLite +//let rules = Table("rules") +// +//let id = Expression("id") +//let name = Expression("name")//domain or IP/mask +// +//let type = Expression("type") +//let policy = Expression("policy") +//let proxyName = Expression("proxyName") + +class SFRuleWriter { + + + + + + +} diff --git a/Surf/SFTableViewCell.swift b/Surf/SFTableViewCell.swift new file mode 100644 index 0000000..fe53565 --- /dev/null +++ b/Surf/SFTableViewCell.swift @@ -0,0 +1,26 @@ +// +// SFTableViewCell.swift +// Surf +// +// Created by 孔祥波 on 21/02/2017. +// Copyright © 2017 abigt. All rights reserved. +// + +import UIKit + +class SFTableViewCell: UITableViewCell { + + static let textcolor = UIColor.white + static let textcolorW = UIColor.black + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/Surf/SFTableViewController.swift b/Surf/SFTableViewController.swift new file mode 100644 index 0000000..55259c5 --- /dev/null +++ b/Surf/SFTableViewController.swift @@ -0,0 +1,282 @@ +// +// SFTableViewController.swift +// Surf +// +// Created by abigt on 16/2/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +import SwiftyStoreKit +enum RegisteredPurchase: String { + + case KCP + case HTTP + case Rule + case Analyze + case Pro + case VIP + case OneGB //1GB 不限流量 + //case 30D + case nonConsumablePurchase + case consumablePurchase + case autoRenewablePurchase + case nonRenewingPurchase +} +open class SFTableViewController: UITableViewController { + let appBundleId = "com.abigt.Surf" + + func dataForShare(filePath:URL?) ->Data? { + guard let u = filePath else { + return nil + } + do { + let data = try Data.init(contentsOf: u) + return data + }catch let e { + print(e.localizedDescription) + } + return nil + } + func messageForProductRetrievalInfo(_ result: RetrieveResults) -> String { + + if let product = result.retrievedProducts.first { + let priceString = product.localizedPrice! + return " \(product.localizedTitle) - \(priceString)" + } else if let invalidProductId = result.invalidProductIDs.first { + return "Could not retrieve product info" + " Invalid product identifier: \(invalidProductId)" + } else { + let errorString = result.error?.localizedDescription ?? "Unknown error. Please contact support" + return "Could not retrieve product info " + errorString + } + + } + + func alertMessageAction(_ message:String,complete:(() -> Void)?) { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: message, preferredStyle: style) + let action = UIAlertAction.init(title: "OK", style: .default) { (action:UIAlertAction) -> Void in + if let callback = complete { + callback() + } + } + let actionCancel = UIAlertAction.init(title: "Cancel", style: .default) { (action:UIAlertAction) -> Void in + + } + alert.addAction(action) + alert.addAction(actionCancel) + self.present(alert, animated: true) { () -> Void in + + } + } + + func alertMessageAction(_ message:String) { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: message, preferredStyle: style) + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + alert.dismiss(animated: false, completion: nil) + } + self.present(alert, animated: true) { () -> Void in + + } + } + + + + open override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + func shareAirDropURL(_ u:URL,name:String) { + if !FileManager.default.fileExists(atPath: u.path) { + return + } + let dest = URL.init(fileURLWithPath: NSTemporaryDirectory()+name) + do { + try FileManager.default.copyItem(at: u, to: dest) + }catch let e { + print(e.localizedDescription) + } + let controller = UIActivityViewController(activityItems: [dest],applicationActivities:nil) + if let actv = controller.popoverPresentationController { + actv.barButtonItem = self.navigationItem.rightBarButtonItem + actv.sourceView = self.view + } + controller.completionWithItemsHandler = { (type,complete,items,error) in + do { + try FileManager.default.removeItem(at: dest) + }catch let e { + print(e.localizedDescription) + } + + } + + self.present(controller, animated: true) { () -> Void in + } + } + override open func viewDidLoad() { + super.viewDidLoad() + NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "themeChanged"), object: nil, queue: OperationQueue.main) {[weak self] (noti) in + if let strong = self { + strong.refreshTheme() + } + } + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + func refreshTheme(){ + let blackStyle = ProxyGroupSettings.share.wwdcStyle + if blackStyle { + let color3 = UIColor.init(red: 0x26/255.0, green: 0x28/255.0, blue: 0x32/255.0, alpha: 1.0) + self.tableView.backgroundColor = color3 + }else { + self.tableView.backgroundColor = UIColor.groupTableViewBackground + } + self.tableView.reloadData() + } + override open func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + refreshTheme() + } +// override public func didReceiveMemoryWarning() { +// super.didReceiveMemoryWarning() +// // Dispose of any resources that can be recreated. +// } +// +// // MARK: - Table view data source +// +// override public func numberOfSectionsInTableView(tableView: UITableView) -> Int { +// // #warning Incomplete implementation, return the number of sections +// return 0 +// } +// +// override public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { +// // #warning Incomplete implementation, return the number of rows +// return 0 +// } + + /* + override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ +// override open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { +// return " " +// } +// override open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { +// return " " +// } + open override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { + let v = view as! UITableViewHeaderFooterView + if ProxyGroupSettings.share.wwdcStyle { + v.contentView.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + }else { + v.contentView.backgroundColor = UIColor.groupTableViewBackground + } + + } + open override func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int){ + let v = view as! UITableViewHeaderFooterView + if ProxyGroupSettings.share.wwdcStyle { + v.contentView.backgroundColor = UIColor.init(red: 0x2d/255.0, green: 0x30/255.0, blue: 0x3b/255.0, alpha: 1.0) + }else { + v.contentView.backgroundColor = UIColor.groupTableViewBackground + } + + } + func alertWithTitle(_ title: String, message: String) -> UIAlertController { + + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + return alert + } + func showAlert(_ alert: UIAlertController) { + guard self.presentedViewController != nil else { + self.present(alert, animated: true, completion: nil) + return + } + } + func alertForRestorePurchases(_ results: RestoreResults) -> UIAlertController { + + if results.restoreFailedPurchases.count > 0 { + print("Restore Failed: \(results.restoreFailedPurchases)") + return alertWithTitle("Restore failed", message: "Unknown error. Please contact support") + } else if results.restoredPurchases.count > 0 { + print("Restore Success: \(results.restoredPurchases)") + return alertWithTitle("Purchases Restored", message: "All purchases have been restored") + } else { + print("Nothing to Restore") + return alertWithTitle("Nothing to restore", message: "No previous purchases were found") + } + } + +} diff --git a/Surf/SFVPNManager.swift b/Surf/SFVPNManager.swift new file mode 100644 index 0000000..d0f22db --- /dev/null +++ b/Surf/SFVPNManager.swift @@ -0,0 +1,412 @@ +// +// SFVPNManager.swift +// Surf +// +// Created by abigt on 16/2/5. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation +import NetworkExtension +import SFSocket +import XRuler +extension NEVPNStatus: CustomStringConvertible { + public var description: String { + switch self { + case .disconnected: return "Disconnected" + case .invalid: return "Invalid" + case .connected: return "Connected" + case .connecting: return "Connecting" + case .disconnecting: return "Disconnecting" + case .reasserting: return "Reconnecting" + } + } + public var titleForButton:String { + switch self{ + case .disconnected: + + return "Connect" + case .invalid: + return "Invalid" + case .connected: + return "Disconnect" + case .connecting: + return "Connecting" + case .disconnecting: + return "Disconnecting" + case .reasserting: + return "Reasserting" + } + } +} + + +class SFNETunnelProviderManager:NETunnelProviderManager { + //var pluginType:String = "com.abigt.Surf" + class func loadOrCreateDefaultWithCompletionHandler(_ completionHandler: ((NETunnelProviderManager?, Error?) -> Void)?) { + self.loadAllFromPreferences { (managers, error) -> Void in + if let error = error { + print("Error: Could not load managers: \(error.localizedDescription)") + if let completionHandler = completionHandler { + completionHandler(nil, error) + } + return + } + let bId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String + if let managers = managers { + if managers.indices ~= 0 { + if let completionHandler = completionHandler { + var m:NETunnelProviderManager? + for mm in managers { + let _ = mm.protocolConfiguration as! NETunnelProviderProtocol + + + } + + + if m == nil { + m = managers[0] + } + print("manager \(managers.count) \(String(describing: m?.protocolConfiguration))") + completionHandler(m, nil) + + + + } + return + } + } + + let config = NETunnelProviderProtocol() + config.providerConfiguration = ["App": bId,"PluginType":"com.abigt.Surf"] + #if os(iOS) + + config.providerBundleIdentifier = "com.abigt.Surf4.PacketTunnel" + #else + config.providerBundleIdentifier = "com.abigt.Surf.mac.extension" + #endif + config.serverAddress = "240.84.1.24" + + let manager = SFNETunnelProviderManager() + manager.protocolConfiguration = config + if bId == "com.abigt.Surf" { + manager.localizedDescription = "Surfing" + }else { + manager.localizedDescription = "Surfing Today" + } + + //manager.setPluginType("com.abigt.Surf") + // manager. +// manager.onDemandEnabled = true +// manager.onDemandRules = [NEOnDemandRule]() +// +// let newRule = NEOnDemandRuleEvaluateConnection() +// +// //newRule.DNSSearchDomainMatch = domains +// var rules = [NEEvaluateConnectionRule]() +// let r = NEEvaluateConnectionRule.init(matchDomains: domains, andAction: .ConnectIfNeeded) +// +// rules.append(r) +// newRule.connectionRules? = rules +// newRule.interfaceTypeMatch = .Any +// manager.onDemandRules?.append(newRule) + + manager.saveToPreferences(completionHandler: { (error) -> Void in + if let completionHandler = completionHandler { + + completionHandler(manager, error) + } + }) + } + } +} + + +class SFVPNManager { + static let shared:SFVPNManager = SFVPNManager() + var manager:NETunnelProviderManager? + var proVersion:String = "" + var config:String = "" + var loading:Bool = false + var session:String = "" + var vpnmanager:NEVPNManager = NEVPNManager.shared() + func loadVPNManager(_ completionHandler: @escaping (Error?) -> Void){ + vpnmanager.loadFromPreferences { (error) -> Void in + completionHandler(error) + } + } + + func saveVPNManger(_ completionHandler: ((Error?) -> Void)?) { + if vpnmanager.isEnabled == false{ + vpnmanager.isEnabled = true + vpnmanager.saveToPreferences(completionHandler: { (error) in + completionHandler!(error) + }) + + } else { + completionHandler!(nil) + } + } + func startStopVPNConnect() throws { + let c = vpnmanager.connection + if c.status == .disconnected || c.status == .invalid { + if c.status == .disconnected { + + do { + let conf = ProxyGroupSettings.share.config + try c.startVPNTunnel(options: [kConfig:conf as NSObject,kPro:proVersion as NSObject]) + }catch let e as NSError { + throw e + } + + }else { + c.stopVPNTunnel() + } + } + } + func loadManager(_ completionHandler: ((NETunnelProviderManager?, Error?) -> Void)?) { + + if let m = manager { + if let handler = completionHandler{ + handler(m, nil) + } + + //self.xpc() + }else { + loading = true + SFNETunnelProviderManager.loadOrCreateDefaultWithCompletionHandler { [weak self] (manager, error) -> Void in + if let m = manager { + self!.manager = manager + if let handler = completionHandler{ + if m.onDemandRules == nil { + //self!.addOnDemandRule([]) + } + self!.loading = false + handler(m, error) + } + } + + + // self!.registerStatus() + // self!.xpc() + // if self!.manager.enabled == false { + // self!.enabledToggled(false) + // } + // self!.tableView.reloadData() + // mylog("\(self!.manager.protocolConfiguration)") + } + } + } + func xpc(){ + // Send a simple IPC message to the provider, handle the response. + //AxLogger.log("send Hello Provider") + if let m = manager { + let me = SFVPNXPSCommand.HELLO.rawValue + "|Hello Provider" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8), m.connection.status != .invalid + { + do { + try session.sendProviderMessage(message) { response in + if let response = response { + if let responseString = String.init(data:response , encoding: .utf8){ + let list = responseString.components(separatedBy: ":") + self.session = list.last! + print("Received response from the provider: \(responseString)") + } + + //self.registerStatus() + } else { + print("Got a nil response from the provider") + } + } + } catch { + print("Failed to send a message to the provider") + } + } + }else { + print("message dont init") + } + + } + /// De-register for configuration change notifications. + /// Handle the user toggling the "enabled" switch. + func test(_ domains:[String],enable:Bool,wifiEnable:Bool){ + var onDemandRules = [NEOnDemandRule]() + let newRule = NEOnDemandRuleEvaluateConnection() + var connectionRules:[NEEvaluateConnectionRule] = [] + //print(newRule.connectionRules) + //newRule.DNSSearchDomainMatch = domains + + let r:NEEvaluateConnectionRule = NEEvaluateConnectionRule.init(matchDomains: domains, andAction: .connectIfNeeded) + + if wifiEnable { + newRule.interfaceTypeMatch = .any + }else { + #if os(iOS) + newRule.interfaceTypeMatch = .cellular + #else + newRule.interfaceTypeMatch = .any + #endif + + + } + connectionRules.append(r) + newRule.connectionRules = connectionRules + newRule.interfaceTypeMatch = .any + + + + onDemandRules.append(newRule) + print(onDemandRules) + } + func test2(_ domains:[String],enable:Bool,wifiEnable:Bool) { + + var onDemandRules = [NEOnDemandRule]() + + + let newRule = NEOnDemandRuleConnect() + + newRule.dnsSearchDomainMatch = domains + + if wifiEnable { + newRule.interfaceTypeMatch = .any + }else { + #if os(iOS) + newRule.interfaceTypeMatch = .cellular + #else + newRule.interfaceTypeMatch = .any + #endif + //newRule.interfaceTypeMatch = .Cellular + } + + onDemandRules.append(newRule) + print(onDemandRules) + + + } + func addOnDemandRule(_ domains:[String],wifiEnable:Bool,enable:Bool,completion: ((Error?) -> Void)?){ + if let m = manager { + + var onDemandRules = [NEOnDemandRule]() + let newRule = NEOnDemandRuleEvaluateConnection() + var connectionRules:[NEEvaluateConnectionRule] = [] + //print(newRule.connectionRules) + //newRule.DNSSearchDomainMatch = domains + + let r:NEEvaluateConnectionRule = NEEvaluateConnectionRule.init(matchDomains: domains, andAction: .connectIfNeeded) + + if wifiEnable { + newRule.interfaceTypeMatch = .any + }else { + #if os(iOS) + newRule.interfaceTypeMatch = .cellular + #else + newRule.interfaceTypeMatch = .any + #endif + //newRule.interfaceTypeMatch = .Cellular + } + if connectionRules.count > 0 { + connectionRules.removeAll() + } + connectionRules.append(r) + newRule.connectionRules = connectionRules + + + + + onDemandRules.append(newRule) + print(onDemandRules) + + + m.onDemandRules = onDemandRules + m.isOnDemandEnabled = enable + //fixme + m.saveToPreferences(completionHandler: { (error) -> Void in + if let completion = completion { + completion(error) + } + }) + + + } + + } + func enabledToggled(_ start:Bool) { + if let m = manager { + m.isEnabled = true + let bId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String + if bId == "com.abigt.Surf" { + m.localizedDescription = "Surfing" + }else { + m.localizedDescription = "Surfing Today" + } + m.saveToPreferences { error in + guard error == nil else { + //self.enabledSwitch.on = self.targetManager.enabled + //self.startStopToggle.enabled = self.enabledSwitch.on + print("show update status") + + return + } + + + m.loadFromPreferences { error in + //self.enabledSwitch.on = self.targetManager.enabled + //self.startStopToggle.enabled = self.enabledSwitch.on + print("loadFromPreferencesWithCompletionHandler \(String(describing: error?.localizedDescription))") + // self!.tableView.reloadData() + if start { + do { + _ = try self.startStopToggled(self.config) + }catch let error { + print(error) + } + + } + + } + + } + } + + } + /// Handle the user toggling the "VPN" switch. + func startStopToggled(_ config:String) throws ->Bool{ + if let m = manager { + self.config = config + if self.config.isEmpty{ + self.config = ProxyGroupSettings.share.config + } + if m.connection.status == .disconnected || m.connection.status == .invalid { + do { + + if m.isEnabled { + let u = groupContainerURL() + let path = u.path + print("starting!!! path:\(u)") + try m.connection.startVPNTunnel(options: [kConfig:config as NSString,kPro:proVersion as NSObject,kPath:path as NSString]) + + + + + + }else { + enabledToggled(true) + } + } + catch let error { + throw error + //mylog("Failed to start the VPN: \(error)") + } + } + else { + print("stoping!!!") + m.connection.stopVPNTunnel() + } + }else { + + return false + } + return true + } +} diff --git a/Surf/SFVerify.swift b/Surf/SFVerify.swift new file mode 100644 index 0000000..cd062d9 --- /dev/null +++ b/Surf/SFVerify.swift @@ -0,0 +1,299 @@ +// +// SFVerify.swift +// Surf +// +// Created by abigt on 2017/6/15. +// Copyright © 2017年 abigt. All rights reserved. +// + +import Foundation +import StoreKit +import SwiftyStoreKit +import ObjectMapper +import SFSocket +import XRuler +extension SFTableViewController { + func getProductInfo(_ purchase: RegisteredPurchase,complete:@escaping ((String) -> Void)) { + + NetworkActivityIndicatorManager.networkOperationStarted() + SwiftyStoreKit.retrieveProductsInfo([appBundleId + "." + purchase.rawValue]) { result in + NetworkActivityIndicatorManager.networkOperationFinished() + complete(self.messageForProductRetrievalInfo(result)) + //self.showAlert(self.alertForProductRetrievalInfo(result)) + } + } + //验证产品购买情况 + func verifyReceipt(_ product:RegisteredPurchase = RegisteredPurchase.Pro) ->Bool{ + + if (Int(appBuild())! % 2) != 0 { + return true + } + if product == .Pro { + if findPurchase(product) { + return true + }else { + verifyProduct(product, result: { t in + print("222 verifyReceiptBuy \(product.rawValue)") + if t { + if product == .Pro { + + print("pro version \(t) \(product.rawValue)") + } + + }else { + print("not pro version \(product.rawValue)") + } + }) + + return false + } + }else { + return findPurchase(product) + } + + + + + } + func findPurchase(_ product:RegisteredPurchase = RegisteredPurchase.Pro) ->Bool { + + if let receipt = ProxyGroupSettings.share.receipt { + for inapp in receipt.in_app { + print("inapp buy \(inapp.product_id)") + if inapp.product_id == "com.abigt.Surf." + product.rawValue || inapp.product_id == "com.abigt.Surf.Pro"{ + print("version buy version > 3.2 ,buy") + return true + //break + } + } + + if let purchase_ms = Int64(receipt.original_purchase_date_ms) { + if purchase_ms < 1498088100000 { + + return true + } + } + + let buyversion = receipt.original_application_version.components(separatedBy: ".") + let localversion = "3.2".components(separatedBy: ".") + var purched = false + for (idx,item) in buyversion.enumerated() { + + + if idx < localversion.count { + let x = localversion[idx] + if Int(x)! > Int(item)! { + print("version buy \(x) item:\(item)") + purched = true + break + }else { + continue + } + }else { + + + break + } + } + + return purched + + + + } + + + + return false + } + func verifyProduct(_ product:RegisteredPurchase = RegisteredPurchase.Pro,result: @escaping (Bool) ->Void) { + // guard let u = Bundle.main.appStoreReceiptURL else {return } + // do { + // let data = try Data.init(contentsOf: u) + // print(" record \(data)") + // }catch let e { + // print("nobuy record") + // } + NetworkActivityIndicatorManager.networkOperationStarted() + verifyReceipt { appresult in + NetworkActivityIndicatorManager.networkOperationFinished() + //self.showAlert(self.alertForVerifyReceipt(result)) + switch appresult { + case .success(let receipt): + print("Verify receipt Success: \(receipt)") + NSLog("%@", receipt) + let r = Mapper().map(JSON: receipt) + if let rr = r?.receipt { + do { + try ProxyGroupSettings.share.saveReceipt(rr) + }catch let e { + print("\(e.localizedDescription)") + } + + //按版本,不是购买时间3.2 以后免费 + let buyversion = rr.original_application_version.components(separatedBy: ".") + let localversion = "3.2".components(separatedBy: ".") + var purched = false + for (idx,item) in buyversion.enumerated() { + + + if idx < localversion.count { + let x = localversion[idx] + if Int(x)! > Int(item)! { + + purched = true + break + }else { + continue + } + }else { + + + break + } + } + if purched { + result(purched) + return + }else { + for inapp in rr.in_app { + print("inapp buy \(inapp.product_id)") + if inapp.product_id == "com.abigt.Surf." + product.rawValue { + print("version buy version > 3.2 ,buy") + purched = true + break + } + } + } + result(purched) + }else { + result(false) + } + + case .error(let error): + print("Verify receipt Failed: \(error)") + var alert:UIAlertController + switch error { + case .noReceiptData: + alert = self.alertWithTitle("Receipt verification", message: "No receipt data. Try again.") + + case .networkError(let error): + alert = self.alertWithTitle("Receipt verification", message: "Network error while verifying receipt: \(error)") + + default: + alert = self.alertWithTitle("Receipt verification", message: "Receipt verification failed: \(error)") + } + self.showAlert(alert) + } + + } + } + func verifyReceipt(completion: @escaping (VerifyReceiptResult) -> Void) { + + let appleValidator = AppleReceiptValidator(service: .production) + let password = "e09dbf3ea2454af4bb5f55c8a5d00d8c" + SwiftyStoreKit.verifyReceipt(using: appleValidator, forceRefresh: true, completion: completion) + } + func changeToBuyPage() { + let vc = UIStoryboard.init(name: "buy", bundle: nil).instantiateInitialViewController()! + self.navigationController?.pushViewController(vc, animated: true) + } + + + + + + + + func alertForProductRetrievalInfo(_ result: RetrieveResults) -> UIAlertController { + + if let product = result.retrievedProducts.first { + let priceString = product.localizedPrice! + return alertWithTitle(product.localizedTitle, message: "\(product.localizedDescription) - \(priceString)") + } else if let invalidProductId = result.invalidProductIDs.first { + return alertWithTitle("Could not retrieve product info", message: "Invalid product identifier: \(invalidProductId)") + } else { + let errorString = result.error?.localizedDescription ?? "Unknown error. Please contact support" + return alertWithTitle("Could not retrieve product info", message: errorString) + } + } + + // swiftlint:disable cyclomatic_complexity + func alertForPurchaseResult(_ result: PurchaseResult) -> UIAlertController? { + switch result { + case .success(let purchase): + print("Purchase Success: \(purchase.productId)") + return alertWithTitle("Thank You", message: "Purchase completed") + case .error(let error): + print("Purchase Failed: \(error)") + switch error.code { + case .unknown: return alertWithTitle("Purchase failed", message: "Unknown error. Please contact support") + case .clientInvalid: // client is not allowed to issue the request, etc. + return alertWithTitle("Purchase failed", message: "Not allowed to make the payment") + case .paymentCancelled: // user cancelled the request, etc. + return nil + case .paymentInvalid: // purchase identifier was invalid, etc. + return alertWithTitle("Purchase failed", message: "The purchase identifier was invalid") + case .paymentNotAllowed: // this device is not allowed to make the payment + return alertWithTitle("Purchase failed", message: "The device is not allowed to make the payment") + case .storeProductNotAvailable: // Product is not available in the current storefront + return alertWithTitle("Purchase failed", message: "The product is not available in the current storefront") + case .cloudServicePermissionDenied: // user has not allowed access to cloud service information + return alertWithTitle("Purchase failed", message: "Access to cloud service information is not allowed") + case .cloudServiceNetworkConnectionFailed: // the device could not connect to the nework + return alertWithTitle("Purchase failed", message: "Could not connect to the network") + case .cloudServiceRevoked: // user has revoked permission to use this cloud service + return alertWithTitle("Purchase failed", message: "Cloud service was revoked") + } + } + } + + + + func alertForVerifyReceipt(_ result: VerifyReceiptResult) -> UIAlertController { + + switch result { + case .success(let receipt): + print("Verify receipt Success: \(receipt)") + return alertWithTitle("Receipt verified", message: "Receipt verified remotely") + case .error(let error): + print("Verify receipt Failed: \(error)") + switch error { + case .noReceiptData: + return alertWithTitle("Receipt verification", message: "No receipt data. Try again.") + case .networkError(let error): + return alertWithTitle("Receipt verification", message: "Network error while verifying receipt: \(error)") + default: + return alertWithTitle("Receipt verification", message: "Receipt verification failed: \(error)") + } + } + } + + func alertForVerifySubscription(_ result: VerifySubscriptionResult) -> UIAlertController { + + switch result { + case .purchased(let expiryDate): + print("Product is valid until \(expiryDate)") + return alertWithTitle("Product is purchased", message: "Product is valid until \(expiryDate)") + case .expired(let expiryDate): + print("Product is expired since \(expiryDate)") + return alertWithTitle("Product expired", message: "Product is expired since \(expiryDate)") + case .notPurchased: + print("This product has never been purchased") + return alertWithTitle("Not purchased", message: "This product has never been purchased") + } + } + + func alertForVerifyPurchase(_ result: VerifyPurchaseResult) -> UIAlertController { + + switch result { + case .purchased: + print("Product is purchased") + return alertWithTitle("Product is purchased", message: "Product will not expire") + case .notPurchased: + print("This product has never been purchased") + return alertWithTitle("Not purchased", message: "This product has never been purchased") + } + } + +} diff --git a/Surf/SFViewController.swift b/Surf/SFViewController.swift new file mode 100644 index 0000000..dd4a4af --- /dev/null +++ b/Surf/SFViewController.swift @@ -0,0 +1,110 @@ +// +// SFViewController.swift +// Surf +// +// Created by 孔祥波 on 9/2/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit + +class SFViewController: UIViewController { + + func dataForShare(filePath:URL?) ->Data? { + guard let u = filePath else { + return nil + } + do { + let data = try Data.init(contentsOf: u) + return data + }catch let e { + print(e.localizedDescription) + } + return nil + } + func fontsize() ->CGFloat { + var size:CGFloat = 12.0; + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + size = 14 + default: + size = 8 + break + + } + return size + } + func alertMessageAction(_ message:String,complete:(() -> Void)?) { + var style:UIAlertControllerStyle = .alert + let deviceIdiom = UIScreen.main.traitCollection.userInterfaceIdiom + switch deviceIdiom { + case .pad: + style = .alert + default: + break + + } + let alert = UIAlertController.init(title: "Alert", message: message, preferredStyle: style) + let action = UIAlertAction.init(title: "OK", style: .default) { (action:UIAlertAction) -> Void in + if let callback = complete { + callback() + } + } + alert.addAction(action) + self.present(alert, animated: true) { () -> Void in + + } + } + + func shareAirDropURL(_ u:URL,name:String) { + if !FileManager.default.fileExists(atPath: u.path) { + return + } + let dest = URL.init(fileURLWithPath: NSTemporaryDirectory()+name) + do { + try FileManager.default.copyItem(at: u, to: dest) + }catch let e { + print(e.localizedDescription) + } + let controller = UIActivityViewController(activityItems: [u],applicationActivities:nil) + if let actv = controller.popoverPresentationController { + actv.barButtonItem = self.navigationItem.rightBarButtonItem + actv.sourceView = self.view + } + controller.completionWithItemsHandler = { (type,complete,items,error) in + do { + try FileManager.default.removeItem(at: u) + }catch let e { + print(e.localizedDescription) + } + + } + + self.present(controller, animated: true) { () -> Void in + } + } + override func viewDidLoad() { + super.viewDidLoad() + + //automaticallyAdjustsScrollViewInsets = true + // Do any additional setup after loading the view. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/SFWebViewController.swift b/Surf/SFWebViewController.swift new file mode 100644 index 0000000..0a58590 --- /dev/null +++ b/Surf/SFWebViewController.swift @@ -0,0 +1,91 @@ +// +// SFWebViewController.swift +// Surf +// +// Created by abigt on 16/1/18. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit + + +class SFWebViewController: UIViewController,UIWebViewDelegate{ + + var url:URL? + var headerInfo:String! + @IBOutlet weak var webView: UIWebView! + @IBOutlet weak var textView:UITextView! + override func viewDidLoad() { + super.viewDidLoad() + self.title = headerInfo + + textView.text = "loading" + + edgesForExtendedLayout = .all + + guard let url = url else {return} + guard let scheme = url.scheme else {return} + if scheme.hasPrefix("file") { + let content = try! String.init(contentsOf: url) + textView.text = content + webView.removeFromSuperview() + }else { + webView.frame = self.view.frame + webView.isOpaque = false; + + webView.backgroundColor = UIColor.clear + textView.removeFromSuperview() + // let v = UIWebView.init(frame: self.view.frame) + // self.view.addSubview(v) + + } + + } + func loadContent() { + guard let url = url else {return} + guard let scheme = url.scheme else {return} + if scheme.hasPrefix("file") { + let content = try! String.init(contentsOf: url) + textView.text = content + + }else { + let req = NSURLRequest.init(url: url) + + // let v = UIWebView.init(frame: self.view.frame) + // self.view.addSubview(v) + webView.loadRequest(req as URLRequest) + webView.delegate = self + } + + + + //let data = try! NSData.init(contentsOfURL: url!) + // + //webView.loadHTMLString(content, baseURL: url) + + //webView.loadData(data!, MIMEType: "application/txt", textEncodingName: "UTF-8", baseURL: NSURL.init(string: "http://abigt.net")!) + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + loadContent() + } + func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{ + return true + } + + func webViewDidStartLoad(_ webView: UIWebView){ + + } + + func webViewDidFinishLoad(_ webView: UIWebView){ + + let string = "addCSSRule('body', '-webkit-text-size-adjust: 10;')" + webView.stringByEvaluatingJavaScript(from: string) + } + + func webView(_ webView: UIWebView, didFailLoadWithError error: Error){ + print(error) + } + + +} diff --git a/Surf/SFactivity.swift b/Surf/SFactivity.swift new file mode 100644 index 0000000..6d7fe28 --- /dev/null +++ b/Surf/SFactivity.swift @@ -0,0 +1,38 @@ +// +// SFData.swift +// Surf +// +// Created by 孔祥波 on 8/19/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import Foundation +import UIKit +class SFactivityData:NSObject,UIActivityItemSource{ + @available(iOS 6.0, *) + + public func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any // called to determine data type. only the class of the return type is consulted. it should match what -itemForActivityType: returns later{ + + { + return "x" + } + + public func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType?) -> Any? // called to fetch data after an activity is selected. you can return nil. + + { + return "x" + } + + + var data:NSData? + func activityViewControllerPlaceholderItem(activityViewController: UIActivityViewController) -> Any { + return "public.text" as AnyObject + } + private func activityViewController(activityViewController: UIActivityViewController, itemForActivityType activityType: String) -> Any? { + return data + } + private func activityViewController(activityViewController: UIActivityViewController, subjectForActivityType activityType: String?) -> String { + return "request.json" + } + +} diff --git a/Surf/SSMethod.storyboard b/Surf/SSMethod.storyboard new file mode 100644 index 0000000..18c4000 --- /dev/null +++ b/Surf/SSMethod.storyboard @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/SampleCell.swift b/Surf/SampleCell.swift new file mode 100644 index 0000000..a19d764 --- /dev/null +++ b/Surf/SampleCell.swift @@ -0,0 +1,44 @@ +// +// SampleCell.swift +// Surf +// +// Created by abigt on 16/1/18. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import XRuler +class SampleCell: UITableViewCell { + @IBOutlet weak var label:UILabel? + @IBOutlet weak var iconlabel:UILabel? + func updateUI(){ + //c.label?.attributedText = s + //Configure the cell... + if ProxyGroupSettings.share.wwdcStyle { + label?.textColor = SFTableViewCell.textcolor + iconlabel?.textColor = SFTableViewCell.textcolor + }else { + label?.textColor = SFTableViewCell.textcolorW + iconlabel?.textColor = SFTableViewCell.textcolorW + } + } +} + +class SampleSwitchCell: SampleCell { + @IBOutlet weak var statuslabel:UILabel? + @IBOutlet weak var sfSwitch:UISwitch? + var valueChanged: ((UISwitch) -> Void)? + @IBAction func enableAction(_ sender:UISwitch){ + valueChanged?(sfSwitch!) + } + override func updateUI(){ + super.updateUI() + if ProxyGroupSettings.share.wwdcStyle { + statuslabel?.textColor = UIColor.white + iconlabel?.textColor = SFTableViewCell.textcolor + }else { + statuslabel?.textColor = UIColor.darkText + iconlabel?.textColor = SFTableViewCell.textcolorW + } + } +} diff --git a/Surf/SecondViewController.swift b/Surf/SecondViewController.swift new file mode 100644 index 0000000..c1c9b16 --- /dev/null +++ b/Surf/SecondViewController.swift @@ -0,0 +1,25 @@ +// +// SecondViewController.swift +// Surf +// +// Created by abigt on 15/11/20. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit + +class SecondViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + +} + diff --git a/Surf/Socks.swift b/Surf/Socks.swift new file mode 100644 index 0000000..2a6a99a --- /dev/null +++ b/Surf/Socks.swift @@ -0,0 +1,39 @@ +// +// Socks.swift +// Surf +// +// Created by abigt on 15/12/3. +// Copyright © 2015年 abigt. All rights reserved. +// + +import Foundation +@objc(KKSocks) class Socks :NSObject,NSCoding{ + public func encode(with aCoder: NSCoder) { + aCoder.encode(self.proxyName, forKey: "proxyName") + aCoder.encode(self.serverAddress, forKey: "serverAddress") + aCoder.encode(self.serverPort, forKey: "serverPort") + aCoder.encode(self.password, forKey: "password") + aCoder.encode(self.method, forKey: "method") + aCoder.encode(self.serverType, forKey: "serverType") + } + + internal var proxyName:String? + internal var serverAddress:String? + internal var serverPort:String? + var password:String? + var method:String? + var serverType:String? + override init() {} + required init?(coder aDecoder: NSCoder){ + super.init() + + self.proxyName = aDecoder.decodeObject(forKey: "proxyName") as? String + self.serverAddress = aDecoder.decodeObject(forKey: "serverAddress") as? String + self.serverPort = aDecoder.decodeObject(forKey: "serverPort") as? String + self.password = aDecoder.decodeObject(forKey: "password") as? String + self.method = aDecoder.decodeObject(forKey: "method") as? String + self.serverType = aDecoder.decodeObject(forKey: "serverType") as? String + } + + +} diff --git a/Surf/StatViewController.swift b/Surf/StatViewController.swift new file mode 100644 index 0000000..4fe4a85 --- /dev/null +++ b/Surf/StatViewController.swift @@ -0,0 +1,97 @@ +// +// StatViewController.swift +// Surf +// +// Created by abigt on 16/2/14. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit + +class StatViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + return 0 + } + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 0 + } + + /* + override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + if editingStyle == .Delete { + // Delete the row from the data source + tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + } else if editingStyle == .Insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/Surf-Bridging-Header.h b/Surf/Surf-Bridging-Header.h new file mode 100644 index 0000000..296c4b3 --- /dev/null +++ b/Surf/Surf-Bridging-Header.h @@ -0,0 +1,30 @@ +// +// Surf-Bridging-Header.h +// Surf +// +// Created by abigt on 15/12/7. +// Copyright © 2015年 abigt. All rights reserved. +// + +#ifndef Surf_Bridging_Header_h +#define Surf_Bridging_Header_h + +//#import "MMDB.h" + +#include + +# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#ifdef DEBUG + +//NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#else +//# define DLog(...) +//# define SLog(...) +#endif + +// ALog always displays output regardless of the DEBUG setting +#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +//#import +//#import +#import +#endif /* Surf_Bridging_Header_h */ diff --git a/Surf/Surf-Swift.h b/Surf/Surf-Swift.h new file mode 100644 index 0000000..3e3c858 --- /dev/null +++ b/Surf/Surf-Swift.h @@ -0,0 +1,359 @@ +// Generated by Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76) +#pragma clang diagnostic push + +#if defined(__has_include) && __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#include +#include +#include +#include + +#if defined(__has_include) && __has_include() +# include +#elif !defined(__cplusplus) || __cplusplus < 201103L +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +#endif + +typedef struct _NSZone NSZone; + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif + +#if defined(__has_attribute) && __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +#else +# define SWIFT_RUNTIME_NAME(X) +#endif +#if defined(__has_attribute) && __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +#else +# define SWIFT_COMPILE_NAME(X) +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif + +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif + +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif + +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if defined(__has_attribute) && __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type +#endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +#if defined(__has_feature) && __has_feature(modules) +@import UIKit; +@import AVFoundation; +@import ObjectiveC; +@import Foundation; +#endif + +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +@class NSBundle; +@class NSCoder; + +SWIFT_CLASS("_TtC4Surf25AcknowledgeViewController") +@interface AcknowledgeViewController : UIViewController +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class BarcodeScanViewController; + + +/// The tunnel delegate protocol. +SWIFT_PROTOCOL("_TtP4Surf19BarcodeScanDelegate_") +@protocol BarcodeScanDelegate +- (void)barcodeScanDidScan:(BarcodeScanViewController * __nonnull)controller configString:(NSString * __nonnull)configString; +- (void)barcodeScanCancelScan:(BarcodeScanViewController * __nonnull)controller; +@end + +@class KKSocks; +@protocol AddEditDelegate; +@class NSMutableArray; +@class UISegmentedControl; +@class UIStoryboardSegue; +@class TextFieldCell; + +SWIFT_CLASS("_TtC4Surf17AddEditController") +@interface AddEditController : UITableViewController +@property (nonatomic) NSInteger numberOfSetting; +@property (nonatomic) BOOL useCamera; +@property (nonatomic, strong) KKSocks * __nonnull config; +@property (nonatomic, strong) id __nullable delegate; +@property (nonatomic) BOOL typeHttp; +@property (nonatomic, strong) NSMutableArray * __nonnull textFields; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified nameCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified addressCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified portCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified passwdCell; +@property (nonatomic, weak) IBOutlet TextFieldCell * __null_unspecified methodCell; +- (void)viewDidLoad; +- (void)loadConfig; +- (void)valueChanged:(UISegmentedControl * __nonnull)sender; +- (void)saveConfig:(id __nonnull)sender; +- (IBAction)useBarcode:(id __nonnull)sender; +- (void)barcodeScanDidScan:(BarcodeScanViewController * __nonnull)controller configString:(NSString * __nonnull)configString; +- (void)barcodeScanCancelScan:(BarcodeScanViewController * __nonnull)controller; +- (void)prepareForSegue:(UIStoryboardSegue * __nonnull)segue sender:(id __nullable)sender; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + + +/// The tunnel delegate protocol. +SWIFT_PROTOCOL("_TtP4Surf15AddEditDelegate_") +@protocol AddEditDelegate +- (void)addConfig:(AddEditController * __nonnull)controller config:(KKSocks * __nonnull)config; +@end + +@class UIWindow; +@class UIApplication; +@class NSObject; + +SWIFT_CLASS("_TtC4Surf11AppDelegate") +@interface AppDelegate : UIResponder +@property (nonatomic, strong) UIWindow * __nullable window; +- (BOOL)application:(UIApplication * __nonnull)application didFinishLaunchingWithOptions:(NSDictionary * __nullable)launchOptions; +- (void)applicationWillResignActive:(UIApplication * __nonnull)application; +- (void)applicationDidEnterBackground:(UIApplication * __nonnull)application; +- (void)applicationWillEnterForeground:(UIApplication * __nonnull)application; +- (void)applicationDidBecomeActive:(UIApplication * __nonnull)application; +- (void)applicationWillTerminate:(UIApplication * __nonnull)application; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +@class AVCaptureSession; +@class AVCaptureVideoPreviewLayer; +@class AVCaptureOutput; +@class AVCaptureConnection; + +SWIFT_CLASS("_TtC4Surf25BarcodeScanViewController") +@interface BarcodeScanViewController : UIViewController +@property (nonatomic, readonly, copy) NSString * __nonnull kScanQRCodeQueueName; +@property (nonatomic, strong) AVCaptureSession * __nullable captureSession; +@property (nonatomic, strong) AVCaptureVideoPreviewLayer * __nullable videoPreviewLayer; +@property (nonatomic) BOOL useCamera; +@property (nonatomic, strong) id __nullable delegate; +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (IBAction)cancleAction:(id __nonnull)sender; +- (BOOL)startReading; +- (void)stopReading; +- (void)captureOutput:(AVCaptureOutput * __null_unspecified)captureOutput didOutputMetadataObjects:(NSArray * __null_unspecified)metadataObjects fromConnection:(AVCaptureConnection * __null_unspecified)connection; +- (void)reportScanResult:(NSString * __null_unspecified)result; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC4Surf9DataShare") +@interface DataShare : NSObject ++ (BOOL)save:(KKSocks * __nonnull)sock; ++ (NSString * __nonnull)configPath; ++ (KKSocks * __nonnull)readConfig; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC4Surf23HelpTableViewController") +@interface HelpTableViewController : UITableViewController +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class NSURL; +@class UITextView; + +SWIFT_CLASS("_TtC4Surf21LogFileViewController") +@interface LogFileViewController : UIViewController +@property (nonatomic, strong) NSURL * __nullable filePath; +@property (nonatomic, weak) IBOutlet UITextView * __nullable textView; +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class UITableView; +@class NSIndexPath; +@class UITableViewCell; + +SWIFT_CLASS("_TtC4Surf26LogListTableViewController") +@interface LogListTableViewController : UITableViewController +@property (nonatomic, copy) NSArray * __nonnull fileList; +- (void)viewDidLoad; +- (void)viewWillAppear:(BOOL)animated; +- (void)viewDidAppear:(BOOL)animated; +- (void)findFiles; +- (void)didReceiveMemoryWarning; +- (NSInteger)numberOfSectionsInTableView:(UITableView * __nonnull)tableView; +- (NSInteger)tableView:(UITableView * __nonnull)tableView numberOfRowsInSection:(NSInteger)section; +- (UITableViewCell * __nonnull)tableView:(UITableView * __nonnull)tableView cellForRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)prepareForSegue:(UIStoryboardSegue * __nonnull)segue sender:(id __nullable)sender; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class NEVPNManager; +@class UIButton; + +SWIFT_CLASS("_TtC4Surf23ProxyListViewController") +@interface ProxyListViewController : UITableViewController + +/// The target VPN configuration. +@property (nonatomic, strong) NEVPNManager * __nonnull targetManager; +@property (nonatomic, strong) NEVPNManager * __nullable configManage; + +/// A list of NEVPNManager objects for the packet tunnel configurations. +@property (nonatomic, copy) NSArray * __nonnull managers; +@property (nonatomic, weak) UIButton * __nullable startStopButton; +@property (nonatomic, strong) NSMutableArray * __nonnull proxyList; +@property (nonatomic, strong) NSIndexPath * __nullable selectPath; +@property (nonatomic, strong) NSURL * __nonnull applicationDocumentsDirectory; +- (void)loadProxys; + +/// Unwind segue handler. +- (IBAction)handleUnwind:(UIStoryboardSegue * __nonnull)sender; +- (void)saveProxys; + +/// Handle the event where the view is being hidden. +- (void)viewWillDisappear:(BOOL)animated; +- (void)viewDidLoad; +- (void)findUsedConfig; + +/// Handle the event of the view being displayed. +- (void)viewWillAppear:(BOOL)animated; +- (void)didReceiveMemoryWarning; +- (void)setEditing:(BOOL)editing animated:(BOOL)animated; +- (NSInteger)numberOfSectionsInTableView:(UITableView * __nonnull)tableView; +- (NSInteger)tableView:(UITableView * __nonnull)tableView numberOfRowsInSection:(NSInteger)section; +- (IBAction)startConnect:(id __nonnull)sender; +- (UITableViewCell * __nonnull)tableView:(UITableView * __nonnull)tableView cellForRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)updateCell:(UITableViewCell * __nonnull)cell indexPath:(NSIndexPath * __nonnull)indexPath; +- (BOOL)tableView:(UITableView * __nonnull)tableView canEditRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (UITableViewCellEditingStyle)tableView:(UITableView * __nonnull)tableView editingStyleForRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)tableView:(UITableView * __nonnull)tableView didSelectRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)saveConfig; +- (void)tableView:(UITableView * __nonnull)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath * __nonnull)indexPath; +- (void)addConfig:(AddEditController * __nonnull)controller config:(KKSocks * __nonnull)config; +- (void)prepareForSegue:(UIStoryboardSegue * __nonnull)segue sender:(id __nullable)sender; +- (nonnull instancetype)initWithStyle:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +@interface ProxyListViewController (SWIFT_EXTENSION(Surf)) +- (void)setTargetManager:(NEVPNManager * __nullable)manager title:(NSString * __nullable)title; + +/// Re-load all of the packet tunnel configurations from the Network Extension preferences +- (void)reloadManagers; + +/// Register for configuration change notifications. +- (void)registerStatus; +- (void)observeStatus; + +/// De-register for configuration change notifications. +- (void)stopObservingStatus; +- (void)xpc; + +/// Handle the user toggling the "enabled" switch. +- (IBAction)enabledToggled; + +/// Handle the user toggling the "VPN" switch. +- (IBAction)startStopToggled:(id __nonnull)sender; +@end + + +SWIFT_CLASS("_TtC4Surf20SecondViewController") +@interface SecondViewController : UIViewController +- (void)viewDidLoad; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * __nullable)nibNameOrNil bundle:(NSBundle * __nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS_NAMED("Socks") +@interface KKSocks : NSObject +@property (nonatomic, copy) NSString * __nullable proxyName; +@property (nonatomic, copy) NSString * __nullable serverAddress; +@property (nonatomic, copy) NSString * __nullable serverPort; +@property (nonatomic, copy) NSString * __nullable password; +@property (nonatomic, copy) NSString * __nullable method; +@property (nonatomic, copy) NSString * __nullable serverType; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)encodeWithCoder:(NSCoder * __nonnull)aCoder; +@end + +@class UITextField; +@class UILabel; + +SWIFT_CLASS("_TtC4Surf13TextFieldCell") +@interface TextFieldCell : UITableViewCell +@property (nonatomic, weak) IBOutlet UITextField * __null_unspecified textField; +@property (nonatomic, weak) IBOutlet UILabel * __null_unspecified cellLabel; +@property (nonatomic, copy) void (^ __nullable valueChanged)(UITextField * __nonnull); +- (void)textFieldDidEndEditing:(UITextField * __nonnull)textField; +- (BOOL)textFieldShouldReturn:(UITextField * __nonnull)textField; +- (nonnull instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString * __nullable)reuseIdentifier OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +#pragma clang diagnostic pop diff --git a/Surf/Surf-iOS.xcconfig b/Surf/Surf-iOS.xcconfig new file mode 100644 index 0000000..eade272 --- /dev/null +++ b/Surf/Surf-iOS.xcconfig @@ -0,0 +1,24 @@ +// +// Surf-iOS.xcconfig +// Surf +// +// Created by abigt on 16/1/28. +// Copyright © 2016年 abigt. All rights reserved. +// +HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/MMDB" + +OTHER_LDFLAGS = $(inherited) -framework Crashlytics -framework Fabric //-framework Xcon -framework XRuler + +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/iosLib" "$(PROJECT_DIR)/Carthage/Build/iOS/" +LIBRARY_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/iosLib" "$(PROJECT_DIR)/Carthage/Build/iOS/" + + + +HEADER_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/iosLib" "$(SRCROOT)/share/include" "$(SRCROOT)/Shared/header" "$(SRCROOT)/MMDB" "$(SRCROOT)/shared/lwip/badvpn" +USER_HEADER_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/iosLib" "$(SRCROOT)/Shared/header" "$(SRCROOT)/Shared/lwip/src/include/"** +OTHER_CFLAGS = $(inherited) -isystem -I"$(PROJECT_DIR)/iosLib" + + + + + diff --git a/Surf/Surf.entitlements b/Surf/Surf.entitlements new file mode 100644 index 0000000..94aa2de --- /dev/null +++ b/Surf/Surf.entitlements @@ -0,0 +1,40 @@ + + + + + aps-environment + development + com.apple.developer.icloud-container-identifiers + + iCloud.com.abigt.Surf + + com.apple.developer.icloud-services + + CloudDocuments + + com.apple.developer.networking.HotspotHelper + + com.apple.developer.networking.networkextension + + app-proxy-provider + content-filter-provider + packet-tunnel-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + com.apple.developer.ubiquity-container-identifiers + + iCloud.com.abigt.Surf + + com.apple.security.application-groups + + group.com.abigt.Surf + + keychain-access-groups + + $(AppIdentifierPrefix)com.abigt.Surf + + + diff --git a/Surf/SwitchCell.swift b/Surf/SwitchCell.swift new file mode 100644 index 0000000..593a15d --- /dev/null +++ b/Surf/SwitchCell.swift @@ -0,0 +1,22 @@ +// +// SwitchCell.swift +// Surf +// +// Created by abigt on 16/2/24. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import XRuler +class SwitchCell: UITableViewCell { + + @IBOutlet weak var enableSwitch:UISwitch! + @IBOutlet weak var label: UILabel! + func wwdc(){ + if ProxyGroupSettings.share.wwdcStyle { + label.textColor = UIColor.white + }else { + label.textColor = UIColor.black + } + } +} diff --git a/Surf/TextFieldCell.swift b/Surf/TextFieldCell.swift new file mode 100644 index 0000000..a42e3ed --- /dev/null +++ b/Surf/TextFieldCell.swift @@ -0,0 +1,47 @@ +// +// TextFieldCell.swift +// Surf +// +// Created by kiwi on 15/11/23. +// Copyright © 2015年 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +class TextFieldCell: UITableViewCell,UITextFieldDelegate { + + @IBOutlet weak var textField: UITextField! + @IBOutlet weak var cellLabel: UILabel? + + + var valueChanged: ((UITextField) -> Void)? + + func textFieldDidEndEditing(_ textField: UITextField) { + + valueChanged?(textField) + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + valueChanged?(textField) + return true + } + deinit{ + + } + func wwdcStyle(){ + let style = ProxyGroupSettings.share.wwdcStyle + if style { + textField.textColor = UIColor.white + cellLabel?.textColor = UIColor.white + }else { + textField.textColor = UIColor.black + cellLabel?.textColor = UIColor.black + } + + } +} diff --git a/Surf/TitleView.swift b/Surf/TitleView.swift new file mode 100644 index 0000000..ec94142 --- /dev/null +++ b/Surf/TitleView.swift @@ -0,0 +1,52 @@ +// +// TitleView.swift +// Surf +// +// Created by abigt on 16/5/25. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit + +class TitleView: UIView { + var titleLabel:UILabel + var subLabel:UILabel + override init(frame: CGRect) { + var y0:CGFloat = 10.0 + var y1:CGFloat = 32.0 + let os = ProcessInfo().operatingSystemVersion + switch (os.majorVersion, os.minorVersion, os.patchVersion) { + case (8, 0, _): + print("iOS >= 8.0.0, < 8.1.0") + case (8, _, _): + print("iOS >= 8.1.0, < 9.0") + case (11, _, _): + y0 = y0 - 6 + y1 = y1 - 6 + default: + // this code will have already crashed on iOS 7, so >= iOS 10.0 + print("iOS >= 9.0.0") + } + + titleLabel = UILabel.init(frame: CGRect(x:0,y: y0,width: frame.size.width,height: 20)) + titleLabel.font = UIFont.boldSystemFont(ofSize: 16) + //titleLabel?.sizeToFit() + titleLabel.textAlignment = .center + titleLabel.textColor = UIColor.white + + subLabel = UILabel.init(frame: CGRect(x:0, y:y1, width:frame.size.width, height:15)) + subLabel.font = UIFont.systemFont(ofSize: 12) + //titleLabel?.sizeToFit() + subLabel.textAlignment = .center + subLabel.textColor = UIColor.lightGray + //subLabel.backgroundColor = UIColor.cyanColor() + + super.init(frame: frame) + self.addSubview(titleLabel) + self.addSubview(subLabel) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Surf/TwoLableCell.swift b/Surf/TwoLableCell.swift new file mode 100644 index 0000000..c4d1f3e --- /dev/null +++ b/Surf/TwoLableCell.swift @@ -0,0 +1,28 @@ +// +// TwoLableCell.swift +// Surf +// +// Created by abigt on 16/1/25. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation +import UIKit +import SFSocket +import XRuler +class TwoLableCell: UITableViewCell { + @IBOutlet weak var label: UILabel! + @IBOutlet weak var cellLabel: UILabel! + func wwdcStyle(){ + let style = ProxyGroupSettings.share.wwdcStyle + if style { + label.textColor = UIColor.white + cellLabel.textColor = UIColor.white + }else { + label.textColor = UIColor.black + cellLabel.textColor = UIColor.black + } + + } + +} diff --git a/Surf/WidgetSelectViewController.swift b/Surf/WidgetSelectViewController.swift new file mode 100644 index 0000000..6bd667e --- /dev/null +++ b/Surf/WidgetSelectViewController.swift @@ -0,0 +1,89 @@ +// +// WidgetSelectViewController.swift +// Surf +// +// Created by 孔祥波 on 7/7/16. +// Copyright © 2016 abigt. All rights reserved. +// + +import UIKit +import SFSocket +import XRuler +class WidgetSelectCell: UITableViewCell { + + @IBOutlet weak var titleLabel:UILabel! + + @IBOutlet weak var selectedLabel:UILabel! + /* + // Only override drawRect: if you perform custom drawing. + // An empty implementation adversely affects performance during animation. + override func drawRect(rect: CGRect) { + // Drawing code + } + */ + +} +class WidgetSelectViewController: SFTableViewController { + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Today Widget Config" + //versionLable?.text = "Version " + appVersion() + " (Build " + appBuild() + ")" + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem() + } + // MARK: - Table view data source + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?{ + return "If Select 0, Widget will can\'t dial(auto remove Surfing Today profile on iOS 9). Bigger then 0, mean Widget show Proxy Count" + } + override func numberOfSections(in tableView: UITableView) -> Int { + + // #warning Incomplete implementation, return the number of sections + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + // if section == 0 { + // return funcTitles.count + // } + return 6 + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + + let cell = tableView.dequeueReusableCell(withIdentifier: "widgetCell", for: indexPath as IndexPath) + let c = cell as! WidgetSelectCell + c.titleLabel.text = String(indexPath.row) + cell.updateStandUI() + + c.selectedLabel.text = "\u{f383}" + + if ProxyGroupSettings.share.widgetProxyCount == indexPath.row { + c.selectedLabel.isHidden = false + }else { + c.selectedLabel.isHidden = true + } + //c.label?.text = list[indexPath.row] + //Configure the cell... + + return cell + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath as IndexPath, animated: true) + ProxyGroupSettings.share.widgetProxyCount = indexPath.row + if indexPath.row == 0 { + ProxyGroupSettings.share.disableWidget = true + } + try! ProxyGroupSettings.share.save() + tableView.reloadData() + } +} diff --git a/Surf/buy.storyboard b/Surf/buy.storyboard new file mode 100755 index 0000000..a4f31b2 --- /dev/null +++ b/Surf/buy.storyboard @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/config.html b/Surf/config.html new file mode 100644 index 0000000..438ffdf --- /dev/null +++ b/Surf/config.html @@ -0,0 +1,194 @@ + + + +
{
  • Hosts: { },
  • Proxy:
    {
    • ProxyName :
      {
      • passwd: "password",
      • host: "127.0.0.1",
      • protocol: "https",
      • port: "3120",
      • method: "username"
      }
    },
  • Rule:
    {
    • DOMAIN-KEYWORD:
      {
      • blogspot:
        {
        • Proxy: "ProxyName"
        },
      • google:
        {
        • Proxy: "ProxyName"
        },
      • facebook:
        {
        • Proxy: "ProxyName"
        },
      • youtube:
        {
        • Proxy: "ProxyName"
        }
      },
    • IP-CIDR:
      {
      • 172.16.0.0/12:
        {
        • Proxy: "DIRECT"
        },
      • 10.0.0.0/8:
        {
        • Proxy: "DIRECT"
        },
      • 127.0.0.0/8:
        {
        • Proxy: "DIRECT"
        },
      • 192.168.0.0/16:
        {
        • Proxy: "DIRECT"
        }
      },
    • GEOIP:
      {
      • CN:
        {
        • Proxy: "DIRECT"
        }
      },
    • USER-AGENT:
      {
      • Chrome:
        {
        • Proxy: "ProxyName"
        },
      • Twitter:
        {
        • Proxy: "ProxyName"
        },
      • GeoServices:
        {
        • Proxy: "ProxyName"
        },
      • SyncedDefaults:
        {
        • Proxy: "ProxyName"
        },
      • Safari:
        {
        • Proxy: "ProxyName"
        }
      },
    • DOMAIN-SUFFIX:
      {
      • chromium.org:
        {
        • Proxy: "ProxyName"
        },
      • duckduckgo.com:
        {
        • Proxy: "ProxyName"
        },
      • adcdownload.apple.com:
        {
        • Proxy: "DIRECT"
        },
      • kat.cr:
        {
        • Proxy: "ProxyName"
        },
      • cloudfront.net:
        {
        • Proxy: "ProxyName"
        },
      • dropcam.com:
        {
        • Proxy: "ProxyName"
        },
      • wsj.net:
        {
        • Proxy: "ProxyName"
        },
      • github.io:
        {
        • Proxy: "ProxyName"
        },
      • wikipedia.org:
        {
        • Proxy: "ProxyName"
        },
      • golang.org:
        {
        • Proxy: "ProxyName"
        },
      • blog.com:
        {
        • Proxy: "ProxyName"
        },
      • github.com:
        {
        • Proxy: "ProxyName"
        },
      • fabric.io:
        {
        • Proxy: "ProxyName"
        },
      • gmail.com:
        {
        • Proxy: "ProxyName"
        },
      • gravatar.com:
        {
        • Proxy: "ProxyName"
        },
      • imgur.com:
        {
        • Proxy: "ProxyName"
        },
      • engadget.com:
        {
        • Proxy: "ProxyName"
        },
      • nytimes.com:
        {
        • Proxy: "ProxyName"
        },
      • flickr.com:
        {
        • Proxy: "ProxyName"
        },
      • dnsimple.com:
        {
        • Proxy: "ProxyName"
        },
      • usefedora.com:
        {
        • Proxy: "ProxyName"
        },
      • hootsuite.com:
        {
        • Proxy: "ProxyName"
        },
      • gstatic.com:
        {
        • Proxy: "ProxyName"
        },
      • ow.ly:
        {
        • Proxy: "ProxyName"
        },
      • openwrt.org:
        {
        • Proxy: "ProxyName"
        },
      • ubnt.com:
        {
        • Proxy: "ProxyName"
        },
      • symauth.com:
        {
        • Proxy: "ProxyName"
        },
      • wikipedia.com:
        {
        • Proxy: "ProxyName"
        },
      • dropbox.com:
        {
        • Proxy: "ProxyName"
        },
      • cl.ly:
        {
        • Proxy: "ProxyName"
        },
      • cloudflare.com:
        {
        • Proxy: "ProxyName"
        },
      • mobile01.com:
        {
        • Proxy: "ProxyName"
        },
      • j.mp:
        {
        • Proxy: "ProxyName"
        },
      • akamaihd.net:
        {
        • Proxy: "ProxyName"
        },
      • dropboxusercontent.com:
        {
        • Proxy: "ProxyName"
        },
      • githubusercontent.com:
        {
        • Proxy: "ProxyName"
        },
      • wsj.com:
        {
        • Proxy: "ProxyName"
        },
      • twitch.tv:
        {
        • Proxy: "ProxyName"
        },
      • name.com:
        {
        • Proxy: "ProxyName"
        },
      • edgekey.net:
        {
        • Proxy: "ProxyName"
        },
      • amazon.com:
        {
        • Proxy: "ProxyName"
        },
      • slideshare.net:
        {
        • Proxy: "ProxyName"
        },
      • bigfools.com:
        {
        • Proxy: "ProxyName"
        },
      • modmyi.com:
        {
        • Proxy: "ProxyName"
        },
      • crashlytics.com:
        {
        • Proxy: "ProxyName"
        },
      • instagram.com:
        {
        • Proxy: "ProxyName"
        },
      • tumblr.com:
        {
        • Proxy: "ProxyName"
        },
      • jshint.com:
        {
        • Proxy: "ProxyName"
        },
      • swcdn.apple.com:
        {
        • Proxy: "DIRECT"
        },
      • blogsmithmedia.com:
        {
        • Proxy: "ProxyName"
        },
      • openvpn.net:
        {
        • Proxy: "ProxyName"
        },
      • digicert.com:
        {
        • Proxy: "ProxyName"
        },
      • wikimedia.org:
        {
        • Proxy: "ProxyName"
        },
      • pinboard.in:
        {
        • Proxy: "ProxyName"
        },
      • ssl-images-amazon.com:
        {
        • Proxy: "ProxyName"
        },
      • box.net:
        {
        • Proxy: "ProxyName"
        },
      • imageshack.us:
        {
        • Proxy: "ProxyName"
        },
      • mzstatic.com:
        {
        • Proxy: "ProxyName"
        },
      • ggpht.com:
        {
        • Proxy: "ProxyName"
        },
      • cocoapods.org:
        {
        • Proxy: "ProxyName"
        },
      • angularjs.org:
        {
        • Proxy: "ProxyName"
        },
      • lithium.com:
        {
        • Proxy: "ProxyName"
        },
      • fbcdn.net:
        {
        • Proxy: "ProxyName"
        },
      • twitter.com:
        {
        • Proxy: "ProxyName"
        },
      • wp.com:
        {
        • Proxy: "ProxyName"
        },
      • amazonaws.com:
        {
        • Proxy: "ProxyName"
        },
      • t.co:
        {
        • Proxy: "ProxyName"
        },
      • blogger.com:
        {
        • Proxy: "ProxyName"
        },
      • edgecastcdn.net:
        {
        • Proxy: "ProxyName"
        },
      • sstatic.net:
        {
        • Proxy: "ProxyName"
        },
      • licdn.com:
        {
        • Proxy: "ProxyName"
        },
      • vimeo.com:
        {
        • Proxy: "ProxyName"
        },
      • youtu.be:
        {
        • Proxy: "ProxyName"
        },
      • linode.com:
        {
        • Proxy: "ProxyName"
        },
      • fastly.net:
        {
        • Proxy: "ProxyName"
        },
      • apple.com:
        {
        • Proxy: "ProxyName"
        },
      • eurekavpt.com:
        {
        • Proxy: "ProxyName"
        },
      • dropboxstatic.com:
        {
        • Proxy: "ProxyName"
        },
      • wordpress.com:
        {
        • Proxy: "ProxyName"
        },
      • symcb.com:
        {
        • Proxy: "ProxyName"
        },
      • android.com:
        {
        • Proxy: "ProxyName"
        },
      • goo.gl:
        {
        • Proxy: "ProxyName"
        },
      • sonyentertainmentnetwork.com:
        {
        • Proxy: "ProxyName"
        },
      • ytimg.com:
        {
        • Proxy: "ProxyName"
        },
      • path.com:
        {
        • Proxy: "ProxyName"
        },
      • megaupload.com:
        {
        • Proxy: "ProxyName"
        },
      • blogcdn.com:
        {
        • Proxy: "ProxyName"
        },
      • stackoverflow.com:
        {
        • Proxy: "ProxyName"
        },
      • linkedin.com:
        {
        • Proxy: "ProxyName"
        },
      • thepiratebay.org:
        {
        • Proxy: "ProxyName"
        },
      • bloomberg.com:
        {
        • Proxy: "ProxyName"
        },
      • iphone-dev.org:
        {
        • Proxy: "ProxyName"
        },
      • bitbucket.org:
        {
        • Proxy: "ProxyName"
        },
      • appldnld.apple.com:
        {
        • Proxy: "DIRECT"
        },
      • bit.ly:
        {
        • Proxy: "ProxyName"
        },
      • itunes.com:
        {
        • Proxy: "ProxyName"
        },
      • phobos.apple.com:
        {
        • Proxy: "DIRECT"
        },
      • appspot.com:
        {
        • Proxy: "ProxyName"
        },
      • symcd.com:
        {
        • Proxy: "ProxyName"
        },
      • fb.me:
        {
        • Proxy: "ProxyName"
        },
      • staticflickr.com:
        {
        • Proxy: "ProxyName"
        },
      • feedburner.com:
        {
        • Proxy: "ProxyName"
        },
      • godaddy.com:
        {
        • Proxy: "ProxyName"
        },
      • docker.com:
        {
        • Proxy: "ProxyName"
        },
      • fc2.com:
        {
        • Proxy: "ProxyName"
        },
      • icloud-analysis.com:
        {
        • Proxy: "REJECT"
        },
      • dribbble.com:
        {
        • Proxy: "ProxyName"
        },
      • twimg.com:
        {
        • Proxy: "ProxyName"
        },
      • squarespace.com:
        {
        • Proxy: "ProxyName"
        },
      • ift.tt:
        {
        • Proxy: "ProxyName"
        }
      },
    • FINAL: "ProxyName"
    },
  • General:
    {
    • loglevel : "notify",
    • commnet: "this is comment",
    • author: "surfing"
    }
}
\ No newline at end of file diff --git a/Surf/const.swift b/Surf/const.swift new file mode 100644 index 0000000..e00f7e7 --- /dev/null +++ b/Surf/const.swift @@ -0,0 +1,297 @@ +// +// const.swift +// Surf +// +// Created by abigt on 16/1/15. +// Copyright © 2016年 abigt. All rights reserved. +// + +import Foundation + + +let sampleConfig = "surf.conf" +let DefaultConfig = "Default.conf" +//let kSelect = "kSelectConf" + +//var groupIdentifier = "" + + +#if os(iOS) +let groupIdentifier = "group.com.abigt.Surf" +#else + let groupIdentifier = "745WQDK4L7.com.abigt.Surf" +#endif +let configExt = ".conf" +let packetconfig = "group.com.abigt.config" +let flagconfig = "group.com.abigt.flag" +let onDemandKey = "com.abigt.onDemandKey" +let errDomain = "com.abigt.socket" +let fm = FileManager.default + +//#if os(iOS) +let proxyIpAddr:String = "240.7.1.10" +let loopbackAddr:String = "127.0.0.1" +let dnsAddr:String = "218.75.4.130" +let proxyHTTPSIpAddr:String = "240.7.1.11" +let xxIpAddr:String = "240.7.1.12" +let tunIP:String = "240.7.1.9" +// #else +//let proxyIpAddr:String = "240.0.0.3" +//let dnsAddr:String = "218.75.4.130" +//let proxyHTTPSIpAddr:String = "240.7.1.11" +//let tunIP:String = "240.200.200.200" +// #endif +let vpnServer:String = "240.89.6.4" + +let httpProxyPort = 10080 +let httpsocketProxyPort = 10080 +let HttpsProxyPort = 10081 + +let agentsFile = "useragents.plist" +let kProxyGroup = "ProxyGroup" +let kProxyGroupFile = ".ProxyGroup" +var groupContainerURLVPN:String = "" + +let iOSAppIden = "com.abigt.Surf" +let iOSTodayIden = "com.abigt.Surf.SurfToday" +let MacAppIden = "com.abigt.Surf.mac" +let MacTunnelIden = "com.abigt.Surf.mac.extension" +let iOSTunnelIden = "com.abigt.Surf.PacketTunnel" +let configMacFn = "abigt.conf" + +let NOTIFY_SERVER_PROFILES_CHANGED = "NOTIFY_SERVER_PROFILES_CHANGED" +let NOTIFY_ADV_PROXY_CONF_CHANGED = "NOTIFY_ADV_PROXY_CONF_CHANGED" +let NOTIFY_ADV_CONF_CHANGED = "NOTIFY_ADV_CONF_CHANGED" +let NOTIFY_HTTP_CONF_CHANGED = "NOTIFY_HTTP_CONF_CHANGED" +let NOTIFY_INVALIDE_QR = "NOTIFY_INVALIDE_QR" + +let bId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String +let applicationDocumentsDirectory: URL = { + // The directory the application uses to store the Core Data store file. This code uses a directory named "com.abigtmac.test" in the application's documents Application Support directory. + let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + return urls[urls.count-1] +}() +func groupContainerURL() ->URL{ + #if os(macOS) + return fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + #else + if bId == iOSAppIden || bId == iOSTodayIden || bId == MacAppIden { + return fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + }else { + if !groupContainerURLVPN.isEmpty { + let path = readPathFromFile() + return URL.init(fileURLWithPath: path) + }else { + return fm.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)! + } + } + + #endif + //return URL.init(fileURLWithPath: "") + +} +func readPathFromFile() ->String { + let url = applicationDocumentsDirectory.appendingPathComponent("groupContainerURLVPN") + do { + let s = try NSString.init(contentsOf: url, encoding: String.Encoding.utf8.rawValue) + return s as String + }catch _{ + + } + return "" +} + +let supportEmail = "support@abigt.net" +let KEEP_APPLE_TCP = false +let kPro = "ProEdition" +let kConfig = "Config" +let kPath = "kPath" +let logdirURL = groupContainerURL().appendingPathComponent("Log") + +/* + * + * Limit resource feature + * + * + */ + + +let proxyChangedOK = "select proxy changed" +let proxyChangedErr = "proxy change failure" +enum SFVPNXPSCommand:String{ + case HELLO = "HELLO" + case RECNETREQ = "RECNETREQ" + case RULERESULT = "RULERESULT" + case STATUS = "STATUS" + case FLOWS = "FLOWS" + case LOADRULE = "LOADRULE" + case CHANGEPROXY = "CHANGEPROXY" + case UPDATERULE = "UPDATERULE" + var description: String { + switch self { + case .LOADRULE: return "LOADRULE" + case .HELLO: return "HELLO" + case .RECNETREQ : return "RECNETREQ" + case .RULERESULT: return "RULERESULT" + case .STATUS : return "STATUS" + case .FLOWS : return "FLOWS" + case .CHANGEPROXY : return "CHANGEPROXY" + case .UPDATERULE: return "UPDATERULE" + } + } +} + +//let directDomains = ["apple.com", +// "icloud.com", +// "lcdn-registration.apple.com", +// "analytics.126.net", +// "baidu.com", +// "taobao.com", +// "alicdn.com", +// "cn", +// "qq.com", +// "jd.com", +// "126.net", +// "163.com", +// "alicdn.com", +// "amap.com", +// "bdimg.com", +// "bdstatic.com", +// "cnbeta.com", +// "cnzz.com", +// "douban.com", +// "gtimg.com", +// "hao123.com", +// "haosou.com", +// "ifeng.com", +// "iqiyi.com", +// "jd.com", +// "netease.com", +// "qhimg.com", +// "qq.com", +// "sogou.com", +// "sohu.com", +// "soso.com", +// "suning.com", +// "tmall.com", +// "tudou.com", +// "weibo.com", +// "youku.com", +// "xunlei.com", +// "zhihu.com", +// "ls.apple.com", +// "weather.com", +// "ykimg.com", +// "medium.com", +// "api.smoot.apple.com", +// "configuration.apple.com", +// "xp.apple.com", +// "smp-device-content.apple.com", +// "guzzoni.apple.com", +// "captive.apple.com", +// "ess.apple.com", +// "push.apple.com", +// "akadns.net", +// "outlook.com"] +//let proxyListDomains = ["cdninstagram.com", +// "twimg.com", +// "t.co", +// "kenengba.com", +// "akamai.net", +// "mzstatic.com", +// "itunes.com", +// "mzstatic.com", +// "me.com", +// "amazonaws.com", +// "android.com", +// "angularjs.org", +// "appspot.com", +// "akamaihd.net", +// "amazon.com", +// "bit.ly", +// "bitbucket.org", +// "blog.com", +// "blogcdn.com", +// "blogger.com", +// "blogsmithmedia.com", +// "box.net", +// "bloomberg.com", +// "chromium.org", +// "cl.ly", +// "cloudfront.net", +// "cloudflare.com", +// "cocoapods.org", +// "crashlytics.com", +// "dribbble.com", +// "dropbox.com", +// "dropboxstatic.com", +// "dropboxusercontent.com", +// "docker.com", +// "duckduckgo.com", +// "digicert.com", +// "dnsimple.com", +// "edgecastcdn.net", +// "engadget.com", +// "eurekavpt.com", +// "fb.me", +// "fbcdn.net", +// "fc2.com", +// "feedburner.com", +// "fabric.io", +// "flickr.com", +// "fastly.net", +// "ggpht.com", +// "github.com", +// "github.io", +// "githubusercontent.com", +// "golang.org", +// "goo.gl", +// "gstatic.com", +// "godaddy.com", +// "gravatar.com", +// "imageshack.us", +// "imgur.com", +// "jshint.com", +// "ift.tt", +// "j.mp", +// "kat.cr", +// "linode.com", +// "linkedin.com", +// "licdn.com", +// "lithium.com", +// "megaupload.com", +// "mobile01.com", +// "modmyi.com", +// "nytimes.com", +// "name.com", +// "openvpn.net", +// "openwrt.org", +// "ow.ly", +// "pinboard.in", +// "ssl-images-amazon.com", +// "sstatic.net", +// "stackoverflow.com", +// "staticflickr.com", +// "squarespace.com", +// "symcd.com", +// "symcb.com", +// "symauth.com", +// "ubnt.com", +// "t.co", +// "thepiratebay.org", +// "tumblr.com", +// "twimg.com", +// "twitch.tv", +// "twitter.com", +// "wikipedia.com", +// "wikipedia.org", +// "wikimedia.org", +// "wordpress.com", +// "wsj.com", +// "wsj.net", +// "wp.com", +// "vimeo.com", +// "youtu.be", +// "ytimg.com", +// "bbc.uk.co", +// "tapbots.com"] diff --git a/Surf/data.json b/Surf/data.json new file mode 100644 index 0000000..dc558e2 --- /dev/null +++ b/Surf/data.json @@ -0,0 +1,1745 @@ +[ + { + "code": "AD", + "emoji": "🇦🇩", + "unicode": "U+1F1E6 U+1F1E9", + "name": "Andorra", + "title": "flag for Andorra" + }, + { + "code": "AE", + "emoji": "🇦🇪", + "unicode": "U+1F1E6 U+1F1EA", + "name": "United Arab Emirates", + "title": "flag for United Arab Emirates" + }, + { + "code": "AF", + "emoji": "🇦🇫", + "unicode": "U+1F1E6 U+1F1EB", + "name": "Afghanistan", + "title": "flag for Afghanistan" + }, + { + "code": "AG", + "emoji": "🇦🇬", + "unicode": "U+1F1E6 U+1F1EC", + "name": "Antigua and Barbuda", + "title": "flag for Antigua and Barbuda" + }, + { + "code": "AI", + "emoji": "🇦🇮", + "unicode": "U+1F1E6 U+1F1EE", + "name": "Anguilla", + "title": "flag for Anguilla" + }, + { + "code": "AL", + "emoji": "🇦🇱", + "unicode": "U+1F1E6 U+1F1F1", + "name": "Albania", + "title": "flag for Albania" + }, + { + "code": "AM", + "emoji": "🇦🇲", + "unicode": "U+1F1E6 U+1F1F2", + "name": "Armenia", + "title": "flag for Armenia" + }, + { + "code": "AO", + "emoji": "🇦🇴", + "unicode": "U+1F1E6 U+1F1F4", + "name": "Angola", + "title": "flag for Angola" + }, + { + "code": "AQ", + "emoji": "🇦🇶", + "unicode": "U+1F1E6 U+1F1F6", + "name": "Antarctica", + "title": "flag for Antarctica" + }, + { + "code": "AR", + "emoji": "🇦🇷", + "unicode": "U+1F1E6 U+1F1F7", + "name": "Argentina", + "title": "flag for Argentina" + }, + { + "code": "AS", + "emoji": "🇦🇸", + "unicode": "U+1F1E6 U+1F1F8", + "name": "American Samoa", + "title": "flag for American Samoa" + }, + { + "code": "AT", + "emoji": "🇦🇹", + "unicode": "U+1F1E6 U+1F1F9", + "name": "Austria", + "title": "flag for Austria" + }, + { + "code": "AU", + "emoji": "🇦🇺", + "unicode": "U+1F1E6 U+1F1FA", + "name": "Australia", + "title": "flag for Australia" + }, + { + "code": "AW", + "emoji": "🇦🇼", + "unicode": "U+1F1E6 U+1F1FC", + "name": "Aruba", + "title": "flag for Aruba" + }, + { + "code": "AX", + "emoji": "🇦🇽", + "unicode": "U+1F1E6 U+1F1FD", + "name": "Åland Islands", + "title": "flag for Åland Islands" + }, + { + "code": "AZ", + "emoji": "🇦🇿", + "unicode": "U+1F1E6 U+1F1FF", + "name": "Azerbaijan", + "title": "flag for Azerbaijan" + }, + { + "code": "BA", + "emoji": "🇧🇦", + "unicode": "U+1F1E7 U+1F1E6", + "name": "Bosnia and Herzegovina", + "title": "flag for Bosnia and Herzegovina" + }, + { + "code": "BB", + "emoji": "🇧🇧", + "unicode": "U+1F1E7 U+1F1E7", + "name": "Barbados", + "title": "flag for Barbados" + }, + { + "code": "BD", + "emoji": "🇧🇩", + "unicode": "U+1F1E7 U+1F1E9", + "name": "Bangladesh", + "title": "flag for Bangladesh" + }, + { + "code": "BE", + "emoji": "🇧🇪", + "unicode": "U+1F1E7 U+1F1EA", + "name": "Belgium", + "title": "flag for Belgium" + }, + { + "code": "BF", + "emoji": "🇧🇫", + "unicode": "U+1F1E7 U+1F1EB", + "name": "Burkina Faso", + "title": "flag for Burkina Faso" + }, + { + "code": "BG", + "emoji": "🇧🇬", + "unicode": "U+1F1E7 U+1F1EC", + "name": "Bulgaria", + "title": "flag for Bulgaria" + }, + { + "code": "BH", + "emoji": "🇧🇭", + "unicode": "U+1F1E7 U+1F1ED", + "name": "Bahrain", + "title": "flag for Bahrain" + }, + { + "code": "BI", + "emoji": "🇧🇮", + "unicode": "U+1F1E7 U+1F1EE", + "name": "Burundi", + "title": "flag for Burundi" + }, + { + "code": "BJ", + "emoji": "🇧🇯", + "unicode": "U+1F1E7 U+1F1EF", + "name": "Benin", + "title": "flag for Benin" + }, + { + "code": "BL", + "emoji": "🇧🇱", + "unicode": "U+1F1E7 U+1F1F1", + "name": "Saint Barthélemy", + "title": "flag for Saint Barthélemy" + }, + { + "code": "BM", + "emoji": "🇧🇲", + "unicode": "U+1F1E7 U+1F1F2", + "name": "Bermuda", + "title": "flag for Bermuda" + }, + { + "code": "BN", + "emoji": "🇧🇳", + "unicode": "U+1F1E7 U+1F1F3", + "name": "Brunei Darussalam", + "title": "flag for Brunei Darussalam" + }, + { + "code": "BO", + "emoji": "🇧🇴", + "unicode": "U+1F1E7 U+1F1F4", + "name": "Bolivia", + "title": "flag for Bolivia" + }, + { + "code": "BQ", + "emoji": "🇧🇶", + "unicode": "U+1F1E7 U+1F1F6", + "name": "Bonaire, Sint Eustatius and Saba", + "title": "flag for Bonaire, Sint Eustatius and Saba" + }, + { + "code": "BR", + "emoji": "🇧🇷", + "unicode": "U+1F1E7 U+1F1F7", + "name": "Brazil", + "title": "flag for Brazil" + }, + { + "code": "BS", + "emoji": "🇧🇸", + "unicode": "U+1F1E7 U+1F1F8", + "name": "Bahamas", + "title": "flag for Bahamas" + }, + { + "code": "BT", + "emoji": "🇧🇹", + "unicode": "U+1F1E7 U+1F1F9", + "name": "Bhutan", + "title": "flag for Bhutan" + }, + { + "code": "BV", + "emoji": "🇧🇻", + "unicode": "U+1F1E7 U+1F1FB", + "name": "Bouvet Island", + "title": "flag for Bouvet Island" + }, + { + "code": "BW", + "emoji": "🇧🇼", + "unicode": "U+1F1E7 U+1F1FC", + "name": "Botswana", + "title": "flag for Botswana" + }, + { + "code": "BY", + "emoji": "🇧🇾", + "unicode": "U+1F1E7 U+1F1FE", + "name": "Belarus", + "title": "flag for Belarus" + }, + { + "code": "BZ", + "emoji": "🇧🇿", + "unicode": "U+1F1E7 U+1F1FF", + "name": "Belize", + "title": "flag for Belize" + }, + { + "code": "CA", + "emoji": "🇨🇦", + "unicode": "U+1F1E8 U+1F1E6", + "name": "Canada", + "title": "flag for Canada" + }, + { + "code": "CC", + "emoji": "🇨🇨", + "unicode": "U+1F1E8 U+1F1E8", + "name": "Cocos (Keeling) Islands", + "title": "flag for Cocos (Keeling) Islands" + }, + { + "code": "CD", + "emoji": "🇨🇩", + "unicode": "U+1F1E8 U+1F1E9", + "name": "Congo", + "title": "flag for Congo" + }, + { + "code": "CF", + "emoji": "🇨🇫", + "unicode": "U+1F1E8 U+1F1EB", + "name": "Central African Republic", + "title": "flag for Central African Republic" + }, + { + "code": "CG", + "emoji": "🇨🇬", + "unicode": "U+1F1E8 U+1F1EC", + "name": "Congo", + "title": "flag for Congo" + }, + { + "code": "CH", + "emoji": "🇨🇭", + "unicode": "U+1F1E8 U+1F1ED", + "name": "Switzerland", + "title": "flag for Switzerland" + }, + { + "code": "CI", + "emoji": "🇨🇮", + "unicode": "U+1F1E8 U+1F1EE", + "name": "Côte D'Ivoire", + "title": "flag for Côte D'Ivoire" + }, + { + "code": "CK", + "emoji": "🇨🇰", + "unicode": "U+1F1E8 U+1F1F0", + "name": "Cook Islands", + "title": "flag for Cook Islands" + }, + { + "code": "CL", + "emoji": "🇨🇱", + "unicode": "U+1F1E8 U+1F1F1", + "name": "Chile", + "title": "flag for Chile" + }, + { + "code": "CM", + "emoji": "🇨🇲", + "unicode": "U+1F1E8 U+1F1F2", + "name": "Cameroon", + "title": "flag for Cameroon" + }, + { + "code": "CN", + "emoji": "🇨🇳", + "unicode": "U+1F1E8 U+1F1F3", + "name": "China", + "title": "flag for China" + }, + { + "code": "CO", + "emoji": "🇨🇴", + "unicode": "U+1F1E8 U+1F1F4", + "name": "Colombia", + "title": "flag for Colombia" + }, + { + "code": "CR", + "emoji": "🇨🇷", + "unicode": "U+1F1E8 U+1F1F7", + "name": "Costa Rica", + "title": "flag for Costa Rica" + }, + { + "code": "CU", + "emoji": "🇨🇺", + "unicode": "U+1F1E8 U+1F1FA", + "name": "Cuba", + "title": "flag for Cuba" + }, + { + "code": "CV", + "emoji": "🇨🇻", + "unicode": "U+1F1E8 U+1F1FB", + "name": "Cape Verde", + "title": "flag for Cape Verde" + }, + { + "code": "CW", + "emoji": "🇨🇼", + "unicode": "U+1F1E8 U+1F1FC", + "name": "Curaçao", + "title": "flag for Curaçao" + }, + { + "code": "CX", + "emoji": "🇨🇽", + "unicode": "U+1F1E8 U+1F1FD", + "name": "Christmas Island", + "title": "flag for Christmas Island" + }, + { + "code": "CY", + "emoji": "🇨🇾", + "unicode": "U+1F1E8 U+1F1FE", + "name": "Cyprus", + "title": "flag for Cyprus" + }, + { + "code": "CZ", + "emoji": "🇨🇿", + "unicode": "U+1F1E8 U+1F1FF", + "name": "Czech Republic", + "title": "flag for Czech Republic" + }, + { + "code": "DE", + "emoji": "🇩🇪", + "unicode": "U+1F1E9 U+1F1EA", + "name": "Germany", + "title": "flag for Germany" + }, + { + "code": "DJ", + "emoji": "🇩🇯", + "unicode": "U+1F1E9 U+1F1EF", + "name": "Djibouti", + "title": "flag for Djibouti" + }, + { + "code": "DK", + "emoji": "🇩🇰", + "unicode": "U+1F1E9 U+1F1F0", + "name": "Denmark", + "title": "flag for Denmark" + }, + { + "code": "DM", + "emoji": "🇩🇲", + "unicode": "U+1F1E9 U+1F1F2", + "name": "Dominica", + "title": "flag for Dominica" + }, + { + "code": "DO", + "emoji": "🇩🇴", + "unicode": "U+1F1E9 U+1F1F4", + "name": "Dominican Republic", + "title": "flag for Dominican Republic" + }, + { + "code": "DZ", + "emoji": "🇩🇿", + "unicode": "U+1F1E9 U+1F1FF", + "name": "Algeria", + "title": "flag for Algeria" + }, + { + "code": "EC", + "emoji": "🇪🇨", + "unicode": "U+1F1EA U+1F1E8", + "name": "Ecuador", + "title": "flag for Ecuador" + }, + { + "code": "EE", + "emoji": "🇪🇪", + "unicode": "U+1F1EA U+1F1EA", + "name": "Estonia", + "title": "flag for Estonia" + }, + { + "code": "EG", + "emoji": "🇪🇬", + "unicode": "U+1F1EA U+1F1EC", + "name": "Egypt", + "title": "flag for Egypt" + }, + { + "code": "EH", + "emoji": "🇪🇭", + "unicode": "U+1F1EA U+1F1ED", + "name": "Western Sahara", + "title": "flag for Western Sahara" + }, + { + "code": "ER", + "emoji": "🇪🇷", + "unicode": "U+1F1EA U+1F1F7", + "name": "Eritrea", + "title": "flag for Eritrea" + }, + { + "code": "ES", + "emoji": "🇪🇸", + "unicode": "U+1F1EA U+1F1F8", + "name": "Spain", + "title": "flag for Spain" + }, + { + "code": "ET", + "emoji": "🇪🇹", + "unicode": "U+1F1EA U+1F1F9", + "name": "Ethiopia", + "title": "flag for Ethiopia" + }, + { + "code": "FI", + "emoji": "🇫🇮", + "unicode": "U+1F1EB U+1F1EE", + "name": "Finland", + "title": "flag for Finland" + }, + { + "code": "FJ", + "emoji": "🇫🇯", + "unicode": "U+1F1EB U+1F1EF", + "name": "Fiji", + "title": "flag for Fiji" + }, + { + "code": "FK", + "emoji": "🇫🇰", + "unicode": "U+1F1EB U+1F1F0", + "name": "Falkland Islands (Malvinas)", + "title": "flag for Falkland Islands (Malvinas)" + }, + { + "code": "FM", + "emoji": "🇫🇲", + "unicode": "U+1F1EB U+1F1F2", + "name": "Micronesia", + "title": "flag for Micronesia" + }, + { + "code": "FO", + "emoji": "🇫🇴", + "unicode": "U+1F1EB U+1F1F4", + "name": "Faroe Islands", + "title": "flag for Faroe Islands" + }, + { + "code": "FR", + "emoji": "🇫🇷", + "unicode": "U+1F1EB U+1F1F7", + "name": "France", + "title": "flag for France" + }, + { + "code": "GA", + "emoji": "🇬🇦", + "unicode": "U+1F1EC U+1F1E6", + "name": "Gabon", + "title": "flag for Gabon" + }, + { + "code": "GB", + "emoji": "🇬🇧", + "unicode": "U+1F1EC U+1F1E7", + "name": "United Kingdom", + "title": "flag for United Kingdom" + }, + { + "code": "GD", + "emoji": "🇬🇩", + "unicode": "U+1F1EC U+1F1E9", + "name": "Grenada", + "title": "flag for Grenada" + }, + { + "code": "GE", + "emoji": "🇬🇪", + "unicode": "U+1F1EC U+1F1EA", + "name": "Georgia", + "title": "flag for Georgia" + }, + { + "code": "GF", + "emoji": "🇬🇫", + "unicode": "U+1F1EC U+1F1EB", + "name": "French Guiana", + "title": "flag for French Guiana" + }, + { + "code": "GG", + "emoji": "🇬🇬", + "unicode": "U+1F1EC U+1F1EC", + "name": "Guernsey", + "title": "flag for Guernsey" + }, + { + "code": "GH", + "emoji": "🇬🇭", + "unicode": "U+1F1EC U+1F1ED", + "name": "Ghana", + "title": "flag for Ghana" + }, + { + "code": "GI", + "emoji": "🇬🇮", + "unicode": "U+1F1EC U+1F1EE", + "name": "Gibraltar", + "title": "flag for Gibraltar" + }, + { + "code": "GL", + "emoji": "🇬🇱", + "unicode": "U+1F1EC U+1F1F1", + "name": "Greenland", + "title": "flag for Greenland" + }, + { + "code": "GM", + "emoji": "🇬🇲", + "unicode": "U+1F1EC U+1F1F2", + "name": "Gambia", + "title": "flag for Gambia" + }, + { + "code": "GN", + "emoji": "🇬🇳", + "unicode": "U+1F1EC U+1F1F3", + "name": "Guinea", + "title": "flag for Guinea" + }, + { + "code": "GP", + "emoji": "🇬🇵", + "unicode": "U+1F1EC U+1F1F5", + "name": "Guadeloupe", + "title": "flag for Guadeloupe" + }, + { + "code": "GQ", + "emoji": "🇬🇶", + "unicode": "U+1F1EC U+1F1F6", + "name": "Equatorial Guinea", + "title": "flag for Equatorial Guinea" + }, + { + "code": "GR", + "emoji": "🇬🇷", + "unicode": "U+1F1EC U+1F1F7", + "name": "Greece", + "title": "flag for Greece" + }, + { + "code": "GS", + "emoji": "🇬🇸", + "unicode": "U+1F1EC U+1F1F8", + "name": "South Georgia", + "title": "flag for South Georgia" + }, + { + "code": "GT", + "emoji": "🇬🇹", + "unicode": "U+1F1EC U+1F1F9", + "name": "Guatemala", + "title": "flag for Guatemala" + }, + { + "code": "GU", + "emoji": "🇬🇺", + "unicode": "U+1F1EC U+1F1FA", + "name": "Guam", + "title": "flag for Guam" + }, + { + "code": "GW", + "emoji": "🇬🇼", + "unicode": "U+1F1EC U+1F1FC", + "name": "Guinea-Bissau", + "title": "flag for Guinea-Bissau" + }, + { + "code": "GY", + "emoji": "🇬🇾", + "unicode": "U+1F1EC U+1F1FE", + "name": "Guyana", + "title": "flag for Guyana" + }, + { + "code": "HK", + "emoji": "🇭🇰", + "unicode": "U+1F1ED U+1F1F0", + "name": "Hong Kong", + "title": "flag for Hong Kong" + }, + { + "code": "HM", + "emoji": "🇭🇲", + "unicode": "U+1F1ED U+1F1F2", + "name": "Heard Island and Mcdonald Islands", + "title": "flag for Heard Island and Mcdonald Islands" + }, + { + "code": "HN", + "emoji": "🇭🇳", + "unicode": "U+1F1ED U+1F1F3", + "name": "Honduras", + "title": "flag for Honduras" + }, + { + "code": "HR", + "emoji": "🇭🇷", + "unicode": "U+1F1ED U+1F1F7", + "name": "Croatia", + "title": "flag for Croatia" + }, + { + "code": "HT", + "emoji": "🇭🇹", + "unicode": "U+1F1ED U+1F1F9", + "name": "Haiti", + "title": "flag for Haiti" + }, + { + "code": "HU", + "emoji": "🇭🇺", + "unicode": "U+1F1ED U+1F1FA", + "name": "Hungary", + "title": "flag for Hungary" + }, + { + "code": "ID", + "emoji": "🇮🇩", + "unicode": "U+1F1EE U+1F1E9", + "name": "Indonesia", + "title": "flag for Indonesia" + }, + { + "code": "IE", + "emoji": "🇮🇪", + "unicode": "U+1F1EE U+1F1EA", + "name": "Ireland", + "title": "flag for Ireland" + }, + { + "code": "IL", + "emoji": "🇮🇱", + "unicode": "U+1F1EE U+1F1F1", + "name": "Israel", + "title": "flag for Israel" + }, + { + "code": "IM", + "emoji": "🇮🇲", + "unicode": "U+1F1EE U+1F1F2", + "name": "Isle of Man", + "title": "flag for Isle of Man" + }, + { + "code": "IN", + "emoji": "🇮🇳", + "unicode": "U+1F1EE U+1F1F3", + "name": "India", + "title": "flag for India" + }, + { + "code": "IO", + "emoji": "🇮🇴", + "unicode": "U+1F1EE U+1F1F4", + "name": "British Indian Ocean Territory", + "title": "flag for British Indian Ocean Territory" + }, + { + "code": "IQ", + "emoji": "🇮🇶", + "unicode": "U+1F1EE U+1F1F6", + "name": "Iraq", + "title": "flag for Iraq" + }, + { + "code": "IR", + "emoji": "🇮🇷", + "unicode": "U+1F1EE U+1F1F7", + "name": "Iran", + "title": "flag for Iran" + }, + { + "code": "IS", + "emoji": "🇮🇸", + "unicode": "U+1F1EE U+1F1F8", + "name": "Iceland", + "title": "flag for Iceland" + }, + { + "code": "IT", + "emoji": "🇮🇹", + "unicode": "U+1F1EE U+1F1F9", + "name": "Italy", + "title": "flag for Italy" + }, + { + "code": "JE", + "emoji": "🇯🇪", + "unicode": "U+1F1EF U+1F1EA", + "name": "Jersey", + "title": "flag for Jersey" + }, + { + "code": "JM", + "emoji": "🇯🇲", + "unicode": "U+1F1EF U+1F1F2", + "name": "Jamaica", + "title": "flag for Jamaica" + }, + { + "code": "JO", + "emoji": "🇯🇴", + "unicode": "U+1F1EF U+1F1F4", + "name": "Jordan", + "title": "flag for Jordan" + }, + { + "code": "JP", + "emoji": "🇯🇵", + "unicode": "U+1F1EF U+1F1F5", + "name": "Japan", + "title": "flag for Japan" + }, + { + "code": "KE", + "emoji": "🇰🇪", + "unicode": "U+1F1F0 U+1F1EA", + "name": "Kenya", + "title": "flag for Kenya" + }, + { + "code": "KG", + "emoji": "🇰🇬", + "unicode": "U+1F1F0 U+1F1EC", + "name": "Kyrgyzstan", + "title": "flag for Kyrgyzstan" + }, + { + "code": "KH", + "emoji": "🇰🇭", + "unicode": "U+1F1F0 U+1F1ED", + "name": "Cambodia", + "title": "flag for Cambodia" + }, + { + "code": "KI", + "emoji": "🇰🇮", + "unicode": "U+1F1F0 U+1F1EE", + "name": "Kiribati", + "title": "flag for Kiribati" + }, + { + "code": "KM", + "emoji": "🇰🇲", + "unicode": "U+1F1F0 U+1F1F2", + "name": "Comoros", + "title": "flag for Comoros" + }, + { + "code": "KN", + "emoji": "🇰🇳", + "unicode": "U+1F1F0 U+1F1F3", + "name": "Saint Kitts and Nevis", + "title": "flag for Saint Kitts and Nevis" + }, + { + "code": "KP", + "emoji": "🇰🇵", + "unicode": "U+1F1F0 U+1F1F5", + "name": "North Korea", + "title": "flag for North Korea" + }, + { + "code": "KR", + "emoji": "🇰🇷", + "unicode": "U+1F1F0 U+1F1F7", + "name": "South Korea", + "title": "flag for South Korea" + }, + { + "code": "KW", + "emoji": "🇰🇼", + "unicode": "U+1F1F0 U+1F1FC", + "name": "Kuwait", + "title": "flag for Kuwait" + }, + { + "code": "KY", + "emoji": "🇰🇾", + "unicode": "U+1F1F0 U+1F1FE", + "name": "Cayman Islands", + "title": "flag for Cayman Islands" + }, + { + "code": "KZ", + "emoji": "🇰🇿", + "unicode": "U+1F1F0 U+1F1FF", + "name": "Kazakhstan", + "title": "flag for Kazakhstan" + }, + { + "code": "LA", + "emoji": "🇱🇦", + "unicode": "U+1F1F1 U+1F1E6", + "name": "Lao People's Democratic Republic", + "title": "flag for Lao People's Democratic Republic" + }, + { + "code": "LB", + "emoji": "🇱🇧", + "unicode": "U+1F1F1 U+1F1E7", + "name": "Lebanon", + "title": "flag for Lebanon" + }, + { + "code": "LC", + "emoji": "🇱🇨", + "unicode": "U+1F1F1 U+1F1E8", + "name": "Saint Lucia", + "title": "flag for Saint Lucia" + }, + { + "code": "LI", + "emoji": "🇱🇮", + "unicode": "U+1F1F1 U+1F1EE", + "name": "Liechtenstein", + "title": "flag for Liechtenstein" + }, + { + "code": "LK", + "emoji": "🇱🇰", + "unicode": "U+1F1F1 U+1F1F0", + "name": "Sri Lanka", + "title": "flag for Sri Lanka" + }, + { + "code": "LR", + "emoji": "🇱🇷", + "unicode": "U+1F1F1 U+1F1F7", + "name": "Liberia", + "title": "flag for Liberia" + }, + { + "code": "LS", + "emoji": "🇱🇸", + "unicode": "U+1F1F1 U+1F1F8", + "name": "Lesotho", + "title": "flag for Lesotho" + }, + { + "code": "LT", + "emoji": "🇱🇹", + "unicode": "U+1F1F1 U+1F1F9", + "name": "Lithuania", + "title": "flag for Lithuania" + }, + { + "code": "LU", + "emoji": "🇱🇺", + "unicode": "U+1F1F1 U+1F1FA", + "name": "Luxembourg", + "title": "flag for Luxembourg" + }, + { + "code": "LV", + "emoji": "🇱🇻", + "unicode": "U+1F1F1 U+1F1FB", + "name": "Latvia", + "title": "flag for Latvia" + }, + { + "code": "LY", + "emoji": "🇱🇾", + "unicode": "U+1F1F1 U+1F1FE", + "name": "Libya", + "title": "flag for Libya" + }, + { + "code": "MA", + "emoji": "🇲🇦", + "unicode": "U+1F1F2 U+1F1E6", + "name": "Morocco", + "title": "flag for Morocco" + }, + { + "code": "MC", + "emoji": "🇲🇨", + "unicode": "U+1F1F2 U+1F1E8", + "name": "Monaco", + "title": "flag for Monaco" + }, + { + "code": "MD", + "emoji": "🇲🇩", + "unicode": "U+1F1F2 U+1F1E9", + "name": "Moldova", + "title": "flag for Moldova" + }, + { + "code": "ME", + "emoji": "🇲🇪", + "unicode": "U+1F1F2 U+1F1EA", + "name": "Montenegro", + "title": "flag for Montenegro" + }, + { + "code": "MF", + "emoji": "🇲🇫", + "unicode": "U+1F1F2 U+1F1EB", + "name": "Saint Martin (French Part)", + "title": "flag for Saint Martin (French Part)" + }, + { + "code": "MG", + "emoji": "🇲🇬", + "unicode": "U+1F1F2 U+1F1EC", + "name": "Madagascar", + "title": "flag for Madagascar" + }, + { + "code": "MH", + "emoji": "🇲🇭", + "unicode": "U+1F1F2 U+1F1ED", + "name": "Marshall Islands", + "title": "flag for Marshall Islands" + }, + { + "code": "MK", + "emoji": "🇲🇰", + "unicode": "U+1F1F2 U+1F1F0", + "name": "Macedonia", + "title": "flag for Macedonia" + }, + { + "code": "ML", + "emoji": "🇲🇱", + "unicode": "U+1F1F2 U+1F1F1", + "name": "Mali", + "title": "flag for Mali" + }, + { + "code": "MM", + "emoji": "🇲🇲", + "unicode": "U+1F1F2 U+1F1F2", + "name": "Myanmar", + "title": "flag for Myanmar" + }, + { + "code": "MN", + "emoji": "🇲🇳", + "unicode": "U+1F1F2 U+1F1F3", + "name": "Mongolia", + "title": "flag for Mongolia" + }, + { + "code": "MO", + "emoji": "🇲🇴", + "unicode": "U+1F1F2 U+1F1F4", + "name": "Macao", + "title": "flag for Macao" + }, + { + "code": "MP", + "emoji": "🇲🇵", + "unicode": "U+1F1F2 U+1F1F5", + "name": "Northern Mariana Islands", + "title": "flag for Northern Mariana Islands" + }, + { + "code": "MQ", + "emoji": "🇲🇶", + "unicode": "U+1F1F2 U+1F1F6", + "name": "Martinique", + "title": "flag for Martinique" + }, + { + "code": "MR", + "emoji": "🇲🇷", + "unicode": "U+1F1F2 U+1F1F7", + "name": "Mauritania", + "title": "flag for Mauritania" + }, + { + "code": "MS", + "emoji": "🇲🇸", + "unicode": "U+1F1F2 U+1F1F8", + "name": "Montserrat", + "title": "flag for Montserrat" + }, + { + "code": "MT", + "emoji": "🇲🇹", + "unicode": "U+1F1F2 U+1F1F9", + "name": "Malta", + "title": "flag for Malta" + }, + { + "code": "MU", + "emoji": "🇲🇺", + "unicode": "U+1F1F2 U+1F1FA", + "name": "Mauritius", + "title": "flag for Mauritius" + }, + { + "code": "MV", + "emoji": "🇲🇻", + "unicode": "U+1F1F2 U+1F1FB", + "name": "Maldives", + "title": "flag for Maldives" + }, + { + "code": "MW", + "emoji": "🇲🇼", + "unicode": "U+1F1F2 U+1F1FC", + "name": "Malawi", + "title": "flag for Malawi" + }, + { + "code": "MX", + "emoji": "🇲🇽", + "unicode": "U+1F1F2 U+1F1FD", + "name": "Mexico", + "title": "flag for Mexico" + }, + { + "code": "MY", + "emoji": "🇲🇾", + "unicode": "U+1F1F2 U+1F1FE", + "name": "Malaysia", + "title": "flag for Malaysia" + }, + { + "code": "MZ", + "emoji": "🇲🇿", + "unicode": "U+1F1F2 U+1F1FF", + "name": "Mozambique", + "title": "flag for Mozambique" + }, + { + "code": "NA", + "emoji": "🇳🇦", + "unicode": "U+1F1F3 U+1F1E6", + "name": "Namibia", + "title": "flag for Namibia" + }, + { + "code": "NC", + "emoji": "🇳🇨", + "unicode": "U+1F1F3 U+1F1E8", + "name": "New Caledonia", + "title": "flag for New Caledonia" + }, + { + "code": "NE", + "emoji": "🇳🇪", + "unicode": "U+1F1F3 U+1F1EA", + "name": "Niger", + "title": "flag for Niger" + }, + { + "code": "NF", + "emoji": "🇳🇫", + "unicode": "U+1F1F3 U+1F1EB", + "name": "Norfolk Island", + "title": "flag for Norfolk Island" + }, + { + "code": "NG", + "emoji": "🇳🇬", + "unicode": "U+1F1F3 U+1F1EC", + "name": "Nigeria", + "title": "flag for Nigeria" + }, + { + "code": "NI", + "emoji": "🇳🇮", + "unicode": "U+1F1F3 U+1F1EE", + "name": "Nicaragua", + "title": "flag for Nicaragua" + }, + { + "code": "NL", + "emoji": "🇳🇱", + "unicode": "U+1F1F3 U+1F1F1", + "name": "Netherlands", + "title": "flag for Netherlands" + }, + { + "code": "NO", + "emoji": "🇳🇴", + "unicode": "U+1F1F3 U+1F1F4", + "name": "Norway", + "title": "flag for Norway" + }, + { + "code": "NP", + "emoji": "🇳🇵", + "unicode": "U+1F1F3 U+1F1F5", + "name": "Nepal", + "title": "flag for Nepal" + }, + { + "code": "NR", + "emoji": "🇳🇷", + "unicode": "U+1F1F3 U+1F1F7", + "name": "Nauru", + "title": "flag for Nauru" + }, + { + "code": "NU", + "emoji": "🇳🇺", + "unicode": "U+1F1F3 U+1F1FA", + "name": "Niue", + "title": "flag for Niue" + }, + { + "code": "NZ", + "emoji": "🇳🇿", + "unicode": "U+1F1F3 U+1F1FF", + "name": "New Zealand", + "title": "flag for New Zealand" + }, + { + "code": "OM", + "emoji": "🇴🇲", + "unicode": "U+1F1F4 U+1F1F2", + "name": "Oman", + "title": "flag for Oman" + }, + { + "code": "PA", + "emoji": "🇵🇦", + "unicode": "U+1F1F5 U+1F1E6", + "name": "Panama", + "title": "flag for Panama" + }, + { + "code": "PE", + "emoji": "🇵🇪", + "unicode": "U+1F1F5 U+1F1EA", + "name": "Peru", + "title": "flag for Peru" + }, + { + "code": "PF", + "emoji": "🇵🇫", + "unicode": "U+1F1F5 U+1F1EB", + "name": "French Polynesia", + "title": "flag for French Polynesia" + }, + { + "code": "PG", + "emoji": "🇵🇬", + "unicode": "U+1F1F5 U+1F1EC", + "name": "Papua New Guinea", + "title": "flag for Papua New Guinea" + }, + { + "code": "PH", + "emoji": "🇵🇭", + "unicode": "U+1F1F5 U+1F1ED", + "name": "Philippines", + "title": "flag for Philippines" + }, + { + "code": "PK", + "emoji": "🇵🇰", + "unicode": "U+1F1F5 U+1F1F0", + "name": "Pakistan", + "title": "flag for Pakistan" + }, + { + "code": "PL", + "emoji": "🇵🇱", + "unicode": "U+1F1F5 U+1F1F1", + "name": "Poland", + "title": "flag for Poland" + }, + { + "code": "PM", + "emoji": "🇵🇲", + "unicode": "U+1F1F5 U+1F1F2", + "name": "Saint Pierre and Miquelon", + "title": "flag for Saint Pierre and Miquelon" + }, + { + "code": "PN", + "emoji": "🇵🇳", + "unicode": "U+1F1F5 U+1F1F3", + "name": "Pitcairn", + "title": "flag for Pitcairn" + }, + { + "code": "PR", + "emoji": "🇵🇷", + "unicode": "U+1F1F5 U+1F1F7", + "name": "Puerto Rico", + "title": "flag for Puerto Rico" + }, + { + "code": "PS", + "emoji": "🇵🇸", + "unicode": "U+1F1F5 U+1F1F8", + "name": "Palestinian Territory", + "title": "flag for Palestinian Territory" + }, + { + "code": "PT", + "emoji": "🇵🇹", + "unicode": "U+1F1F5 U+1F1F9", + "name": "Portugal", + "title": "flag for Portugal" + }, + { + "code": "PW", + "emoji": "🇵🇼", + "unicode": "U+1F1F5 U+1F1FC", + "name": "Palau", + "title": "flag for Palau" + }, + { + "code": "PY", + "emoji": "🇵🇾", + "unicode": "U+1F1F5 U+1F1FE", + "name": "Paraguay", + "title": "flag for Paraguay" + }, + { + "code": "QA", + "emoji": "🇶🇦", + "unicode": "U+1F1F6 U+1F1E6", + "name": "Qatar", + "title": "flag for Qatar" + }, + { + "code": "RE", + "emoji": "🇷🇪", + "unicode": "U+1F1F7 U+1F1EA", + "name": "Réunion", + "title": "flag for Réunion" + }, + { + "code": "RO", + "emoji": "🇷🇴", + "unicode": "U+1F1F7 U+1F1F4", + "name": "Romania", + "title": "flag for Romania" + }, + { + "code": "RS", + "emoji": "🇷🇸", + "unicode": "U+1F1F7 U+1F1F8", + "name": "Serbia", + "title": "flag for Serbia" + }, + { + "code": "RU", + "emoji": "🇷🇺", + "unicode": "U+1F1F7 U+1F1FA", + "name": "Russia", + "title": "flag for Russia" + }, + { + "code": "RW", + "emoji": "🇷🇼", + "unicode": "U+1F1F7 U+1F1FC", + "name": "Rwanda", + "title": "flag for Rwanda" + }, + { + "code": "SA", + "emoji": "🇸🇦", + "unicode": "U+1F1F8 U+1F1E6", + "name": "Saudi Arabia", + "title": "flag for Saudi Arabia" + }, + { + "code": "SB", + "emoji": "🇸🇧", + "unicode": "U+1F1F8 U+1F1E7", + "name": "Solomon Islands", + "title": "flag for Solomon Islands" + }, + { + "code": "SC", + "emoji": "🇸🇨", + "unicode": "U+1F1F8 U+1F1E8", + "name": "Seychelles", + "title": "flag for Seychelles" + }, + { + "code": "SD", + "emoji": "🇸🇩", + "unicode": "U+1F1F8 U+1F1E9", + "name": "Sudan", + "title": "flag for Sudan" + }, + { + "code": "SE", + "emoji": "🇸🇪", + "unicode": "U+1F1F8 U+1F1EA", + "name": "Sweden", + "title": "flag for Sweden" + }, + { + "code": "SG", + "emoji": "🇸🇬", + "unicode": "U+1F1F8 U+1F1EC", + "name": "Singapore", + "title": "flag for Singapore" + }, + { + "code": "SH", + "emoji": "🇸🇭", + "unicode": "U+1F1F8 U+1F1ED", + "name": "Saint Helena, Ascension and Tristan Da Cunha", + "title": "flag for Saint Helena, Ascension and Tristan Da Cunha" + }, + { + "code": "SI", + "emoji": "🇸🇮", + "unicode": "U+1F1F8 U+1F1EE", + "name": "Slovenia", + "title": "flag for Slovenia" + }, + { + "code": "SJ", + "emoji": "🇸🇯", + "unicode": "U+1F1F8 U+1F1EF", + "name": "Svalbard and Jan Mayen", + "title": "flag for Svalbard and Jan Mayen" + }, + { + "code": "SK", + "emoji": "🇸🇰", + "unicode": "U+1F1F8 U+1F1F0", + "name": "Slovakia", + "title": "flag for Slovakia" + }, + { + "code": "SL", + "emoji": "🇸🇱", + "unicode": "U+1F1F8 U+1F1F1", + "name": "Sierra Leone", + "title": "flag for Sierra Leone" + }, + { + "code": "SM", + "emoji": "🇸🇲", + "unicode": "U+1F1F8 U+1F1F2", + "name": "San Marino", + "title": "flag for San Marino" + }, + { + "code": "SN", + "emoji": "🇸🇳", + "unicode": "U+1F1F8 U+1F1F3", + "name": "Senegal", + "title": "flag for Senegal" + }, + { + "code": "SO", + "emoji": "🇸🇴", + "unicode": "U+1F1F8 U+1F1F4", + "name": "Somalia", + "title": "flag for Somalia" + }, + { + "code": "SR", + "emoji": "🇸🇷", + "unicode": "U+1F1F8 U+1F1F7", + "name": "Suriname", + "title": "flag for Suriname" + }, + { + "code": "SS", + "emoji": "🇸🇸", + "unicode": "U+1F1F8 U+1F1F8", + "name": "South Sudan", + "title": "flag for South Sudan" + }, + { + "code": "ST", + "emoji": "🇸🇹", + "unicode": "U+1F1F8 U+1F1F9", + "name": "Sao Tome and Principe", + "title": "flag for Sao Tome and Principe" + }, + { + "code": "SV", + "emoji": "🇸🇻", + "unicode": "U+1F1F8 U+1F1FB", + "name": "El Salvador", + "title": "flag for El Salvador" + }, + { + "code": "SX", + "emoji": "🇸🇽", + "unicode": "U+1F1F8 U+1F1FD", + "name": "Sint Maarten (Dutch Part)", + "title": "flag for Sint Maarten (Dutch Part)" + }, + { + "code": "SY", + "emoji": "🇸🇾", + "unicode": "U+1F1F8 U+1F1FE", + "name": "Syrian Arab Republic", + "title": "flag for Syrian Arab Republic" + }, + { + "code": "SZ", + "emoji": "🇸🇿", + "unicode": "U+1F1F8 U+1F1FF", + "name": "Swaziland", + "title": "flag for Swaziland" + }, + { + "code": "TC", + "emoji": "🇹🇨", + "unicode": "U+1F1F9 U+1F1E8", + "name": "Turks and Caicos Islands", + "title": "flag for Turks and Caicos Islands" + }, + { + "code": "TD", + "emoji": "🇹🇩", + "unicode": "U+1F1F9 U+1F1E9", + "name": "Chad", + "title": "flag for Chad" + }, + { + "code": "TF", + "emoji": "🇹🇫", + "unicode": "U+1F1F9 U+1F1EB", + "name": "French Southern Territories", + "title": "flag for French Southern Territories" + }, + { + "code": "TG", + "emoji": "🇹🇬", + "unicode": "U+1F1F9 U+1F1EC", + "name": "Togo", + "title": "flag for Togo" + }, + { + "code": "TH", + "emoji": "🇹🇭", + "unicode": "U+1F1F9 U+1F1ED", + "name": "Thailand", + "title": "flag for Thailand" + }, + { + "code": "TJ", + "emoji": "🇹🇯", + "unicode": "U+1F1F9 U+1F1EF", + "name": "Tajikistan", + "title": "flag for Tajikistan" + }, + { + "code": "TK", + "emoji": "🇹🇰", + "unicode": "U+1F1F9 U+1F1F0", + "name": "Tokelau", + "title": "flag for Tokelau" + }, + { + "code": "TL", + "emoji": "🇹🇱", + "unicode": "U+1F1F9 U+1F1F1", + "name": "Timor-Leste", + "title": "flag for Timor-Leste" + }, + { + "code": "TM", + "emoji": "🇹🇲", + "unicode": "U+1F1F9 U+1F1F2", + "name": "Turkmenistan", + "title": "flag for Turkmenistan" + }, + { + "code": "TN", + "emoji": "🇹🇳", + "unicode": "U+1F1F9 U+1F1F3", + "name": "Tunisia", + "title": "flag for Tunisia" + }, + { + "code": "TO", + "emoji": "🇹🇴", + "unicode": "U+1F1F9 U+1F1F4", + "name": "Tonga", + "title": "flag for Tonga" + }, + { + "code": "TR", + "emoji": "🇹🇷", + "unicode": "U+1F1F9 U+1F1F7", + "name": "Turkey", + "title": "flag for Turkey" + }, + { + "code": "TT", + "emoji": "🇹🇹", + "unicode": "U+1F1F9 U+1F1F9", + "name": "Trinidad and Tobago", + "title": "flag for Trinidad and Tobago" + }, + { + "code": "TV", + "emoji": "🇹🇻", + "unicode": "U+1F1F9 U+1F1FB", + "name": "Tuvalu", + "title": "flag for Tuvalu" + }, + { + "code": "TW", + "emoji": "🇹🇼", + "unicode": "U+1F1F9 U+1F1FC", + "name": "Taiwan", + "title": "flag for Taiwan" + }, + { + "code": "TZ", + "emoji": "🇹🇿", + "unicode": "U+1F1F9 U+1F1FF", + "name": "Tanzania", + "title": "flag for Tanzania" + }, + { + "code": "UA", + "emoji": "🇺🇦", + "unicode": "U+1F1FA U+1F1E6", + "name": "Ukraine", + "title": "flag for Ukraine" + }, + { + "code": "UG", + "emoji": "🇺🇬", + "unicode": "U+1F1FA U+1F1EC", + "name": "Uganda", + "title": "flag for Uganda" + }, + { + "code": "UM", + "emoji": "🇺🇲", + "unicode": "U+1F1FA U+1F1F2", + "name": "United States Minor Outlying Islands", + "title": "flag for United States Minor Outlying Islands" + }, + { + "code": "US", + "emoji": "🇺🇸", + "unicode": "U+1F1FA U+1F1F8", + "name": "United States", + "title": "flag for United States" + }, + { + "code": "UY", + "emoji": "🇺🇾", + "unicode": "U+1F1FA U+1F1FE", + "name": "Uruguay", + "title": "flag for Uruguay" + }, + { + "code": "UZ", + "emoji": "🇺🇿", + "unicode": "U+1F1FA U+1F1FF", + "name": "Uzbekistan", + "title": "flag for Uzbekistan" + }, + { + "code": "VA", + "emoji": "🇻🇦", + "unicode": "U+1F1FB U+1F1E6", + "name": "Vatican City", + "title": "flag for Vatican City" + }, + { + "code": "VC", + "emoji": "🇻🇨", + "unicode": "U+1F1FB U+1F1E8", + "name": "Saint Vincent and The Grenadines", + "title": "flag for Saint Vincent and The Grenadines" + }, + { + "code": "VE", + "emoji": "🇻🇪", + "unicode": "U+1F1FB U+1F1EA", + "name": "Venezuela", + "title": "flag for Venezuela" + }, + { + "code": "VG", + "emoji": "🇻🇬", + "unicode": "U+1F1FB U+1F1EC", + "name": "Virgin Islands, British", + "title": "flag for Virgin Islands, British" + }, + { + "code": "VI", + "emoji": "🇻🇮", + "unicode": "U+1F1FB U+1F1EE", + "name": "Virgin Islands, U.S.", + "title": "flag for Virgin Islands, U.S." + }, + { + "code": "VN", + "emoji": "🇻🇳", + "unicode": "U+1F1FB U+1F1F3", + "name": "Viet Nam", + "title": "flag for Viet Nam" + }, + { + "code": "VU", + "emoji": "🇻🇺", + "unicode": "U+1F1FB U+1F1FA", + "name": "Vanuatu", + "title": "flag for Vanuatu" + }, + { + "code": "WF", + "emoji": "🇼🇫", + "unicode": "U+1F1FC U+1F1EB", + "name": "Wallis and Futuna", + "title": "flag for Wallis and Futuna" + }, + { + "code": "WS", + "emoji": "🇼🇸", + "unicode": "U+1F1FC U+1F1F8", + "name": "Samoa", + "title": "flag for Samoa" + }, + { + "code": "YE", + "emoji": "🇾🇪", + "unicode": "U+1F1FE U+1F1EA", + "name": "Yemen", + "title": "flag for Yemen" + }, + { + "code": "YT", + "emoji": "🇾🇹", + "unicode": "U+1F1FE U+1F1F9", + "name": "Mayotte", + "title": "flag for Mayotte" + }, + { + "code": "ZA", + "emoji": "🇿🇦", + "unicode": "U+1F1FF U+1F1E6", + "name": "South Africa", + "title": "flag for South Africa" + }, + { + "code": "ZM", + "emoji": "🇿🇲", + "unicode": "U+1F1FF U+1F1F2", + "name": "Zambia", + "title": "flag for Zambia" + }, + { + "code": "ZW", + "emoji": "🇿🇼", + "unicode": "U+1F1FF U+1F1FC", + "name": "Zimbabwe", + "title": "flag for Zimbabwe" + } +] \ No newline at end of file diff --git a/Surf/en.lproj/LaunchScreen.strings b/Surf/en.lproj/LaunchScreen.strings new file mode 100644 index 0000000..58fb05f --- /dev/null +++ b/Surf/en.lproj/LaunchScreen.strings @@ -0,0 +1,6 @@ + +/* Class = "UILabel"; text = " A.BIG.T Copyright © 2016-2017 "; ObjectID = "8ie-xW-0ye"; */ +"8ie-xW-0ye.text" = " A.BIG.T Copyright © 2016-2017 "; + +/* Class = "UILabel"; text = "Surfing"; ObjectID = "kId-c2-rCX"; */ +"kId-c2-rCX.text" = "Surfing"; diff --git a/Surf/en.lproj/Main.strings b/Surf/en.lproj/Main.strings new file mode 100644 index 0000000..57a7cc3 --- /dev/null +++ b/Surf/en.lproj/Main.strings @@ -0,0 +1,225 @@ + +/* Class = "UILabel"; text = "TLS"; ObjectID = "09T-1f-Cyu"; */ +"09T-1f-Cyu.text" = "TLS"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "0CT-rs-Gae"; */ +"0CT-rs-Gae.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "0yJ-K4-y7m"; */ +"0yJ-K4-y7m.text" = "Title"; + +/* Class = "UIButton"; normalTitle = "Scan Qrcode Add"; ObjectID = "1Oo-50-jh8"; */ +"1Oo-50-jh8.normalTitle" = "Scan Qrcode Add"; + +/* Class = "UILabel"; text = "Notify"; ObjectID = "2Fb-W4-DT7"; */ +"2Fb-W4-DT7.text" = "Notify"; + +/* Class = "UITabBarItem"; title = "Item"; ObjectID = "3N7-Q8-YFo"; */ +"3N7-Q8-YFo.title" = "Item"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "41s-3R-nBj"; */ +"41s-3R-nBj.text" = "Title"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "4Ig-af-AvN"; */ +"4Ig-af-AvN.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "4iw-vT-QFw"; */ +"4iw-vT-QFw.text" = "Subtitle"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[0] = "APP"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[0]" = "APP"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[1] = "SUFFIX"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[1]" = "SUFFIX"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[2] = "KEYWORD"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[2]" = "KEYWORD"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[3] = "IP"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[3]" = "IP"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[4] = "GEOIP"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[4]" = "GEOIP"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "5dp-7x-GC6"; */ +"5dp-7x-GC6.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Policy"; ObjectID = "5ix-Nm-68p"; */ +"5ix-Nm-68p.text" = "Policy"; + +/* Class = "UILabel"; text = "Verbose"; ObjectID = "6Mm-db-dZz"; */ +"6Mm-db-dZz.text" = "Verbose"; + +/* Class = "UITextField"; placeholder = "require"; ObjectID = "7ev-xI-gWh"; */ +"7ev-xI-gWh.placeholder" = "require"; + +/* Class = "UILabel"; text = "Type/HTTP/Socks5"; ObjectID = "8CL-uh-vWc"; */ +"8CL-uh-vWc.text" = "Type/HTTP/Socks5"; + +/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "9Xx-3o-qLS"; */ +"9Xx-3o-qLS.normalTitle" = "Start"; + +/* Class = "UIButton"; normalTitle = "Show Qrcode Image"; ObjectID = "9gK-jB-2te"; */ +"9gK-jB-2te.normalTitle" = "Show Qrcode Image"; + +/* Class = "UILabel"; text = "Proxy Name"; ObjectID = "A8I-dI-Z4j"; */ +"A8I-dI-Z4j.text" = "Proxy Name"; + +/* Class = "UITabBarItem"; title = "Rule"; ObjectID = "AqA-co-w8V"; */ +"AqA-co-w8V.title" = "Rule"; + +/* Class = "UILabel"; text = "CN"; ObjectID = "Csd-RI-rAl"; */ +"Csd-RI-rAl.text" = "CN"; + +/* Class = "UILabel"; text = "192.168.1.7 1080"; ObjectID = "E9y-1J-XbE"; */ +"E9y-1J-XbE.text" = "192.168.1.7 1080"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "IYN-Qk-G9g"; */ +"IYN-Qk-G9g.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Advance"; ObjectID = "KVp-vM-c1e"; */ +"KVp-vM-c1e.text" = "Advance"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "Kr3-Pr-Vem"; */ +"Kr3-Pr-Vem.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "MSV-L8-XGM"; */ +"MSV-L8-XGM.text" = "Title"; + +/* Class = "UISegmentedControl"; NiM-y4-ptz.segmentTitles[0] = "http"; ObjectID = "NiM-y4-ptz"; */ +"NiM-y4-ptz.segmentTitles[0]" = "http"; + +/* Class = "UISegmentedControl"; NiM-y4-ptz.segmentTitles[1] = "socks5"; ObjectID = "NiM-y4-ptz"; */ +"NiM-y4-ptz.segmentTitles[1]" = "socks5"; + +/* Class = "UILabel"; text = "Acknowledge"; ObjectID = "QDO-BF-ann"; */ +"QDO-BF-ann.text" = "Status"; + +/* Class = "UITabBarItem"; title = "Switch"; ObjectID = "TLs-Ix-8w5"; */ +"TLs-Ix-8w5.title" = "Switch"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Tmf-Uq-kDa"; */ +"Tmf-Uq-kDa.text" = "Title"; + +/* Class = "UILabel"; text = "Proxy Group"; ObjectID = "UGk-Vy-vu2"; */ +"UGk-Vy-vu2.text" = "Proxy Group"; + +/* Class = "UILabel"; text = "Policy"; ObjectID = "aI8-X5-bJi"; */ +"aI8-X5-bJi.text" = "Policy"; + +/* Class = "UITextField"; placeholder = "require"; ObjectID = "bjD-J7-VuI"; */ +"bjD-J7-VuI.placeholder" = "require"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "bvt-dM-dgh"; */ +"bvt-dM-dgh.text" = "Label"; + +/* Class = "UILabel"; text = "notify"; ObjectID = "c6s-BB-TQH"; */ +"c6s-BB-TQH.text" = "notify"; + +/* Class = "UISegmentedControl"; caa-Zb-PbE.segmentTitles[0] = "TCP"; ObjectID = "caa-Zb-PbE"; */ +"caa-Zb-PbE.segmentTitles[0]" = "TCP"; + +/* Class = "UISegmentedControl"; caa-Zb-PbE.segmentTitles[1] = "Socks5"; ObjectID = "caa-Zb-PbE"; */ +"caa-Zb-PbE.segmentTitles[1]" = "Socks5"; + +/* Class = "UISegmentedControl"; caa-Zb-PbE.segmentTitles[2] = "HTTP"; ObjectID = "caa-Zb-PbE"; */ +"caa-Zb-PbE.segmentTitles[2]" = "HTTP"; + +/* Class = "UILabel"; text = "TLS"; ObjectID = "dP4-DJ-vDj"; */ +"dP4-DJ-vDj.text" = "TLS"; + +/* Class = "UITabBarItem"; title = "Item"; ObjectID = "dhh-OL-2ta"; */ +"dhh-OL-2ta.title" = "Item"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "esK-TU-CLm"; */ +"esK-TU-CLm.text" = "Title"; + +/* Class = "UILabel"; text = "Trace"; ObjectID = "fKC-AV-PRY"; */ +"fKC-AV-PRY.text" = "Trace"; + +/* Class = "UILabel"; text = "Info"; ObjectID = "fWx-fH-7hC"; */ +"fWx-fH-7hC.text" = "Info"; + +/* Class = "UILabel"; text = "If enable, all proxys will auto merge to proxy Group"; ObjectID = "gEQ-SU-jXR"; */ +"gEQ-SU-jXR.text" = "If enable, all proxys will auto merge to proxy Group"; + +/* Class = "UILabel"; text = "Buy Record"; ObjectID = "gxR-0n-kUL"; */ +"gxR-0n-kUL.text" = "Buy Record"; + +/* Class = "UILabel"; text = "L"; ObjectID = "h2l-39-STS"; */ +"h2l-39-STS.text" = "L"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "hc4-Kz-yBW"; */ +"hc4-Kz-yBW.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "hhs-PQ-Jra"; */ +"hhs-PQ-Jra.text" = "Label"; + +/* Class = "UIButton"; normalTitle = "Cancel"; ObjectID = "hiW-eo-bVS"; */ +"hiW-eo-bVS.normalTitle" = "Cancel"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "irE-gC-9HN"; */ +"irE-gC-9HN.text" = "Title"; + +/* Class = "UILabel"; text = "Status"; ObjectID = "j9O-5L-RzG"; */ +"j9O-5L-RzG.text" = "Status"; + +/* Class = "UILabel"; text = "notify"; ObjectID = "jL4-cZ-Woj"; */ +"jL4-cZ-Woj.text" = "notify"; + +/* Class = "UILabel"; text = "Proxy Name"; ObjectID = "jdE-XB-ddC"; */ +"jdE-XB-ddC.text" = "Proxy Name"; + +/* Class = "UITextView"; text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."; ObjectID = "ksj-Hi-416"; */ +"ksj-Hi-416.text" = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."; + +/* Class = "UITextField"; placeholder = "Configuration Name"; ObjectID = "nmN-VT-pZg"; */ +"nmN-VT-pZg.placeholder" = "Configuration Name"; + +/* Class = "UITextField"; placeholder = "require"; ObjectID = "o0C-oO-0Hj"; */ +"o0C-oO-0Hj.placeholder" = "require"; + +/* Class = "UILabel"; text = "L"; ObjectID = "o7k-nx-t9o"; */ +"o7k-nx-t9o.text" = "L"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "oLD-3B-mCd"; */ +"oLD-3B-mCd.text" = "Title"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "oNq-RI-QOE"; */ +"oNq-RI-QOE.text" = "Title"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "oXh-1m-G0w"; */ +"oXh-1m-G0w.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "pMl-By-U26"; */ +"pMl-By-U26.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "pea-EA-oWj"; */ +"pea-EA-oWj.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "sAk-AQ-pEw"; */ +"sAk-AQ-pEw.text" = "Title"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "sm3-gp-c4x"; */ +"sm3-gp-c4x.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Warning"; ObjectID = "ssz-DM-XvQ"; */ +"ssz-DM-XvQ.text" = "Warning"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "wGm-XI-tU9"; */ +"wGm-XI-tU9.text" = "Title"; + +/* Class = "UIButton"; normalTitle = "Album"; ObjectID = "wYf-ha-Uyi"; */ +"wYf-ha-Uyi.normalTitle" = "Album"; + +/* Class = "UITableViewController"; title = "Proxy Group"; ObjectID = "wcT-oI-VtM"; */ +"wcT-oI-VtM.title" = "Proxy Group"; + +/* Class = "UILabel"; text = "Log level "; ObjectID = "xNm-4u-KXC"; */ +"xNm-4u-KXC.text" = "Log level "; + +/* Class = "UILabel"; text = "Title"; ObjectID = "yyg-UZ-xh4"; */ +"yyg-UZ-xh4.text" = "Title"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "zz2-Zb-R72"; */ +"zz2-Zb-R72.text" = "Title"; diff --git a/Surf/en.lproj/ana.strings b/Surf/en.lproj/ana.strings new file mode 100644 index 0000000..0db9030 --- /dev/null +++ b/Surf/en.lproj/ana.strings @@ -0,0 +1,153 @@ + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "0L8-Tk-DNu"; */ +"0L8-Tk-DNu.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "0et-Ao-21C"; */ +"0et-Ao-21C.text" = "Upload:"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "1VX-Sh-TYI"; */ +"1VX-Sh-TYI.text" = "Label"; + +/* Class = "UILabel"; text = "Rule Testing"; ObjectID = "1qA-Qp-a7f"; */ +"1qA-Qp-a7f.text" = "Rule Testing"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "3I0-eL-4WW"; */ +"3I0-eL-4WW.text" = "Title"; + +/* Class = "UITabBarItem"; title = "Analyze"; ObjectID = "49F-E9-XLp"; */ +"49F-E9-XLp.title" = "Analyze"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "6Lw-p1-kfH"; */ +"6Lw-p1-kfH.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Rule Testing"; ObjectID = "70x-fn-iXp"; */ +"70x-fn-iXp.text" = "Rule Testing"; + +/* Class = "UILabel"; text = "Transfer"; ObjectID = "73y-Av-kdv"; */ +"73y-Av-kdv.text" = "Transfer"; + +/* Class = "UILabel"; text = "Timing"; ObjectID = "7gj-VJ-LEI"; */ +"7gj-VJ-LEI.text" = "Timing"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "EAT-ec-s8R"; */ +"EAT-ec-s8R.text" = "Download:"; + +/* Class = "UILabel"; text = "L"; ObjectID = "Ewi-TR-1PS"; */ +"Ewi-TR-1PS.text" = "L"; + +/* Class = "UILabel"; text = "REquest Header"; ObjectID = "GHc-x0-4Qk"; */ +"GHc-x0-4Qk.text" = "REquest Header"; + +/* Class = "UITextView"; text = "logo info "; ObjectID = "GJv-lC-J9C"; */ +"GJv-lC-J9C.text" = "logo info "; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "IO4-xz-7eJ"; */ +"IO4-xz-7eJ.text" = "Upload:"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "ITh-r5-rR5"; */ +"ITh-r5-rR5.text" = "Label"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "LWX-Xx-cfD"; */ +"LWX-Xx-cfD.text" = "Subtitle"; + +/* Class = "UILabel"; text = "L"; ObjectID = "Lfy-4E-S1f"; */ +"Lfy-4E-S1f.text" = "L"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "Lpj-9Y-NTI"; */ +"Lpj-9Y-NTI.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "MYi-Y5-T5f"; */ +"MYi-Y5-T5f.text" = "Label"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Pfh-fC-BR4"; */ +"Pfh-fC-BR4.text" = "Title"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Pjb-3z-tnO"; */ +"Pjb-3z-tnO.text" = "Title"; + +/* Class = "UILabel"; text = "Timing"; ObjectID = "QMh-ZJ-lae"; */ +"QMh-ZJ-lae.text" = "Timing"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "SkG-8a-v2A"; */ +"SkG-8a-v2A.text" = "Download:"; + +/* Class = "UILabel"; text = "L"; ObjectID = "VEL-Zx-cI5"; */ +"VEL-Zx-cI5.text" = "L"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "XM1-Fu-wzo"; */ +"XM1-Fu-wzo.text" = "Download:"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "XMa-y4-cOQ"; */ +"XMa-y4-cOQ.text" = "Label"; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "Z7P-wu-wpo"; */ +"Z7P-wu-wpo.text" = "Upload:"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Zrm-IS-WV9"; */ +"Zrm-IS-WV9.text" = "Title"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "aJ5-Vf-lrM"; */ +"aJ5-Vf-lrM.text" = "Download:"; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "bIh-Wc-3c3"; */ +"bIh-Wc-3c3.text" = "Upload:"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "emA-hx-ZeC"; */ +"emA-hx-ZeC.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Establish"; ObjectID = "f6c-qP-rRP"; */ +"f6c-qP-rRP.text" = "Establish"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "grS-rQ-WIL"; */ +"grS-rQ-WIL.text" = "Download:"; + +/* Class = "UILabel"; text = "IP Routing"; ObjectID = "h4d-xC-nbC"; */ +"h4d-xC-nbC.text" = "IP Routing"; + +/* Class = "UILabel"; text = "Transfer"; ObjectID = "hkO-Td-0gL"; */ +"hkO-Td-0gL.text" = "Transfer"; + +/* Class = "UILabel"; text = "REquest Header"; ObjectID = "k2l-uA-O8S"; */ +"k2l-uA-O8S.text" = "REquest Header"; + +/* Class = "UILabel"; text = "L"; ObjectID = "kdb-dn-pIx"; */ +"kdb-dn-pIx.text" = "L"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "kzj-nL-SJo"; */ +"kzj-nL-SJo.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Traffice Usage"; ObjectID = "nyy-oa-eRH"; */ +"nyy-oa-eRH.text" = "Traffice Usage"; + +/* Class = "UILabel"; text = "IP Routing"; ObjectID = "ozq-lF-gOx"; */ +"ozq-lF-gOx.text" = "IP Routing"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "r8L-Ct-ivs"; */ +"r8L-Ct-ivs.text" = "Subtitle"; + +/* Class = "UILabel"; text = "L"; ObjectID = "s3c-D5-ePg"; */ +"s3c-D5-ePg.text" = "L"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "sJN-ng-to0"; */ +"sJN-ng-to0.text" = "Title"; + +/* Class = "UILabel"; text = "L"; ObjectID = "smB-zL-dVS"; */ +"smB-zL-dVS.text" = "L"; + +/* Class = "UILabel"; text = "Traffice Usage"; ObjectID = "srJ-C5-rL0"; */ +"srJ-C5-rL0.text" = "Traffice Usage"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "wCF-yO-AEh"; */ +"wCF-yO-AEh.text" = "Title"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "wKI-Nd-XNA"; */ +"wKI-Nd-XNA.text" = "Download:"; + +/* Class = "UIButton"; normalTitle = "Delete All"; ObjectID = "wYD-Sb-iBf"; */ +"wYD-Sb-iBf.normalTitle" = "Delete All"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "wdN-fx-Hjg"; */ +"wdN-fx-Hjg.text" = "Title"; + +/* Class = "UILabel"; text = "Establish"; ObjectID = "yrc-rh-64Y"; */ +"yrc-rh-64Y.text" = "Establish"; diff --git a/Surf/iCloudViewController.swift b/Surf/iCloudViewController.swift new file mode 100644 index 0000000..45ac9c0 --- /dev/null +++ b/Surf/iCloudViewController.swift @@ -0,0 +1,108 @@ +// +// iCloudViewController.swift +// Surf +// +// Created by 孔祥波 on 24/03/2017. +// Copyright © 2017 abigt. All rights reserved. +// + +import UIKit + +class iCloudViewController: UIViewController { + + @IBOutlet weak var iswitch:UISwitch! + override func viewDidLoad() { + super.viewDidLoad() + let e = UserDefaults.standard.bool(forKey: "iCloudEnable") + iswitch.isOn = e + if iswitch.isOn { + sync() + } + // Do any additional setup after loading the view. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + func moverToiCloud(url:URL){ + let u = applicationDocumentsDirectory + do { + let fs = try fm.contentsOfDirectory(atPath: (u.path)) + for fp in fs { + if fp.hasSuffix(configExt) { + + let dest = url.appendingPathComponent(fp) + let src = u.appendingPathComponent(fp) + // let data = NSData.init(contentsOfURL: src) + // let doc = UIDocument.init(fileURL: dest) + // try doc.loadFromContents(data!, ofType: "public.text") + // doc.saveToURL(dest, forSaveOperation: UIDocumentSaveForOverwriting, completionHandler: { (t) in + // if t { + // print("\(fp) save ok ") + // } + // }) + if FileManager.default.fileExists(atPath: dest.path) { + + }else { + try fm.copyItem(at: src, to: dest) + print("copy \(dest.path)") + } + + } + + } + }catch let e as NSError{ + print("\(e.localizedDescription)") + DispatchQueue.main.async(execute: { [weak self] in + //self!.alertMessageAction("\(e.description)", complete: nil) + + }) + + + } + + + } + @IBAction func iCloud(_ sender:UISwitch){ + if sender.isOn { + UserDefaults.standard.set(true, forKey: "iCloudEnable") + } + let app = UIApplication.shared.delegate as! AppDelegate + app.iCloudEnable = sender.isOn + if sender.isOn { + sync() + } + + + + } + + func sync() { + DispatchQueue.global().async(execute: { [weak self] in + let countainer = FileManager.default.url(forUbiquityContainerIdentifier: nil) + print("countainer:url \(String(describing: countainer))") + let documentsDirectory = countainer!.appendingPathComponent("Documents"); + if !FileManager.default.fileExists(atPath: documentsDirectory.path){ + try! FileManager.default.createDirectory(atPath: documentsDirectory.path, withIntermediateDirectories: false, attributes: nil) + } + self!.moverToiCloud(url: documentsDirectory) + if (countainer != nil) { + DispatchQueue.main.async(execute: { + //self?.alertMessageAction("icloud sync ok", complete: nil) + }) + + } + }) + } + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Surf/iTunesFileTableViewController.swift b/Surf/iTunesFileTableViewController.swift new file mode 100644 index 0000000..3456643 --- /dev/null +++ b/Surf/iTunesFileTableViewController.swift @@ -0,0 +1,80 @@ +// +// iTunesFileTableViewController.swift +// Surf +// +// Created by abigt on 16/1/18. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit + +@objc protocol AddFileDelegate:class { + func importFileConfig(controller: iTunesFileTableViewController, config:String)// file name + func cancelSelect(controller: iTunesFileTableViewController)// file name +} +class iTunesFileTableViewController: UITableViewController { + + var delegate:AddFileDelegate? + var iTunesFiles:[String] = [] + @objc func scanJsonsFile() { + if iTunesFiles.count > 0 { + iTunesFiles.removeAll() + } + let files = try! fm.contentsOfDirectory(atPath: applicationDocumentsDirectory.path) + for f in files { + if let x = f.components(separatedBy: ".").last { + if x == ".conf" { + iTunesFiles.append(f) + } + + } + } + if iTunesFiles.count > 0 { + tableView.reloadData() + } + } + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Please Select config file" + self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(barButtonSystemItem: .cancel, target: self, action: #selector(iTunesFileTableViewController.cancelAction(_:))) + self.navigationItem.leftBarButtonItem = UIBarButtonItem.init(title: "Refresh", style: .plain, target: self, action: #selector(iTunesFileTableViewController.scanJsonsFile)) + scanJsonsFile() + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + var v:UIAlertController + if iTunesFiles.count == 0 { + //don't found config + v = UIAlertController(title: "Alert", message: "Please use iTunes add Config File(\(configExt)) and Retry", preferredStyle: .alert) + let action = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction) -> Void in + } + v.addAction(action) + self.present(v, animated: true) { () -> Void in + + } + } + + } + @objc func cancelAction(_ sender:AnyObject?){ + delegate?.cancelSelect(controller: self) + } + override func numberOfSections(in tableView: UITableView) -> Int { + + + return 1 + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return iTunesFiles.count + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "fileSharing") + cell?.textLabel?.text = iTunesFiles[indexPath.row] + return cell! + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath, animated: false) + delegate?.importFileConfig(controller: self, config: iTunesFiles[indexPath.row]) + } +} diff --git a/Surf/imageView.storyboard b/Surf/imageView.storyboard new file mode 100644 index 0000000..24f2d86 --- /dev/null +++ b/Surf/imageView.storyboard @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Surf/ionicons.ttf b/Surf/ionicons.ttf new file mode 100755 index 0000000..c4e4632 Binary files /dev/null and b/Surf/ionicons.ttf differ diff --git a/Surf/logo.png b/Surf/logo.png new file mode 100644 index 0000000..c7b1f75 Binary files /dev/null and b/Surf/logo.png differ diff --git a/Surf/rules_public.conf b/Surf/rules_public.conf new file mode 100644 index 0000000..fee83b5 --- /dev/null +++ b/Surf/rules_public.conf @@ -0,0 +1,4314 @@ +###################################################################### +# By JAY.C +# 2016.4.9 +# https://qingjie.me +# weibo@dbgeek +# Q群:817167 +# 🇯🇵 🇸🇬 🇰🇷 🇺🇸 🇨🇳 🇭🇰 🇼🇸 +# 更新日志、配置方法、高级运用,请进入博客查看! +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! +# 4.7 更新TTG规则,Snapchat修复,头条修复 +###################################################################### + + +[General] +skip-proxy = 192.168.0.0/16, 10.0.0.0/8, 172.0.0.0/8, 127.0.0.0/24,100.64.0.0/10, localhost, *.local, e.crashlytics.com +#bypass-tun = 192.168.0.0/16, 10.0.0.0/8, 172.0.0.0/8, 127.0.0.0/24, del 101.228.0.0/14, +bypass-tun = 10.0.0.0/8, 172.0.0.0/8, 0.0.0.0/8, 1.0.0.0/9, 1.160.0.0/11, 1.192.0.0/11, 10.0.0.0/8, 14.0.0.0/11, 14.96.0.0/11, 14.128.0.0/11, 14.192.0.0/11, 27.0.0.0/10, 27.96.0.0/11, 27.128.0.0/9, 36.0.0.0/10, 36.96.0.0/11, 36.128.0.0/9, 39.0.0.0/11, 39.64.0.0/10, 39.128.0.0/10, 42.0.0.0/8, 43.224.0.0/11, 45.64.0.0/10, 47.64.0.0/10, 49.0.0.0/9, 49.128.0.0/11, 49.192.0.0/10, 54.192.0.0/11, 58.0.0.0/9, 58.128.0.0/11, 58.192.0.0/10, 59.32.0.0/11, 59.64.0.0/10, 59.128.0.0/9, 60.0.0.0/10, 60.160.0.0/11, 60.192.0.0/10, 61.0.0.0/10, 61.64.0.0/11, 61.128.0.0/10, 61.224.0.0/11, 100.64.0.0/10, 101.0.0.0/9, 101.128.0.0/11, 101.192.0.0/11, 101.232.0.0/13, 101.240.0.0/12, 103.0.0.0/10, 103.192.0.0/10, 106.224.0.0/11, 110.0.0.0/8, 111.0.0.0/11, 111.32.0.0/12, 111.48.0.0/13, 111.56.0.0/14, 111.60.0.0/15, 111.62.0.0/16, 111.64.0.0/10, 111.128.0.0/10, 111.192.0.0/13, 111.200.0.0/14, 111.204.0.0/15, 111.207.0.0/16, 111.208.0.0/12, 111.224.0.0/11, 112.0.0.0/9, 112.128.0.0/11, 112.192.0.0/10, 113.0.0.0/9, 113.128.0.0/11, 113.192.0.0/10, 114.0.0.0/9, 114.128.0.0/11, 114.192.0.0/10, 115.0.0.0/8, 116.0.0.0/8, 117.0.0.0/9, 117.128.0.0/10, 118.0.0.0/11, 118.64.0.0/10, 118.128.0.0/9, 119.0.0.0/9, 119.128.0.0/10, 119.224.0.0/11, 120.0.0.0/10, 120.64.0.0/11, 120.128.0.0/11, 120.192.0.0/10, 121.0.0.0/9, 121.192.0.0/10, 122.0.0.0/8, 123.0.0.0/10, 123.64.0.0/11, 123.96.0.0/12, 123.112.0.0/13, 123.120.0.0/14, 123.124.0.0/16, 124.0.0.0/8, 125.0.0.0/9, 125.160.0.0/11, 125.192.0.0/10, 127.0.0.0/8, 139.0.0.0/11, 139.128.0.0/9, 140.64.0.0/11, 140.128.0.0/11, 140.192.0.0/10, 144.0.0.0/10, 144.96.0.0/11, 144.224.0.0/11, 150.0.0.0/11, 150.96.0.0/11, 150.128.0.0/11, 150.192.0.0/10, 152.96.0.0/11, 153.0.0.0/10, 153.96.0.0/11, 157.0.0.0/10, 157.96.0.0/11, 157.128.0.0/11, 157.224.0.0/11, 159.224.0.0/11, 161.192.0.0/11, 162.96.0.0/11, 163.0.0.0/10, 163.96.0.0/11, 163.128.0.0/10, 163.192.0.0/11, 166.96.0.0/11, 167.128.0.0/10, 167.192.0.0/11, 168.160.0.0/11, 169.254.0.0/16, 171.0.0.0/9, 171.192.0.0/11, 172.16.0.0/12, 175.0.0.0/9, 175.128.0.0/10, 180.64.0.0/10, 180.128.0.0/9, 182.0.0.0/8, 183.0.0.0/10, 183.64.0.0/11, 183.128.0.0/9, 192.0.0.0/24, 192.0.2.0/24, 192.88.99.0/24, 192.96.0.0/11, 192.160.0.0/11, 198.18.0.0/15, 198.51.100.0/24, 202.0.0.0/9, 202.128.0.0/10, 202.192.0.0/11, 203.0.0.0/9, 203.128.0.0/10, 203.192.0.0/11, 210.0.0.0/10, 210.64.0.0/11, 210.160.0.0/11, 210.192.0.0/11, 211.64.0.0/10, 211.128.0.0/10, 218.0.0.0/9, 218.160.0.0/11, 218.192.0.0/10, 219.64.0.0/11, 219.128.0.0/11, 219.192.0.0/10, 220.96.0.0/11, 220.128.0.0/9, 221.0.0.0/11, 221.96.0.0/11, 221.128.0.0/9, 222.0.0.0/8, 223.0.0.0/11, 223.64.0.0/10, 223.128.0.0/9 + + +#屏蔽DNS解析交给运营商解析,如果您网络情况不理想可以使用 +#dns-server = 119.29.29.29, 223.5.5.5, 114.114.114.114 + +loglevel = notify + +# MAC版代理端口配置 # +interface = 0.0.0.0 +port = 8000 +################### + + +[Proxy] +直连 = direct +🇨🇳 CN线路 = custom,qingjie.me,8888,rc4-md5,password,https://down.qingjie.me:443/surge/ss.module,tcp-fast-open=true +🇭🇰 HK线路 = custom,qingjie.me,8888,rc4-md5,password,https://down.qingjie.me:443/surge/ss.module,tcp-fast-open=true +🇭🇰 HK-Azu = custom,qingjie.me,8888,rc4-md5,password,https://down.qingjie.me:443/surge/ss.module,tcp-fast-open=true +🇰🇷 KR线路 = custom,qingjie.me,8888,rc4-md5,password,https://down.qingjie.me:443/surge/ss.module,tcp-fast-open=true + + + +[Proxy Group] +Proxy = select,直连,🇨🇳 CN线路,🇭🇰 HK线路,🇭🇰 HK-Azu,🇰🇷 KR线路 + + + +[Host] + + + +[Rule] + +# 屏蔽升级 By @036 +DOMAIN-SUFFIX,appldnld.apple.com,DIRECT +DOMAIN-SUFFIX,mesu.apple.com,DIRECT + +# Apple PACKAGE PROXY-A +# 建议为代理模式 +DOMAIN,beta.itunes.apple.com,Proxy +DOMAIN,init.itunes.apple.com,DIRECT +DOMAIN,audio.itunes.apple.com,DIRECT +DOMAIN,iosapps.itunes.apple.com,DIRECT + + +# Apple PACKAGE DIRECT +DOMAIN-SUFFIX,appldnld.apple.com,DIRECT +DOMAIN-SUFFIX,adcdownload.apple.com,DIRECT +DOMAIN-SUFFIX,lcdn-registration.apple.com,DIRECT +DOMAIN-SUFFIX,swcdn.apple.com,DIRECT +DOMAIN-SUFFIX,phobos.apple.com,DIRECT +DOMAIN-SUFFIX,ls.apple.com,DIRECT +DOMAIN-SUFFIX,cdn-apple.com,DIRECT + + +# Apple PACKAGE PROXY-B +# 建议直连,较高要求可以改变连接方式 +DOMAIN-SUFFIX,icloud.com,DIRECT +DOMAIN-SUFFIX,me.com,DIRECT +DOMAIN-SUFFIX,apple.com,DIRECT +DOMAIN-SUFFIX,itunes.apple.com,DIRECT +DOMAIN-SUFFIX,mzstatic.com,DIRECT + + + +# Block privacy trackers +DOMAIN,alexa.links.cn,REJECT +DOMAIN,api.amplitude.com,REJECT +DOMAIN,app.sysdigcloud.com,REJECT +DOMAIN,bam.nr-data.net,REJECT +DOMAIN,bi-collector.oneapm.com,REJECT +DOMAIN,cdn.mxpnl.com,REJECT +DOMAIN,collector.githubapp.com,REJECT +DOMAIN,counter.kingsoft.com,REJECT +DOMAIN,js-agent.newrelic.com,REJECT +DOMAIN,pixel.redditmedia.com,REJECT +DOMAIN,pixel.wp.com,REJECT +DOMAIN,sfsapi.micloud.xiaomi.net,REJECT +DOMAIN,stat.m.jd.com,REJECT +DOMAIN,ads.mopub.com,REJECT +DOMAIN,analytics.mopub.com,REJECT +DOMAIN,api.tapstream.com,REJECT +DOMAIN,api.adform.com,REJECT +DOMAIN,e.apsalar.com,REJECT +DOMAIN,syndication.streamads.yahoo.com,REJECT + +# Youku +DOMAIN,ad.api.3g.youku.com,REJECT + +# Tudou +DOMAIN,ad.api.3g.tudou.com,REJECT +DOMAIN,adcontrol.tudou.com,REJECT +DOMAIN,adplay.tudou.com,REJECT +DOMAIN,stat.tudou.com,REJECT +DOMAIN,stats.tudou.com,REJECT + +# Alibaba +DOMAIN,acjs.aliyun.com,REJECT +DOMAIN,adash.m.taobao.com,REJECT +DOMAIN,pindao.huoban.taobao.com,REJECT +DOMAIN,hydra.alibaba.com,REJECT +DOMAIN,rj.m.taobao.com,REJECT +DOMAIN,apoll.m.taobao.com,REJECT + +# Letv +DOMAIN,ark.letv.com,REJECT +DOMAIN,n.mark.letv.com,REJECT +DOMAIN,stat.letv.com,REJECT +DOMAIN,letv.allyes.com,REJECT +DOMAIN,dc.letv.com,REJECT +DOMAIN,fz.letv.com,REJECT +DOMAIN,plog.dc.letv.com,REJECT +DOMAIN,dev.dc.letv.com,REJECT +DOMAIN,pro.letv.com,REJECT +DOMAIN,pro.hoye.letv.com,REJECT + +# PPLIVE +DOMAIN,asimgs.pplive.cn,REJECT + +# Didi +DOMAIN,static.diditaxi.com.cn,REJECT + +# Sohu +DOMAIN,data.vod.itc.cn,REJECT +DOMAIN,imp.optaim.com,REJECT +DOMAIN,mmg.aty.sohu.com,REJECT +DOMAIN,vsohu.admaster.com.cn,REJECT + +# Fengxing +DOMAIN,pub.funshion.com,REJECT + +# 10086 +DOMAIN,go.10086.cn,REJECT +DOMAIN,mobile.log.hunantv.com,REJECT + +# Meitu +DOMAIN,corp.meitu.com,REJECT +DOMAIN,gg.meitu.com,REJECT +DOMAIN,message.meitu.com,REJECT +DOMAIN,tuiguang.meitu.com,REJECT +DOMAIN,xiuxiu.android.dl.meitu.com,REJECT +DOMAIN,xiuxiu.mobile.meitudata.com,REJECT +DOMAIN,a.koudai.com,REJECT + +# QQ +DOMAIN,lives.l.qq.com,REJECT +DOMAIN,monitor.uu.qq.com,REJECT +DOMAIN,omgmta.qq.com,REJECT +DOMAIN,pingjs.qq.com,REJECT +DOMAIN,pingma.qq.com,REJECT +DOMAIN,tajs.qq.com,REJECT +DOMAIN,tcss.qq.com,REJECT + +# 163 +DOMAIN,dsp.youdao.com,REJECT +DOMAIN,g.163.com,REJECT +DOMAIN,g1.163.com,REJECT +DOMAIN,temp.163.com,REJECT +DOMAIN,analytics.163.com,REJECT + +DOMAIN,img1.126.net,REJECT +DOMAIN,f1.p0y.cn,REJECT +DOMAIN,f2.p0y.cn,REJECT + +# Ximalaya +DOMAIN,ad.ximalaya.com,REJECT +DOMAIN,ad.test.ximalaya.com,REJECT + +# Kuwo +DOMAIN,g.kuwo.cn,REJECT +DOMAIN,log.kuwo.cn,REJECT +DOMAIN,updatepage.kuwo.cn,REJECT +DOMAIN,wa.kuwo.cn,REJECT +DOMAIN,webstat.kuwo.cn,REJECT +DOMAIN,g.koowo.com,REJECT +DOMAIN,wa.koowo.com,REJECT + +# Kugou +#DOMAIN,minidcsc.kugou.com,REJECT +#DOMAIN,cpm.sdn.kugou.com,REJECT +#DOMAIN,downmini.kugou.com,REJECT +#DOMAIN,downmobile.kugou.com,REJECT +#DOMAIN,gad.kugou.com,REJECT +#DOMAIN,gg.kugou.com,REJECT +#DOMAIN,install.kugou.com,REJECT +#DOMAIN,log.stat.kugou.com,REJECT +#DOMAIN,logstat.kugou.com,REJECT +#DOMAIN,mvads.kugou.com,REJECT +#DOMAIN,opt.kugou.com,REJECT +#DOMAIN,p.kugou.com,REJECT +#DOMAIN,sdn.kugou.com,REJECT +#DOMAIN,softstart.kugou.com,REJECT +#DOMAIN,tj.kugou.com,REJECT + +# Feng By @撸大湿太 +DOMAIN,yes1.feng.com,REJECT + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + +# Fenghuang +DOMAIN,api.newad.ifeng.com,REJECT + +# Duiba +DOMAIN,duiba.com.cn,REJECT +DOMAIN,dui88.com,REJECT + +# Mangguo +DOMAIN,mp4.res.hunantv.com,REJECT + +# 12306 +DOMAIN,ad.12306.cn,REJECT +DOMAIN,e.domob.com.cn,REJECT +DOMAIN,e.domob.cn,REJECT +DOMAIN,sm.domobcdn.com,REJECT + +# Douban +DOMAIN,erebor.douban.com,REJECT + +#DOMAIN,msg.video.qiyi.com,REJECT +#DOMAIN,msg2.video.qiyi.com,REJECT +#DOMAIN,msg.71.am,REJECT +DOMAIN,meta.video.qiyi.com,REJECT +DOMAIN,data.video.qiyi.com,REJECT +DOMAIN,api.cupid.iqiyi.com,REJECT +DOMAIN,paopao.iqiyi.com,REJECT + + +# Baidu +DOMAIN,cbjs.baidu.com,REJECT +DOMAIN,cpro.baidu.com,REJECT +DOMAIN,eclick.baidu.com,REJECT +DOMAIN,entry.baidu.com,REJECT +DOMAIN,hm.baidu.com,REJECT +DOMAIN,hmma.baidu.com,REJECT +DOMAIN,mobads-logs.baidu.com,REJECT +DOMAIN,mobads.baidu.com,REJECT +DOMAIN,mtj.baidu.com,REJECT +DOMAIN,nsclick.baidu.com,REJECT +DOMAIN,spcode.baidu.com,REJECT +DOMAIN,static.tieba.baidu.com,REJECT +DOMAIN,ucstat.baidu.com,REJECT +DOMAIN,union.baidu.com,REJECT +DOMAIN,imageplus.baidu.com,REJECT + + +# Tieba +DOMAIN,res.limei.com,REJECT +DOMAIN,res.cocounion.com,REJECT + +# SpeedTest +DOMAIN,ads.ookla.com,REJECT +DOMAIN,cdn.ads.ookla.com,REJECT + +# App Laugh Skin +DOMAIN,u1.img.mobile.sina.cn,REJECT + +# 360buy +DOMAIN,union.m.jd.com,REJECT + +# Wechat By @Shoriyami +DOMAIN,qqvideo.tc.qq.com,REJECT + +# Toutiao +DOMAIN,ad.toutiao.com,REJECT +DOMAIN,gma.alicdn.com,REJECT + +# Wasu +DOMAIN,acsystem.wasu.cn,REJECT +DOMAIN,www.gridsum.com,REJECT +DOMAIN,g.gridsum.com,REJECT +DOMAIN,recv-wd.gridsumdissector.com,REJECT +DOMAIN,static.gridsumdissector.com,REJECT + +# Weibo +DOMAIN,alitui.weibo.com,REJECT +DOMAIN,biz.weibo.com,REJECT +DOMAIN,c.biz.weibo.com,REJECT +DOMAIN,game.weibo.com,REJECT +DOMAIN,c.wcpt.biz.weibo.com,REJECT +DOMAIN,s.alitui.weibo.com,REJECT +DOMAIN,zc.biz.weibo.com,REJECT +DOMAIN,zymo.mps.weibo.com,REJECT +DOMAIN,game.weibo.cn,REJECT +DOMAIN,m.game.weibo.cn,REJECT +DOMAIN,promote.biz.weibo.cn,REJECT +DOMAIN,adimg.mobile.sina.cn,REJECT +DOMAIN,newspush.sinajs.cn,REJECT +DOMAIN,sdkapp.mobile.sina.cn,REJECT +DOMAIN,sdkclick.mobile.sina.cn,REJECT +DOMAIN,trends.mobile.sina.cn,REJECT +DOMAIN,wbapp.mobile.sina.cn,REJECT +DOMAIN,wbclick.mobile.sina.cn,REJECT +DOMAIN,wbpctips.mobile.sina.cn,REJECT +DOMAIN,ota.pay.mobile.sina.cn,REJECT +DOMAIN,pay.mobile.sina.cn,REJECT + +# Qiushibaike +DOMAIN,mi.gdt.qq.com,REJECT + +# Sina +DOMAIN,sax.sina.cn,REJECT + +# Xunfei +DOMAIN,bj.imp.voiceads.cn,REJECT + +# Systemav +DOMAIN,m.madthumbs.com,REJECT + +# Google +DOMAIN,csi.gstatic.com,REJECT +DOMAIN,static.googleadsserving.cn,REJECT +DOMAIN,ads.google.com,REJECT +DOMAIN,afd.l.google.com,REJECT +DOMAIN,mobileads.google.com,REJECT +DOMAIN,pagead-tpc.l.google.com,REJECT +DOMAIN,pagead.google.com,REJECT +DOMAIN,pagead.l.google.com,REJECT +DOMAIN,partnerad.l.google.com,REJECT +DOMAIN,ads.youtube.com,REJECT +DOMAIN,ads.gmodules.com,REJECT +DOMAIN,badad.googleplex.com,REJECT +DOMAIN,www.googlecommerce.com,REJECT +DOMAIN,www.googletagmanager.com,REJECT +DOMAIN,service.urchin.com,REJECT + +# AutoHome +DOMAIN,adm3.autoimg.cn,REJECT +DOMAIN,adm0.autoimg.cn,REJECT +DOMAIN,img2.autoimg.cn,REJECT + +# Dropbox +DOMAIN,d.dropbox.com,REJECT +DOMAIN,dl-debug.dropbox.com,REJECT + +# Twitter +DOMAIN,syndication.twitter.com,REJECT + +# DSP +DOMAIN,dsp.lomark.cn,REJECT + +# VIU By +DOMAIN,stream-hk.viu.com,Proxy +DOMAIN,global.adserver.yahoo.com,REJECT + + +# CDN +DOMAIN,init.icloud-analysis.com, REJECT +DOMAIN,zhihu-analytics.zhihu.com,REJECT +DOMAIN,log.cmbchina.com,REJECT +DOMAIN,api.segment.io,REJECT +DOMAIN,api.instabug.com,REJECT +DOMAIN,adlog.flurry.com,REJECT +DOMAIN,ads.flurry.com,REJECT +DOMAIN,fonts.googleapis.com,REJECT + + +DOMAIN,r1.ykimg.com,REJECT +DOMAIN,v.gdt.qq.com,REJECT +DOMAIN,sd.domob.cn,REJECT + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + +DOMAIN-SUFFIX,51.la,REJECT +DOMAIN-SUFFIX,adjust.com,REJECT +DOMAIN-SUFFIX,adjust.io,REJECT +DOMAIN-SUFFIX,beacon.tingyun.com,REJECT +DOMAIN-SUFFIX,cmcore.com,REJECT +DOMAIN-SUFFIX,coremetrics.com,REJECT +DOMAIN-SUFFIX,irs01.com,REJECT +DOMAIN-SUFFIX,madmini.com,REJECT +DOMAIN-SUFFIX,mmstat.com,REJECT +DOMAIN-SUFFIX,optimizelyapis.com,REJECT +DOMAIN-SUFFIX,sitemeter.com,REJECT +DOMAIN-SUFFIX,wrating.com,REJECT +DOMAIN-SUFFIX,99click.com,REJECT +DOMAIN-SUFFIX,acs86.com,REJECT +DOMAIN-SUFFIX,adchina.com,REJECT +DOMAIN-SUFFIX,adcome.cn,REJECT +DOMAIN-SUFFIX,adinfuse.com,REJECT +DOMAIN-SUFFIX,admaster.com.cn,REJECT +DOMAIN-SUFFIX,adnxs.com,REJECT +DOMAIN-SUFFIX,ads.yahoo.com,REJECT +DOMAIN-SUFFIX,adsage.cn,REJECT +DOMAIN-SUFFIX,adsage.com,REJECT +DOMAIN-SUFFIX,adsmogo.org,REJECT +DOMAIN-SUFFIX,aduu.cn,REJECT +DOMAIN-SUFFIX,advertising.com,REJECT +DOMAIN-SUFFIX,adview.cn,REJECT +DOMAIN-SUFFIX,adwhirl.com,REJECT +DOMAIN-SUFFIX,adwo.com,REJECT +DOMAIN-SUFFIX,adxmi.com,REJECT +DOMAIN-SUFFIX,adzerk.net,REJECT +DOMAIN-SUFFIX,allyes.com,REJECT +DOMAIN-SUFFIX,anquan.org,REJECT +DOMAIN-SUFFIX,appads.com,REJECT +DOMAIN-SUFFIX,applifier.com,REJECT +DOMAIN-SUFFIX,applovin.com,REJECT +DOMAIN-SUFFIX,appsflyer.com,REJECT +DOMAIN-SUFFIX,biddingx.com,REJECT +DOMAIN-SUFFIX,chartboost.com,REJECT +DOMAIN-SUFFIX,clicktracks.com,REJECT +DOMAIN-SUFFIX,clickzs.com,REJECT +DOMAIN-SUFFIX,duomeng.cn,REJECT +DOMAIN-SUFFIX,duomeng.net,REJECT +DOMAIN-SUFFIX,duomeng.org,REJECT +DOMAIN-SUFFIX,guohead.com,REJECT +DOMAIN-SUFFIX,guomob.com,REJECT +DOMAIN-SUFFIX,immob.cn,REJECT +DOMAIN-SUFFIX,inmobi.com,REJECT +DOMAIN-SUFFIX,intely.cn,REJECT +DOMAIN-SUFFIX,ipinyou.com,REJECT +DOMAIN-SUFFIX,kejet.net,REJECT +DOMAIN-SUFFIX,localytics.com,REJECT +DOMAIN-SUFFIX,mediav.com,REJECT +DOMAIN-SUFFIX,miaozhen.com,REJECT +DOMAIN-SUFFIX,mobclix.com,REJECT +DOMAIN-SUFFIX,oadz.com,REJECT +DOMAIN-SUFFIX,optaim.com,REJECT +DOMAIN-SUFFIX,optimix.asia,REJECT +DOMAIN-SUFFIX,quantserve.com,REJECT +DOMAIN-SUFFIX,reachmax.cn,REJECT +DOMAIN-SUFFIX,responsys.net,REJECT +DOMAIN-SUFFIX,serving-sys.com,REJECT +DOMAIN-SUFFIX,smartmad.com,REJECT +DOMAIN-SUFFIX,smartadserver.com,REJECT +DOMAIN-SUFFIX,sponsorpay.com,REJECT +DOMAIN-SUFFIX,switchadhub.com,REJECT +DOMAIN-SUFFIX,tanx.com,REJECT +DOMAIN-SUFFIX,tapjoyads.com,REJECT +DOMAIN-SUFFIX,thoughtleadr.com,REJECT +DOMAIN-SUFFIX,unimhk.com,REJECT +DOMAIN-SUFFIX,unlitui.com,REJECT +DOMAIN-SUFFIX,uyunad.com,REJECT +DOMAIN-SUFFIX,vamaker.com,REJECT +DOMAIN-SUFFIX,waps.cn,REJECT +DOMAIN-SUFFIX,wiyun.com,REJECT +DOMAIN-SUFFIX,wooboo.com.cn,REJECT +DOMAIN-SUFFIX,wqmobile.com,REJECT +DOMAIN-SUFFIX,youmi.net,REJECT +DOMAIN-SUFFIX,zhiziyun.com,REJECT +DOMAIN-SUFFIX,segment.com,REJECT + + +# Amazon +DOMAIN-SUFFIX,amazon-adsystem.com,REJECT + +# Youku +DOMAIN-SUFFIX,atm.youku.com,REJECT + +# Alibaba +DOMAIN-SUFFIX,simaba.taobao.com,REJECT + +# Qiyi +DOMAIN-SUFFIX,cupid.iqiyi.com,REJECT +DOMAIN-SUFFIX,cupid.qiyi.com,REJECT +DOMAIN-SUFFIX,afp.qiyi.com,REJECT + +# PPTV +DOMAIN-SUFFIX,de.as.pptv.com,REJECT +DOMAIN-SUFFIX,jp.as.pptv.com,REJECT + +# Zhuishu +DOMAIN-SUFFIX,ht55.cn,REJECT + +# Sohu +DOMAIN-SUFFIX,aty.sohu.com,REJECT +#DOMAIN-SUFFIX,push.tv.sohu.com,REJECT +DOMAIN-SUFFIX,ckm.iqiyi.com,REJECT +DOMAIN-SUFFIX,statcounter.com,REJECT + +# QQ +DOMAIN-SUFFIX,beacon.qq.com,REJECT +DOMAIN-SUFFIX,pingtcss.qq.com,REJECT +DOMAIN-SUFFIX,report.qq.com,REJECT + +# 163 +DOMAIN-SUFFIX,stat.ws.126.net,REJECT +DOMAIN-SUFFIX,union.youdao.com,REJECT + +# FengyunTV By @点儿 +DOMAIN-SUFFIX,kukuplay.com,REJECT + +# Tianqitong By @ENDE +DOMAIN-SUFFIX,fastapi.net,REJECT + + +# VIU By +DOMAIN-SUFFIX,beep-bc.yahoo.com,REJECT + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + +# Baidu +DOMAIN-SUFFIX,baidustatic.com,REJECT +DOMAIN-SUFFIX,pos.baidu.com,REJECT +DOMAIN-SUFFIX,baichuan.baidu.com,REJECT +DOMAIN-SUFFIX,pos.baidu.com,REJECT +DOMAIN-SUFFIX,tuisong.baidu.com,REJECT +DOMAIN-SUFFIX,baidustatic.com,REJECT + +# Weibo +DOMAIN-SUFFIX,g.uusee.com,REJECT +DOMAIN-SUFFIX,traffic.uusee.com,REJECT +DOMAIN-SUFFIX,static.g.ppstream.com,REJECT +DOMAIN-SUFFIX,gw5.push.mcp.weibo.cn,REJECT +DOMAIN-SUFFIX,u1.img.mobile.sina.cn,REJECT + +# Sina +DOMAIN-SUFFIX,beacon.sina.com.cn,REJECT + +# Google +DOMAIN-SUFFIX,2mdn.net,REJECT +DOMAIN-SUFFIX,doubleclick.net,REJECT +DOMAIN-SUFFIX,googleadservices.com,REJECT +DOMAIN-SUFFIX,googletagservices.com,REJECT + +# Youtube +DOMAIN-SUFFIX,googleads.g.doubleclick.net,REJECT +DOMAIN-SUFFIX,ad.doubleclick.net,REJECT +DOMAIN-SUFFIX,files.adform.net,REJECT +DOMAIN-SUFFIX,secure-ds.serving-sys.com,REJECT + +# CDN +DOMAIN-SUFFIX,pubmatic.com,REJECT + +#DOMAIN-KEYWORD,cnzz,REJECT +#DOMAIN-KEYWORD,tongji,REJECT +DOMAIN-KEYWORD,trace,REJECT +#DOMAIN-KEYWORD,track,REJECT +DOMAIN-KEYWORD,traffic,REJECT +DOMAIN-KEYWORD,usage,REJECT +DOMAIN-KEYWORD,openx,REJECT +DOMAIN-KEYWORD,admob,REJECT +DOMAIN-KEYWORD,qtmojo,REJECT +DOMAIN-KEYWORD,analytics,REJECT +#DOMAIN-KEYWORD,gtimg,REJECT + + + + +# Taobao +DOMAIN,h5.m.taobao.com,DIRECT + +# Duolinguo +DOMAIN,api.mixpanel.com,DIRECT +DOMAIN,d2pur3iezf4d1j.cloudfront.net,DIRECT + +DOMAIN,wscdns.com,DIRECT + +# Synology +DOMAIN-SUFFIX,QuickConnect.to,DIRECT + +# Alipay +DOMAIN-SUFFIX,alipaylog.com,DIRECT + +# Taobao +DOMAIN-SUFFIX,taobaocdn.com,DIRECT +DOMAIN-SUFFIX,alicdn.com,DIRECT + +# 12306 +DOMAIN-SUFFIX,12306.cn,DIRECT + +# 17APP +DOMAIN-SUFFIX,17app.co,DIRECT + +# 126 +DOMAIN-SUFFIX,126.net,DIRECT +DOMAIN-SUFFIX,163.com,DIRECT +DOMAIN-SUFFIX,netnease.com,DIRECT + +# 360buy +DOMAIN-SUFFIX,360buyimg.com,DIRECT +#DOMAIN-SUFFIX,jd.com,DIRECT + +# ICBC +DOMAIN-SUFFIX,icbc.com,DIRECT + +# 10010 By ސސސސސސސސސސ +DOMAIN-SUFFIX,6-10010.com,DIRECT + + +# iMuzo +DOMAIN-SUFFIX,iheart.com,DIRECT +DOMAIN-SUFFIX,dongting.com,DIRECT +DOMAIN-SUFFIX,iyyin.com,DIRECT +DOMAIN-SUFFIX,openspeech.cn,DIRECT + + +# CDN +DOMAIN-SUFFIX,yunjiasu-cdn.net,DIRECT +DOMAIN-SUFFIX,8686c.com,DIRECT +DOMAIN-SUFFIX,ourdvs.com,DIRECT +DOMAIN-SUFFIX,spotilocal.com,DIRECT + +# CN DIRECT +DOMAIN-SUFFIX,cn,DIRECT + +# CHINA WHITE LIST +DOMAIN-SUFFIX,com.cn,DIRECT +DOMAIN-SUFFIX,edu.cn,DIRECT +DOMAIN-SUFFIX,org.cn,DIRECT +DOMAIN-SUFFIX,net.cn,DIRECT +DOMAIN-SUFFIX,gov.cn,DIRECT +DOMAIN-SUFFIX,weibo.cn,DIRECT +DOMAIN-SUFFIX,sina.cn,DIRECT +DOMAIN-SUFFIX,tbcdn.cn,DIRECT +DOMAIN-SUFFIX,sinajs.cn,DIRECT +DOMAIN-SUFFIX,amazon.cn,DIRECT +DOMAIN-SUFFIX,360.cn,DIRECT +DOMAIN-SUFFIX,flyme.cn,DIRECT +DOMAIN-SUFFIX,mtime.cn,DIRECT +DOMAIN-SUFFIX,ifanr.cn,DIRECT +DOMAIN-SUFFIX,kuwo.cn,DIRECT +DOMAIN-SUFFIX,kuaipan.cn,DIRECT +DOMAIN-SUFFIX,3g.cn,DIRECT +DOMAIN-SUFFIX,tianya.cn,DIRECT +DOMAIN-SUFFIX,url.cn,DIRECT +DOMAIN-SUFFIX,blued.cn,DIRECT +DOMAIN-SUFFIX,189.cn,DIRECT +DOMAIN-SUFFIX,10086.cn,DIRECT +DOMAIN-SUFFIX,10010.cn,DIRECT +DOMAIN-SUFFIX,uc.cn,DIRECT +DOMAIN-SUFFIX,damai.cn,DIRECT +DOMAIN-SUFFIX,suning.cn,DIRECT +DOMAIN-SUFFIX,liebao.cn,DIRECT +DOMAIN-SUFFIX,mifile.cn,DIRECT +DOMAIN-SUFFIX,voicecloud.cn,DIRECT +DOMAIN-SUFFIX,wps.cn,DIRECT +DOMAIN-SUFFIX,8684.cn,DIRECT +DOMAIN-SUFFIX,uniqlo.cn,DIRECT +DOMAIN-SUFFIX,ifeng.com,DIRECT +DOMAIN-SUFFIX,ifengimg.com,DIRECT +DOMAIN-SUFFIX,bbwc.cn,DIRECT +DOMAIN-SUFFIX,3.cn,DIRECT +DOMAIN-SUFFIX,maxthon.cn,DIRECT +DOMAIN-SUFFIX,xda.cn,DIRECT +DOMAIN-SUFFIX,cntv.cn,DIRECT +DOMAIN-SUFFIX,6.cn,DIRECT +DOMAIN-SUFFIX,meizu.cn,DIRECT +DOMAIN-SUFFIX,360doc.cn,DIRECT +DOMAIN-SUFFIX,sto.cn,DIRECT +DOMAIN-SUFFIX,xiaomi.cn,DIRECT +DOMAIN-SUFFIX,ccb.cn,DIRECT +DOMAIN-SUFFIX,macx.cn,DIRECT +DOMAIN-SUFFIX,d.cn,DIRECT +DOMAIN-SUFFIX,m1905.cn,DIRECT +DOMAIN-SUFFIX,t.cn,DIRECT +DOMAIN-SUFFIX,sh.cn,DIRECT +DOMAIN-SUFFIX,bong.cn,DIRECT +DOMAIN-SUFFIX,mafengwo.cn,DIRECT +DOMAIN-SUFFIX,ucloud.cn,DIRECT +DOMAIN-SUFFIX,xdf.cn,DIRECT +DOMAIN-SUFFIX,china.cn,DIRECT +DOMAIN-SUFFIX,ip.cn,DIRECT +DOMAIN-SUFFIX,news.cn,DIRECT +DOMAIN-SUFFIX,linux.cn,DIRECT +DOMAIN-SUFFIX,dict.cn,DIRECT +DOMAIN-SUFFIX,windowsazure.cn,DIRECT +DOMAIN-SUFFIX,dwz.cn,DIRECT +DOMAIN-SUFFIX,10010.com,DIRECT +DOMAIN-SUFFIX,115.com,DIRECT +DOMAIN-SUFFIX,123u.com,DIRECT +DOMAIN-SUFFIX,126.com,DIRECT +DOMAIN-SUFFIX,17173.com,DIRECT +DOMAIN-SUFFIX,178.com,DIRECT +DOMAIN-SUFFIX,17cdn.com,DIRECT +DOMAIN-SUFFIX,21cn.com,DIRECT +DOMAIN-SUFFIX,2288.org,DIRECT +DOMAIN-SUFFIX,3322.org,DIRECT +DOMAIN-SUFFIX,360doc.com,DIRECT +DOMAIN-SUFFIX,360safe.com,DIRECT +DOMAIN-SUFFIX,36kr.com,DIRECT +DOMAIN-SUFFIX,400gb.com,DIRECT +DOMAIN-SUFFIX,4399.com,DIRECT +DOMAIN-SUFFIX,51.la,DIRECT +DOMAIN-SUFFIX,51buy.com,DIRECT +DOMAIN-SUFFIX,51cto.com,DIRECT +DOMAIN-SUFFIX,51job.com,DIRECT +DOMAIN-SUFFIX,51jobcdn.com,DIRECT +DOMAIN-SUFFIX,5d6d.com,DIRECT +DOMAIN-SUFFIX,5d6d.net,DIRECT +DOMAIN-SUFFIX,61.com,DIRECT +DOMAIN-SUFFIX,6600.org,DIRECT +DOMAIN-SUFFIX,6rooms.com,DIRECT +DOMAIN-SUFFIX,7766.org,DIRECT +DOMAIN-SUFFIX,7k7k.com,DIRECT +DOMAIN-SUFFIX,8800.org,DIRECT +DOMAIN-SUFFIX,8866.org,DIRECT +DOMAIN-SUFFIX,90g.org,DIRECT +DOMAIN-SUFFIX,91.com,DIRECT +DOMAIN-SUFFIX,9966.org,DIRECT +DOMAIN-SUFFIX,acfun.tv,DIRECT +DOMAIN-SUFFIX,aicdn.com,DIRECT +DOMAIN-SUFFIX,ali213.net,DIRECT +DOMAIN-SUFFIX,alibaba.com,DIRECT +DOMAIN-SUFFIX,aliexpress.com,DIRECT +DOMAIN-SUFFIX,aliimg.com,DIRECT +DOMAIN-SUFFIX,alikunlun.com,DIRECT +DOMAIN-SUFFIX,alisoft.com,DIRECT +DOMAIN-SUFFIX,aliyun.com,DIRECT +DOMAIN-SUFFIX,aliyuncdn.com,DIRECT +DOMAIN-SUFFIX,aliyuncs.com,DIRECT +DOMAIN-SUFFIX,anzhi.com,DIRECT +DOMAIN-SUFFIX,appinn.com,DIRECT +DOMAIN-SUFFIX,apple.com,DIRECT +DOMAIN-SUFFIX,appsina.com,DIRECT +DOMAIN-SUFFIX,archlinuxcn.org,DIRECT +DOMAIN-SUFFIX,atpanel.com,DIRECT +DOMAIN-SUFFIX,baifendian.com,DIRECT +DOMAIN-SUFFIX,baihe.com,DIRECT +DOMAIN-SUFFIX,baixing.com,DIRECT +DOMAIN-SUFFIX,bdimg.com,DIRECT +DOMAIN-SUFFIX,bdstatic.com,DIRECT +DOMAIN-SUFFIX,bilibili.tv,DIRECT +DOMAIN-SUFFIX,blogbus.com,DIRECT +DOMAIN-SUFFIX,blueidea.com,DIRECT +DOMAIN-SUFFIX,ccb.com,DIRECT +DOMAIN-SUFFIX,cctv.com,DIRECT +DOMAIN-SUFFIX,cctvpic.com,DIRECT +DOMAIN-SUFFIX,cdn20.com,DIRECT +DOMAIN-SUFFIX,china.com,DIRECT +DOMAIN-SUFFIX,chinabyte.com,DIRECT +DOMAIN-SUFFIX,chinacache.com,DIRECT +DOMAIN-SUFFIX,chinacache.net,DIRECT +DOMAIN-SUFFIX,chinacaipu.com,DIRECT +DOMAIN-SUFFIX,chinagba.com,DIRECT +DOMAIN-SUFFIX,chinahr.com,DIRECT +DOMAIN-SUFFIX,chinajoy.net,DIRECT +DOMAIN-SUFFIX,chinamobile.com,DIRECT +DOMAIN-SUFFIX,chinanetcenter.com,DIRECT +DOMAIN-SUFFIX,chinanews.com,DIRECT +DOMAIN-SUFFIX,chinapnr.com,DIRECT +DOMAIN-SUFFIX,chinaren.com,DIRECT +DOMAIN-SUFFIX,chinaspeeds.net,DIRECT +DOMAIN-SUFFIX,chinaunix.net,DIRECT +DOMAIN-SUFFIX,chinaz.com,DIRECT +DOMAIN-SUFFIX,chint.com,DIRECT +DOMAIN-SUFFIX,chiphell.com,DIRECT +DOMAIN-SUFFIX,chuangxin.com,DIRECT +DOMAIN-SUFFIX,ci123.com,DIRECT +DOMAIN-SUFFIX,ciku5.com,DIRECT +DOMAIN-SUFFIX,citysbs.com,DIRECT +DOMAIN-SUFFIX,class.coursera.org,DIRECT +DOMAIN-SUFFIX,cloudcdn.net,DIRECT +DOMAIN-SUFFIX,cmbchina.com,DIRECT +DOMAIN-SUFFIX,cmfu.com,DIRECT +DOMAIN-SUFFIX,cmread.com,DIRECT +DOMAIN-SUFFIX,cmwb.com,DIRECT +DOMAIN-SUFFIX,cn.archive.ubuntu.com,DIRECT +DOMAIN-SUFFIX,cn.bing.com,DIRECT +DOMAIN-SUFFIX,cn.coremetrics.com,DIRECT +DOMAIN-SUFFIX,cn.debian.org,DIRECT +DOMAIN-SUFFIX,cn.msn.com,DIRECT +DOMAIN-SUFFIX,cnak2.englishtown.com,DIRECT +DOMAIN-SUFFIX,cnbeta.com,DIRECT +DOMAIN-SUFFIX,cnbetacdn.com,DIRECT +DOMAIN-SUFFIX,cnblogs.com,DIRECT +DOMAIN-SUFFIX,cnepub.com,DIRECT +DOMAIN-SUFFIX,cnzz.com,DIRECT +DOMAIN-SUFFIX,comsenz.com,DIRECT +DOMAIN-SUFFIX,csdn.net,DIRECT +DOMAIN-SUFFIX,ct10000.com,DIRECT +DOMAIN-SUFFIX,ctdisk.com,DIRECT +DOMAIN-SUFFIX,dangdang.com,DIRECT +DOMAIN-SUFFIX,dbank.com,DIRECT +DOMAIN-SUFFIX,dedecms.com,DIRECT +DOMAIN-SUFFIX,diandian.com,DIRECT +DOMAIN-SUFFIX,dianping.com,DIRECT +DOMAIN-SUFFIX,discuz.com,DIRECT +DOMAIN-SUFFIX,discuz.net,DIRECT +DOMAIN-SUFFIX,docin.com,DIRECT +DOMAIN-SUFFIX,donews.com,DIRECT +DOMAIN-SUFFIX,dospy.com,DIRECT +DOMAIN-SUFFIX,douban.com,DIRECT +DOMAIN-SUFFIX,douban.fm,DIRECT +DOMAIN-SUFFIX,duapp.com,DIRECT +DOMAIN-SUFFIX,duba.net,DIRECT +DOMAIN-SUFFIX,duomi.com,DIRECT +DOMAIN-SUFFIX,duote.com,DIRECT +DOMAIN-SUFFIX,duowan.com,DIRECT +DOMAIN-SUFFIX,egou.com,DIRECT +DOMAIN-SUFFIX,et8.org,DIRECT +DOMAIN-SUFFIX,etao.com,DIRECT +DOMAIN-SUFFIX,f3322.org,DIRECT +DOMAIN-SUFFIX,fantong.com,DIRECT +DOMAIN-SUFFIX,fenzhi.com,DIRECT +DOMAIN-SUFFIX,fhldns.com,DIRECT +DOMAIN-SUFFIX,ganji.com,DIRECT +DOMAIN-SUFFIX,gaopeng.com,DIRECT +DOMAIN-SUFFIX,geekpark.net,DIRECT +DOMAIN-SUFFIX,gfan.com,DIRECT +DOMAIN-SUFFIX,hacdn.net,DIRECT +DOMAIN-SUFFIX,hadns.net,DIRECT +DOMAIN-SUFFIX,hao123.com,DIRECT +DOMAIN-SUFFIX,hao123img.com,DIRECT +DOMAIN-SUFFIX,hc360.com,DIRECT +DOMAIN-SUFFIX,hdslb.com,DIRECT +DOMAIN-SUFFIX,hexun.com,DIRECT +DOMAIN-SUFFIX,hiapk.com,DIRECT +DOMAIN-SUFFIX,hichina.com,DIRECT +DOMAIN-SUFFIX,hoopchina.com,DIRECT +DOMAIN-SUFFIX,huanqiu.com,DIRECT +DOMAIN-SUFFIX,hudong.com,DIRECT +DOMAIN-SUFFIX,huochepiao.com,DIRECT +DOMAIN-SUFFIX,hupu.com,DIRECT +DOMAIN-SUFFIX,iask.com,DIRECT +DOMAIN-SUFFIX,iciba.com,DIRECT +DOMAIN-SUFFIX,idqqimg.com,DIRECT +DOMAIN-SUFFIX,ifanr.com,DIRECT +DOMAIN-SUFFIX,ijinshan.com,DIRECT +DOMAIN-SUFFIX,iqiyi.com,DIRECT +DOMAIN-SUFFIX,it168.com,DIRECT +DOMAIN-SUFFIX,itcpn.net,DIRECT +DOMAIN-SUFFIX,iteye.com,DIRECT +DOMAIN-SUFFIX,itouzi.com,DIRECT +DOMAIN-SUFFIX,jandan.net,DIRECT +DOMAIN-SUFFIX,jiashule.com,DIRECT +DOMAIN-SUFFIX,jiasule.com,DIRECT +DOMAIN-SUFFIX,jiathis.com,DIRECT +DOMAIN-SUFFIX,jiayuan.com,DIRECT +DOMAIN-SUFFIX,jiepang.com,DIRECT +DOMAIN-SUFFIX,jing.fm,DIRECT +DOMAIN-SUFFIX,jobbole.com,DIRECT +DOMAIN-SUFFIX,jstv.com,DIRECT +DOMAIN-SUFFIX,jumei.com,DIRECT +DOMAIN-SUFFIX,kaixin001.com,DIRECT +DOMAIN-SUFFIX,kandian.com,DIRECT +DOMAIN-SUFFIX,kandian.net,DIRECT +DOMAIN-SUFFIX,kanimg.com,DIRECT +DOMAIN-SUFFIX,kankanews.com,DIRECT +DOMAIN-SUFFIX,kdnet.net,DIRECT +DOMAIN-SUFFIX,koudai8.com,DIRECT +DOMAIN-SUFFIX,ku6.com,DIRECT +DOMAIN-SUFFIX,ku6cdn.com,DIRECT +DOMAIN-SUFFIX,ku6img.com,DIRECT +DOMAIN-SUFFIX,kuaidi100.com,DIRECT +DOMAIN-SUFFIX,kugou.com,DIRECT +DOMAIN-SUFFIX,lashou.com,DIRECT +DOMAIN-SUFFIX,letao.com,DIRECT +DOMAIN-SUFFIX,letv.com,DIRECT +DOMAIN-SUFFIX,lietou.com,DIRECT +DOMAIN-SUFFIX,linezing.com,DIRECT +DOMAIN-SUFFIX,loli.mg,DIRECT +DOMAIN-SUFFIX,loli.vg,DIRECT +DOMAIN-SUFFIX,lvping.com,DIRECT +DOMAIN-SUFFIX,lxdns.com,DIRECT +DOMAIN-SUFFIX,mangocity.com,DIRECT +DOMAIN-SUFFIX,mapbar.com,DIRECT +DOMAIN-SUFFIX,mcbbs.net,DIRECT +DOMAIN-SUFFIX,meilishuo.com,DIRECT +DOMAIN-SUFFIX,meituan.com,DIRECT +DOMAIN-SUFFIX,meituan.net,DIRECT +DOMAIN-SUFFIX,meizu.com,DIRECT +DOMAIN-SUFFIX,microsoft.com,DIRECT +DOMAIN-SUFFIX,miui.com,DIRECT +DOMAIN-SUFFIX,moe123.com,DIRECT +DOMAIN-SUFFIX,moegirl.org,DIRECT +DOMAIN-SUFFIX,mop.com,DIRECT +DOMAIN-SUFFIX,mtime.com,DIRECT +DOMAIN-SUFFIX,my-card.in,DIRECT +DOMAIN-SUFFIX,mydrivers.com,DIRECT +DOMAIN-SUFFIX,mzstatic.com,DIRECT +DOMAIN-SUFFIX,newsmth.net,DIRECT +DOMAIN-SUFFIX,ngacn.cc,DIRECT +DOMAIN-SUFFIX,nuomi.com,DIRECT +DOMAIN-SUFFIX,okbuy.com,DIRECT +DOMAIN-SUFFIX,optaim.com,DIRECT +DOMAIN-SUFFIX,oschina.net,DIRECT +DOMAIN-SUFFIX,paipai.com,DIRECT +DOMAIN-SUFFIX,pcbeta.com,DIRECT +DOMAIN-SUFFIX,pchome.net,DIRECT +DOMAIN-SUFFIX,pcpop.com,DIRECT +DOMAIN-SUFFIX,pengyou.com,DIRECT +DOMAIN-SUFFIX,phoenixlzx.com,DIRECT +DOMAIN-SUFFIX,phpwind.net,DIRECT +DOMAIN-SUFFIX,pingan.com,DIRECT +DOMAIN-SUFFIX,pool.ntp.org,DIRECT +DOMAIN-SUFFIX,pplive.com,DIRECT +DOMAIN-SUFFIX,pps.tv,DIRECT +DOMAIN-SUFFIX,ppstream.com,DIRECT +DOMAIN-SUFFIX,pptv.com,DIRECT +DOMAIN-SUFFIX,pubyun.com,DIRECT +DOMAIN-SUFFIX,qhimg.com,DIRECT +DOMAIN-SUFFIX,qianlong.com,DIRECT +DOMAIN-SUFFIX,qidian.com,DIRECT +DOMAIN-SUFFIX,qingdaonews.com,DIRECT +DOMAIN-SUFFIX,qiniu.com,DIRECT +DOMAIN-SUFFIX,qiniudn.com,DIRECT +DOMAIN-SUFFIX,qiushibaike.com,DIRECT +DOMAIN-SUFFIX,qiyi.com,DIRECT +DOMAIN-SUFFIX,qiyipic.com,DIRECT +DOMAIN-SUFFIX,qqmail.com,DIRECT +DOMAIN-SUFFIX,qstatic.com,DIRECT +DOMAIN-SUFFIX,qunar.com,DIRECT +DOMAIN-SUFFIX,qunarzz.com,DIRECT +DOMAIN-SUFFIX,qvbuy.com,DIRECT +DOMAIN-SUFFIX,renren.com,DIRECT +DOMAIN-SUFFIX,renrendai.com,DIRECT +DOMAIN-SUFFIX,rrfmn.com,DIRECT +DOMAIN-SUFFIX,rrimg.com,DIRECT +DOMAIN-SUFFIX,sanguosha.com,DIRECT +DOMAIN-SUFFIX,sdo.com,DIRECT +DOMAIN-SUFFIX,sina.com,DIRECT +DOMAIN-SUFFIX,sinaapp.com,DIRECT +DOMAIN-SUFFIX,sinaedge.com,DIRECT +DOMAIN-SUFFIX,sinajs.com,DIRECT +DOMAIN-SUFFIX,skycn.com,DIRECT +DOMAIN-SUFFIX,smzdm.com,DIRECT +DOMAIN-SUFFIX,sogou.com,DIRECT +DOMAIN-SUFFIX,sohu.com,DIRECT +DOMAIN-SUFFIX,soku.com,DIRECT +DOMAIN-SUFFIX,solidot.org,DIRECT +DOMAIN-SUFFIX,soso.com,DIRECT +DOMAIN-SUFFIX,soufun.com,DIRECT +DOMAIN-SUFFIX,soufunimg.com,DIRECT +DOMAIN-SUFFIX,staticfile.org,DIRECT +DOMAIN-SUFFIX,staticsdo.com,DIRECT +DOMAIN-SUFFIX,suning.com,DIRECT +DOMAIN-SUFFIX,szzfgjj.com,DIRECT +DOMAIN-SUFFIX,tanx.com,DIRECT +DOMAIN-SUFFIX,tbcache.com,DIRECT +DOMAIN-SUFFIX,tdimg.com,DIRECT +DOMAIN-SUFFIX,tencent.com,DIRECT +DOMAIN-SUFFIX,tenpay.com,DIRECT +DOMAIN-SUFFIX,tgbus.com,DIRECT +DOMAIN-SUFFIX,thawte.com,DIRECT +DOMAIN-SUFFIX,tiancity.com,DIRECT +DOMAIN-SUFFIX,tianyaui.com,DIRECT +DOMAIN-SUFFIX,tiexue.net,DIRECT +DOMAIN-SUFFIX,tmall.com,DIRECT +DOMAIN-SUFFIX,tmcdn.net,DIRECT +DOMAIN-SUFFIX,tom.com,DIRECT +DOMAIN-SUFFIX,tomonline-inc.com,DIRECT +DOMAIN-SUFFIX,tuan800.com,DIRECT +DOMAIN-SUFFIX,tuan800.net,DIRECT +DOMAIN-SUFFIX,tuanimg.com,DIRECT +DOMAIN-SUFFIX,tudou.com,DIRECT +DOMAIN-SUFFIX,tudouui.com,DIRECT +DOMAIN-SUFFIX,tuniu.com,DIRECT +DOMAIN-SUFFIX,u148.net,DIRECT +DOMAIN-SUFFIX,u17.com,DIRECT +DOMAIN-SUFFIX,ubuntu.com,DIRECT +DOMAIN-SUFFIX,ucjoy.com,DIRECT +DOMAIN-SUFFIX,uni-marketers.com,DIRECT +DOMAIN-SUFFIX,unionpay.com,DIRECT +DOMAIN-SUFFIX,unionpaysecure.com,DIRECT +DOMAIN-SUFFIX,upaiyun.com,DIRECT +DOMAIN-SUFFIX,upyun.com,DIRECT +DOMAIN-SUFFIX,uusee.com,DIRECT +DOMAIN-SUFFIX,uuu9.com,DIRECT +DOMAIN-SUFFIX,vaikan.com,DIRECT +DOMAIN-SUFFIX,vancl.com,DIRECT +DOMAIN-SUFFIX,vcimg.com,DIRECT +DOMAIN-SUFFIX,verycd.com,DIRECT +DOMAIN-SUFFIX,wandoujia.com,DIRECT +DOMAIN-SUFFIX,wdjimg.com,DIRECT +DOMAIN-SUFFIX,weibo.com,DIRECT +DOMAIN-SUFFIX,weiphone.com,DIRECT +DOMAIN-SUFFIX,weiyun.com,DIRECT +DOMAIN-SUFFIX,west263.com,DIRECT +DOMAIN-SUFFIX,wrating.com,DIRECT +DOMAIN-SUFFIX,wumii.com,DIRECT +DOMAIN-SUFFIX,xdcdn.net,DIRECT +DOMAIN-SUFFIX,xiachufang.com,DIRECT +DOMAIN-SUFFIX,xiami.com,DIRECT +DOMAIN-SUFFIX,xiami.net,DIRECT +DOMAIN-SUFFIX,xiaomi.com,DIRECT +DOMAIN-SUFFIX,xiaonei.com,DIRECT +DOMAIN-SUFFIX,xiazaiba.com,DIRECT +DOMAIN-SUFFIX,xici.net,DIRECT +DOMAIN-SUFFIX,xilu.com,DIRECT +DOMAIN-SUFFIX,xinhuanet.com,DIRECT +DOMAIN-SUFFIX,xinnet.com,DIRECT +DOMAIN-SUFFIX,xlpan.com,DIRECT +DOMAIN-SUFFIX,xnpic.com,DIRECT +DOMAIN-SUFFIX,xungou.com,DIRECT +DOMAIN-SUFFIX,xunlei.com,DIRECT +DOMAIN-SUFFIX,ydstatic.com,DIRECT +DOMAIN-SUFFIX,yesky.com,DIRECT +DOMAIN-SUFFIX,yeyou.com,DIRECT +DOMAIN-SUFFIX,yihaodian.com,DIRECT +DOMAIN-SUFFIX,yihaodianimg.com,DIRECT +DOMAIN-SUFFIX,yingjiesheng.com,DIRECT +DOMAIN-SUFFIX,yintai.com,DIRECT +DOMAIN-SUFFIX,yinyuetai.com,DIRECT +DOMAIN-SUFFIX,yiqifa.com,DIRECT +DOMAIN-SUFFIX,qingjie.me,DIRECT +DOMAIN-SUFFIX,yixun.com,DIRECT +DOMAIN-SUFFIX,ykimg.com,DIRECT +DOMAIN-SUFFIX,ynet.com,DIRECT +DOMAIN-SUFFIX,youdao.com,DIRECT +DOMAIN-SUFFIX,eqxiu.com,DIRECT +DOMAIN-SUFFIX,yougou.com,DIRECT +DOMAIN-SUFFIX,youku.com,DIRECT +DOMAIN-SUFFIX,yupoo.com,DIRECT +DOMAIN-SUFFIX,yy.com,DIRECT +DOMAIN-SUFFIX,zbjimg.com,DIRECT +DOMAIN-SUFFIX,zhaopin.com,DIRECT +DOMAIN-SUFFIX,zhi.hu,DIRECT +DOMAIN-SUFFIX,zhihu.com,DIRECT +DOMAIN-SUFFIX,zhimg.com,DIRECT +DOMAIN-SUFFIX,zhubajie.com,DIRECT +DOMAIN-SUFFIX,zongheng.com,DIRECT +DOMAIN-SUFFIX,v2ex.com,DIRECT +DOMAIN-SUFFIX,hi-pda.com,DIRECT +DOMAIN-SUFFIX,yhd.com,DIRECT +DOMAIN-SUFFIX,58cdn.com,DIRECT +DOMAIN-SUFFIX,avosapps.com,DIRECT +DOMAIN-SUFFIX,mob.com,DIRECT +DOMAIN-SUFFIX,same.com,DIRECT +DOMAIN-SUFFIX,toutiao.com,DIRECT +DOMAIN-SUFFIX,zaih.com,DIRECT +DOMAIN-SUFFIX,lantouzi.com,DIRECT +DOMAIN-SUFFIX,amap.com,DIRECT +DOMAIN-SUFFIX,haosou.com,DIRECT +DOMAIN-SUFFIX,huofu.com,DIRECT +DOMAIN-SUFFIX,5wei.com,DIRECT +DOMAIN-SUFFIX,travelrely.com,DIRECT +DOMAIN-SUFFIX,seekingalpha.com,DIRECT +DOMAIN-SUFFIX,appsflyer.com,DIRECT +#DOMAIN-SUFFIX,gtimg.com,DIRECT + + +# Toutiao +#DOMAIN,ic.snssdk.com,REJECT + + +# Zhuishu +DOMAIN-SUFFIX,zhuishushenqi.com,DIRECT + +# Appzapp By @冯冯ryan_ +DOMAIN-KEYWORD,appzapp,DIRECT + +# CDN +DOMAIN-KEYWORD,ccgslb,DIRECT +DOMAIN-KEYWORD,chinacache,DIRECT + +# Duolinguo +DOMAIN-KEYWORD,duolingo,DIRECT + +# Synology +DOMAIN-KEYWORD,0x,DIRECT + +# Moke +DOMAIN-KEYWORD,moke,DIRECT +DOMAIN-KEYWORD,sinaimg,DIRECT + +# 12306 +DOMAIN-KEYWORD,steam,DIRECT +DOMAIN-KEYWORD,alipay,DIRECT +DOMAIN-KEYWORD,360buy,DIRECT +DOMAIN-KEYWORD,alimama,DIRECT + + + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + + +DOMAIN,g.co,Proxy +DOMAIN,goo.gl,Proxy + + +DOMAIN,app.adjust.com,Proxy +DOMAIN,api.weather.com,Proxy + +# Snapchat +DOMAIN,data.flurry.com,Proxy +DOMAIN,app.snapchat.com,Proxy + +# GFW BLACK LIST +DOMAIN-SUFFIX,com.tw,Proxy +DOMAIN-SUFFIX,com.hk,Proxy +DOMAIN-SUFFIX,com.jp,Proxy +DOMAIN-SUFFIX,0rz.tw,Proxy +DOMAIN-SUFFIX,0to255.com,Proxy +DOMAIN-SUFFIX,1-apple.com.tw,Proxy +DOMAIN-SUFFIX,1024.inc.gs,Proxy +DOMAIN-SUFFIX,10conditionsoflove.com,Proxy +DOMAIN-SUFFIX,10musume.com,Proxy +DOMAIN-SUFFIX,123rf.com,Proxy +DOMAIN-SUFFIX,12bet.com,Proxy +DOMAIN-SUFFIX,12vpn.com,Proxy +DOMAIN-SUFFIX,141hongkong.com,Proxy +DOMAIN-SUFFIX,173ng.com,Proxy +DOMAIN-SUFFIX,17t17p.com,Proxy +DOMAIN-SUFFIX,1984bbs.com,Proxy +DOMAIN-SUFFIX,1984bbs.org,Proxy +DOMAIN-SUFFIX,1998cdp.org,Proxy +DOMAIN-SUFFIX,1bao.org,Proxy +DOMAIN-SUFFIX,1eew.com,Proxy +DOMAIN-SUFFIX,1pondo.tv,Proxy +DOMAIN-SUFFIX,2-hand.info,Proxy +DOMAIN-SUFFIX,2000fun.com,Proxy +DOMAIN-SUFFIX,2008xianzhang.info,Proxy +DOMAIN-SUFFIX,213.so,Proxy +DOMAIN-SUFFIX,21andy.com,Proxy +DOMAIN-SUFFIX,228.net.tw,Proxy +DOMAIN-SUFFIX,24smile.org,Proxy +DOMAIN-SUFFIX,2shared.com,Proxy +DOMAIN-SUFFIX,301works.org,Proxy +DOMAIN-SUFFIX,315lz.com,Proxy +DOMAIN-SUFFIX,32red.com,Proxy +DOMAIN-SUFFIX,365singles.com.ar,Proxy +DOMAIN-SUFFIX,36rain.com,Proxy +DOMAIN-SUFFIX,3a5a.com,Proxy +DOMAIN-SUFFIX,3boys2girls.com,Proxy +DOMAIN-SUFFIX,3tui.net,Proxy +DOMAIN-SUFFIX,4bluestones.biz,Proxy +DOMAIN-SUFFIX,4chan.org,Proxy +DOMAIN-SUFFIX,4shared.com,Proxy +DOMAIN-SUFFIX,4sq.com,Proxy +DOMAIN-SUFFIX,4sqi.net,Proxy +DOMAIN-SUFFIX,51.ca,Proxy +DOMAIN-SUFFIX,5i01.com,Proxy +DOMAIN-SUFFIX,5isotoi5.org,Proxy +DOMAIN-SUFFIX,5maodang.com,Proxy +DOMAIN-SUFFIX,6-4.net,Proxy +DOMAIN-SUFFIX,64museum.org,Proxy +DOMAIN-SUFFIX,64tianwang.com,Proxy +DOMAIN-SUFFIX,64wiki.com,Proxy +DOMAIN-SUFFIX,666kb.com,Proxy +DOMAIN-SUFFIX,6park.com,Proxy +DOMAIN-SUFFIX,6v6dota.com,Proxy +DOMAIN-SUFFIX,7capture.com,Proxy +DOMAIN-SUFFIX,84000.co,Proxy +DOMAIN-SUFFIX,85st.com,Proxy +DOMAIN-SUFFIX,881903.com,Proxy +DOMAIN-SUFFIX,888.com,Proxy +DOMAIN-SUFFIX,89-64.org,Proxy +DOMAIN-SUFFIX,9001700.com,Proxy +DOMAIN-SUFFIX,908taiwan.org,Proxy +DOMAIN-SUFFIX,91porn.com,Proxy +DOMAIN-SUFFIX,92ccav.com,Proxy +DOMAIN-SUFFIX,9bis.com,Proxy +DOMAIN-SUFFIX,9bis.net,Proxy +DOMAIN-SUFFIX,9to5mac.com,Proxy +DOMAIN-SUFFIX,a-normal-day.com,Proxy +DOMAIN-SUFFIX,a5.com.ru,Proxy +DOMAIN-SUFFIX,aamacau.com,Proxy +DOMAIN-SUFFIX,aarki.net,Proxy +DOMAIN-SUFFIX,abc.pp.ru,Proxy +DOMAIN-SUFFIX,abc.xyz,Proxy +DOMAIN-SUFFIX,abercrombie.com,Proxy +DOMAIN-SUFFIX,abitno.linpie.com,Proxy +DOMAIN-SUFFIX,ablwang.com,Proxy +DOMAIN-SUFFIX,aboluowang.com,Proxy +DOMAIN-SUFFIX,aboutgfw.com,Proxy +DOMAIN-SUFFIX,ac.jiruan.net,Proxy +DOMAIN-SUFFIX,acgkj.com,Proxy +DOMAIN-SUFFIX,actimes.com.au,Proxy +DOMAIN-SUFFIX,aculo.us,Proxy +DOMAIN-SUFFIX,adblockplus.org,Proxy +DOMAIN-SUFFIX,addictedtocoffee.de,Proxy +DOMAIN-SUFFIX,addthis.com,Proxy +DOMAIN-SUFFIX,adult.friendfinder.com,Proxy +DOMAIN-SUFFIX,adultfriendfinder.com,Proxy +DOMAIN-SUFFIX,adultkeep.net,Proxy +DOMAIN-SUFFIX,advanscene.com,Proxy +DOMAIN-SUFFIX,advertfan.com,Proxy +DOMAIN-SUFFIX,ae.hao123.com,Proxy +DOMAIN-SUFFIX,aenhancers.com,Proxy +DOMAIN-SUFFIX,af.mil,Proxy +DOMAIN-SUFFIX,aiph.net,Proxy +DOMAIN-SUFFIX,aisex.com,Proxy +DOMAIN-SUFFIX,ait.org.tw,Proxy +DOMAIN-SUFFIX,aiweiwei.com,Proxy +DOMAIN-SUFFIX,aiweiweiblog.com,Proxy +DOMAIN-SUFFIX,ajaxplorer.info,Proxy +DOMAIN-SUFFIX,ajsands.com,Proxy +DOMAIN-SUFFIX,akiba-online.com,Proxy +DOMAIN-SUFFIX,al-qimmah.net,Proxy +DOMAIN-SUFFIX,alabout.com,Proxy +DOMAIN-SUFFIX,alasbarricadas.org,Proxy +DOMAIN-SUFFIX,alexlur.org,Proxy +DOMAIN-SUFFIX,alien-ufos.com,Proxy +DOMAIN-SUFFIX,aliengu.com,Proxy +DOMAIN-SUFFIX,alkasir.com,Proxy +DOMAIN-SUFFIX,all-that-is-interesting.com,Proxy +DOMAIN-SUFFIX,allaboutalpha.com,Proxy +DOMAIN-SUFFIX,allgirlsallowed.org,Proxy +DOMAIN-SUFFIX,alliance.org.hk,Proxy +DOMAIN-SUFFIX,allinfa.com,Proxy +DOMAIN-SUFFIX,allinfo.com,Proxy +DOMAIN-SUFFIX,allmovie.com,Proxy +DOMAIN-SUFFIX,allonlinux.free.fr,Proxy +DOMAIN-SUFFIX,alternate-tools.com,Proxy +DOMAIN-SUFFIX,altrec.com,Proxy +DOMAIN-SUFFIX,alvinalexander.com,Proxy +DOMAIN-SUFFIX,alwaysdata.com,Proxy +DOMAIN-SUFFIX,alwaysdata.net,Proxy +DOMAIN-SUFFIX,am730.com.hk,Proxy +DOMAIN-SUFFIX,ameblo.jp,Proxy +DOMAIN-SUFFIX,americangreencard.com,Proxy +DOMAIN-SUFFIX,amiblockedornot.com,Proxy +DOMAIN-SUFFIX,amnesty.org,Proxy +DOMAIN-SUFFIX,amnestyusa.org,Proxy +DOMAIN-SUFFIX,amnyemachen.org,Proxy +DOMAIN-SUFFIX,amoiist.com,Proxy +DOMAIN-SUFFIX,amusingplanet.com,Proxy +DOMAIN-SUFFIX,amzs.me,Proxy +DOMAIN-SUFFIX,analyze-v.com,Proxy +DOMAIN-SUFFIX,anchorfree.com,Proxy +DOMAIN-SUFFIX,ancsconf.org,Proxy +DOMAIN-SUFFIX,andfaraway.net,Proxy +DOMAIN-SUFFIX,angularjs.org,Proxy +DOMAIN-SUFFIX,animecrazy.net,Proxy +DOMAIN-SUFFIX,aniscartujo.com,Proxy +DOMAIN-SUFFIX,anobii.com,Proxy +DOMAIN-SUFFIX,anontext.com,Proxy +DOMAIN-SUFFIX,anonym.to,Proxy +DOMAIN-SUFFIX,anonymizer.com,Proxy +DOMAIN-SUFFIX,answering-islam.org,Proxy +DOMAIN-SUFFIX,antd.org,Proxy +DOMAIN-SUFFIX,anthonycalzadilla.com,Proxy +DOMAIN-SUFFIX,antidrm.hpg.ig.com.br,Proxy +DOMAIN-SUFFIX,antiwave.net,Proxy +DOMAIN-SUFFIX,aobo.com.au,Proxy +DOMAIN-SUFFIX,aolchannels.aol.com,Proxy +DOMAIN-SUFFIX,aolnews.com,Proxy +DOMAIN-SUFFIX,aomiwang.com,Proxy +DOMAIN-SUFFIX,apetube.com,Proxy +DOMAIN-SUFFIX,api.linksalpha.com,Proxy +DOMAIN-SUFFIX,api.path.com,Proxy +DOMAIN-SUFFIX,api.proxlet.com,Proxy +DOMAIN-SUFFIX,api.supertweet.net,Proxy +DOMAIN-SUFFIX,apiary.io,Proxy +DOMAIN-SUFFIX,apidocs.linksalpha.com,Proxy +DOMAIN-SUFFIX,apigee.com,Proxy +DOMAIN-SUFFIX,app.box.com,Proxy +DOMAIN-SUFFIX,app.heywire.com,Proxy +DOMAIN-SUFFIX,app.hkatvnews.com,Proxy +DOMAIN-SUFFIX,appleactionews.com,Proxy +DOMAIN-SUFFIX,apps.hloli.net,Proxy +DOMAIN-SUFFIX,appspot.com,Proxy +DOMAIN-SUFFIX,aprs.net,Proxy +DOMAIN-SUFFIX,ar.hao123.com,Proxy +DOMAIN-SUFFIX,ar.wikipedia.org,Proxy +DOMAIN-SUFFIX,archdaily.net,Proxy +DOMAIN-SUFFIX,archive.is,Proxy +DOMAIN-SUFFIX,archive.org,Proxy +DOMAIN-SUFFIX,archlinuxarm.org,Proxy +DOMAIN-SUFFIX,arctosia.com,Proxy +DOMAIN-SUFFIX,areca-backup.org,Proxy +DOMAIN-SUFFIX,arlingtoncemetery.mil,Proxy +DOMAIN-SUFFIX,army.mil,Proxy +DOMAIN-SUFFIX,art-or-porn.com,Proxy +DOMAIN-SUFFIX,artsy.net,Proxy +DOMAIN-SUFFIX,asana.com,Proxy +DOMAIN-SUFFIX,asdfg.jp,Proxy +DOMAIN-SUFFIX,asiaharvest.org,Proxy +DOMAIN-SUFFIX,asianews.it,Proxy +DOMAIN-SUFFIX,asianspiss.com,Proxy +DOMAIN-SUFFIX,asianwomensfilm.de,Proxy +DOMAIN-SUFFIX,askstudent.com,Proxy +DOMAIN-SUFFIX,askynz.net,Proxy +DOMAIN-SUFFIX,assembla.com,Proxy +DOMAIN-SUFFIX,assembly.com,Proxy +DOMAIN-SUFFIX,assets-yammer.com,Proxy +DOMAIN-SUFFIX,astonmartinnews.com,Proxy +DOMAIN-SUFFIX,astrill.com,Proxy +DOMAIN-SUFFIX,atc.org.au,Proxy +DOMAIN-SUFFIX,atdmt.com,Proxy +DOMAIN-SUFFIX,atgfw.org,Proxy +DOMAIN-SUFFIX,atj.org.tw,Proxy +DOMAIN-SUFFIX,atlaspost.com,Proxy +DOMAIN-SUFFIX,atnext.com,Proxy +DOMAIN-SUFFIX,avaaz.org,Proxy +DOMAIN-SUFFIX,avast.com,Proxy +DOMAIN-SUFFIX,avdb.in,Proxy +DOMAIN-SUFFIX,avdb.tv,Proxy +DOMAIN-SUFFIX,avidemux.org,Proxy +DOMAIN-SUFFIX,avoision.com,Proxy +DOMAIN-SUFFIX,awardwinningfjords.com,Proxy +DOMAIN-SUFFIX,axureformac.com,Proxy +DOMAIN-SUFFIX,azubu.tv,Proxy +DOMAIN-SUFFIX,babynet.com.hk,Proxy +DOMAIN-SUFFIX,backpackers.com.tw,Proxy +DOMAIN-SUFFIX,backtotiananmen.com,Proxy +DOMAIN-SUFFIX,badassjs.com,Proxy +DOMAIN-SUFFIX,badoo.com,Proxy +DOMAIN-SUFFIX,baidu.jp,Proxy +DOMAIN-SUFFIX,baixing.me,Proxy +DOMAIN-SUFFIX,bannedbook.org,Proxy +DOMAIN-SUFFIX,barenakedislam.com,Proxy +DOMAIN-SUFFIX,barnabu.co.uk,Proxy +DOMAIN-SUFFIX,basetimesheightdividedby2.com,Proxy +DOMAIN-SUFFIX,bayvoice.net,Proxy +DOMAIN-SUFFIX,bb.ttv.com.tw,Proxy +DOMAIN-SUFFIX,bbci.co.uk,Proxy +DOMAIN-SUFFIX,bbg.gov,Proxy +DOMAIN-SUFFIX,bbsfeed.com,Proxy +DOMAIN-SUFFIX,bbsland.com,Proxy +DOMAIN-SUFFIX,bbsone.com,Proxy +DOMAIN-SUFFIX,bcc.com.tw,Proxy +DOMAIN-SUFFIX,bd.zhe.la,Proxy +DOMAIN-SUFFIX,beanstalkapp.com,Proxy +DOMAIN-SUFFIX,bebo.com,Proxy +DOMAIN-SUFFIX,beeg.com,Proxy +DOMAIN-SUFFIX,behindkink.com,Proxy +DOMAIN-SUFFIX,beijing1989.com,Proxy +DOMAIN-SUFFIX,beijingspring.com,Proxy +DOMAIN-SUFFIX,benjaminste.in,Proxy +DOMAIN-SUFFIX,bestvpn.com,Proxy +DOMAIN-SUFFIX,bestvpnservice.com,Proxy +DOMAIN-SUFFIX,bestvpnusa.com,Proxy +DOMAIN-SUFFIX,bet365.com,Proxy +DOMAIN-SUFFIX,beta.iset.com.tw,Proxy +DOMAIN-SUFFIX,beta.usejump.com,Proxy +DOMAIN-SUFFIX,betfair.com,Proxy +DOMAIN-SUFFIX,bettween.com,Proxy +DOMAIN-SUFFIX,betvictor.com,Proxy +DOMAIN-SUFFIX,bewww.net,Proxy +DOMAIN-SUFFIX,beyondfirewall.com,Proxy +DOMAIN-SUFFIX,bfnn.org,Proxy +DOMAIN-SUFFIX,bfsh.hk,Proxy +DOMAIN-SUFFIX,biantailajiao.com,Proxy +DOMAIN-SUFFIX,biantailajiao.in,Proxy +DOMAIN-SUFFIX,biblesforamerica.org,Proxy +DOMAIN-SUFFIX,bic2011.org,Proxy +DOMAIN-SUFFIX,bigfools.com,Proxy +DOMAIN-SUFFIX,bignews.org,Proxy +DOMAIN-SUFFIX,bigsound.org,Proxy +DOMAIN-SUFFIX,bill.zhong.pp.ru,Proxy +DOMAIN-SUFFIX,bill2-software.com,Proxy +DOMAIN-SUFFIX,billypan.com,Proxy +DOMAIN-SUFFIX,billywr.com,Proxy +DOMAIN-SUFFIX,binaryage.com,Proxy +DOMAIN-SUFFIX,bipic.net,Proxy +DOMAIN-SUFFIX,bit.ly,Proxy +DOMAIN-SUFFIX,bitbucket.org,Proxy +DOMAIN-SUFFIX,bitcointalk.org,Proxy +DOMAIN-SUFFIX,bitshare.com,Proxy +DOMAIN-SUFFIX,bjzc.org,Proxy +DOMAIN-SUFFIX,blinkx.com,Proxy +DOMAIN-SUFFIX,blinw.com,Proxy +DOMAIN-SUFFIX,blip.tv,Proxy +DOMAIN-SUFFIX,blockcn.com,Proxy +DOMAIN-SUFFIX,bloodshed.net,Proxy +DOMAIN-SUFFIX,bloomfortune.com,Proxy +DOMAIN-SUFFIX,bloomingdales.com,Proxy +DOMAIN-SUFFIX,bnrmetal.com,Proxy +DOMAIN-SUFFIX,boardreader.com,Proxy +DOMAIN-SUFFIX,bobulate.com,Proxy +DOMAIN-SUFFIX,bod.asia,Proxy +DOMAIN-SUFFIX,bolin.netfirms.com,Proxy +DOMAIN-SUFFIX,bonbonme.com,Proxy +DOMAIN-SUFFIX,bonjourlesgeeks.com,Proxy +DOMAIN-SUFFIX,boobstagram.com,Proxy +DOMAIN-SUFFIX,book.com.tw,Proxy +DOMAIN-SUFFIX,books.com.tw,Proxy +DOMAIN-SUFFIX,bookshelfporn.com,Proxy +DOMAIN-SUFFIX,bot.nu,Proxy +DOMAIN-SUFFIX,botanwang.com,Proxy +DOMAIN-SUFFIX,bowenpress.com,Proxy +DOMAIN-SUFFIX,box.com,Proxy +DOMAIN-SUFFIX,box.net,Proxy +DOMAIN-SUFFIX,boxun.com,Proxy +DOMAIN-SUFFIX,boxun.tv,Proxy +DOMAIN-SUFFIX,boxunblog.com,Proxy +DOMAIN-SUFFIX,boxunclub.com,Proxy +DOMAIN-SUFFIX,boyfriendtv.com,Proxy +DOMAIN-SUFFIX,boysmaster.com,Proxy +DOMAIN-SUFFIX,br.hao123.com,Proxy +DOMAIN-SUFFIX,br.st,Proxy +DOMAIN-SUFFIX,bralio.com,Proxy +DOMAIN-SUFFIX,branch.com,Proxy +DOMAIN-SUFFIX,brandonhutchinson.com,Proxy +DOMAIN-SUFFIX,braumeister.org,Proxy +DOMAIN-SUFFIX,bravotube.net,Proxy +DOMAIN-SUFFIX,brazzers.com,Proxy +DOMAIN-SUFFIX,break.com,Proxy +DOMAIN-SUFFIX,breakingtweets.com,Proxy +DOMAIN-SUFFIX,breakwall.net,Proxy +DOMAIN-SUFFIX,briefdream.com,Proxy +DOMAIN-SUFFIX,brightkite.com,Proxy +DOMAIN-SUFFIX,briian.com,Proxy +DOMAIN-SUFFIX,brizzly.com,Proxy +DOMAIN-SUFFIX,broadbook.com,Proxy +DOMAIN-SUFFIX,broadpressinc.com,Proxy +DOMAIN-SUFFIX,browserscope.org,Proxy +DOMAIN-SUFFIX,brucewang.net,Proxy +DOMAIN-SUFFIX,bt95.com,Proxy +DOMAIN-SUFFIX,btdigg.org,Proxy +DOMAIN-SUFFIX,btspread.com,Proxy +DOMAIN-SUFFIX,budaedu.org,Proxy +DOMAIN-SUFFIX,buff.ly,Proxy +DOMAIN-SUFFIX,bugclub.org,Proxy +DOMAIN-SUFFIX,bulbous.freeserve.co.uk,Proxy +DOMAIN-SUFFIX,bullog.org,Proxy +DOMAIN-SUFFIX,bullogger.com,Proxy +DOMAIN-SUFFIX,businessinsider.com,Proxy +DOMAIN-SUFFIX,businessinsider.com.au,Proxy +DOMAIN-SUFFIX,businesstimes.com.cn,Proxy +DOMAIN-SUFFIX,businessweek.com,Proxy +DOMAIN-SUFFIX,buugaa.com,Proxy +DOMAIN-SUFFIX,buy.yahoo.com.tw,Proxy +DOMAIN-SUFFIX,buzzhand.com,Proxy +DOMAIN-SUFFIX,buzzurl.jp,Proxy +DOMAIN-SUFFIX,bwsj.hk,Proxy +DOMAIN-SUFFIX,bx.tl,Proxy +DOMAIN-SUFFIX,c-est-simple.com,Proxy +DOMAIN-SUFFIX,c-spanvideo.org,Proxy +DOMAIN-SUFFIX,c1521.biz.tm,Proxy +DOMAIN-SUFFIX,c1522.mooo.com,Proxy +DOMAIN-SUFFIX,cacnw.com,Proxy +DOMAIN-SUFFIX,cactusvpn.com,Proxy +DOMAIN-SUFFIX,cafepress.com,Proxy +DOMAIN-SUFFIX,cahr.org.tw,Proxy +DOMAIN-SUFFIX,calameo.com,Proxy +DOMAIN-SUFFIX,calebelston.com,Proxy +DOMAIN-SUFFIX,cam4.com,Proxy +DOMAIN-SUFFIX,cam4.jp,Proxy +DOMAIN-SUFFIX,cam4.sg,Proxy +DOMAIN-SUFFIX,cams.com,Proxy +DOMAIN-SUFFIX,cams.org.sg,Proxy +DOMAIN-SUFFIX,canadameet.com,Proxy +DOMAIN-SUFFIX,canyu.org,Proxy +DOMAIN-SUFFIX,cao.im,Proxy +DOMAIN-SUFFIX,caobian.info,Proxy +DOMAIN-SUFFIX,caochangqing.com,Proxy +DOMAIN-SUFFIX,cardinalkungfoundation.org,Proxy +DOMAIN-SUFFIX,cari.com.my,Proxy +DOMAIN-SUFFIX,casatibet.org.mx,Proxy +DOMAIN-SUFFIX,caspion.com,Proxy +DOMAIN-SUFFIX,catcatbox.com,Proxy +DOMAIN-SUFFIX,catch22.net,Proxy +DOMAIN-SUFFIX,catfightpayperview.xxx,Proxy +DOMAIN-SUFFIX,catholic.org.hk,Proxy +DOMAIN-SUFFIX,catholic.org.tw,Proxy +DOMAIN-SUFFIX,cattt.com,Proxy +DOMAIN-SUFFIX,cbc.ca,Proxy +DOMAIN-SUFFIX,cbs.ntu.edu.tw,Proxy +DOMAIN-SUFFIX,cbsnews.com,Proxy +DOMAIN-SUFFIX,cbtc.org.hk,Proxy +DOMAIN-SUFFIX,ccavtop10.com,Proxy +DOMAIN-SUFFIX,ccdtr.org,Proxy +DOMAIN-SUFFIX,ccim.org,Proxy +DOMAIN-SUFFIX,cclife.org,Proxy +DOMAIN-SUFFIX,ccthere.com,Proxy +DOMAIN-SUFFIX,cctongbao.com,Proxy +DOMAIN-SUFFIX,ccue.ca,Proxy +DOMAIN-SUFFIX,ccue.com,Proxy +DOMAIN-SUFFIX,cdbook.org,Proxy +DOMAIN-SUFFIX,cdd.me,Proxy +DOMAIN-SUFFIX,cdef.org,Proxy +DOMAIN-SUFFIX,cdig.info,Proxy +DOMAIN-SUFFIX,cdjp.org,Proxy +DOMAIN-SUFFIX,cdn.printfriendly.com,Proxy +DOMAIN-SUFFIX,cdn.softlayer.net,Proxy +DOMAIN-SUFFIX,cdn.sstatic.net,Proxy +DOMAIN-SUFFIX,cdn.staticstuff.net,Proxy +DOMAIN-SUFFIX,cdn.v2ex.com,Proxy +DOMAIN-SUFFIX,cdnews.com.tw,Proxy +DOMAIN-SUFFIX,cdp.sinica.edu.tw,Proxy +DOMAIN-SUFFIX,cdp1989.org,Proxy +DOMAIN-SUFFIX,cdp1998.org,Proxy +DOMAIN-SUFFIX,cdp2006.org,Proxy +DOMAIN-SUFFIX,cdpa.url.tw,Proxy +DOMAIN-SUFFIX,cdpeu.org,Proxy +DOMAIN-SUFFIX,cdpusa.org,Proxy +DOMAIN-SUFFIX,cdpweb.org,Proxy +DOMAIN-SUFFIX,cdpwu.org,Proxy +DOMAIN-SUFFIX,cdw.com,Proxy +DOMAIN-SUFFIX,cecc.gov,Proxy +DOMAIN-SUFFIX,cellulo.info,Proxy +DOMAIN-SUFFIX,cenci.tk,Proxy +DOMAIN-SUFFIX,cenews.eu,Proxy +DOMAIN-SUFFIX,centralnation.com,Proxy +DOMAIN-SUFFIX,centurys.net,Proxy +DOMAIN-SUFFIX,certificate.revocationcheck.com,Proxy +DOMAIN-SUFFIX,cfhks.org.hk,Proxy +DOMAIN-SUFFIX,cftfc.com,Proxy +DOMAIN-SUFFIX,cgdepot.org,Proxy +DOMAIN-SUFFIX,cgst.edu,Proxy +DOMAIN-SUFFIX,ch.shvoong.com,Proxy +DOMAIN-SUFFIX,chandoo.org,Proxy +DOMAIN-SUFFIX,change.org,Proxy +DOMAIN-SUFFIX,changp.com,Proxy +DOMAIN-SUFFIX,chaos.e-spacy.com,Proxy +DOMAIN-SUFFIX,chapm25.com,Proxy +DOMAIN-SUFFIX,chaturbate.com,Proxy +DOMAIN-SUFFIX,chengmingmag.com,Proxy +DOMAIN-SUFFIX,chenguangcheng.com,Proxy +DOMAIN-SUFFIX,chenpokong.com,Proxy +DOMAIN-SUFFIX,cherrysave.com,Proxy +DOMAIN-SUFFIX,chevronwp7.com,Proxy +DOMAIN-SUFFIX,chhongbi.org,Proxy +DOMAIN-SUFFIX,chicagoncmtv.com,Proxy +DOMAIN-SUFFIX,chingcheong.com,Proxy +DOMAIN-SUFFIX,chithu.org,Proxy +DOMAIN-SUFFIX,chn.chosun.com,Proxy +DOMAIN-SUFFIX,chrdnet.com,Proxy +DOMAIN-SUFFIX,chrispederick.com,Proxy +DOMAIN-SUFFIX,chrispederick.net,Proxy +DOMAIN-SUFFIX,christianstudy.com,Proxy +DOMAIN-SUFFIX,christiantimes.org.hk,Proxy +DOMAIN-SUFFIX,christusrex.org,Proxy +DOMAIN-SUFFIX,chrlawyers.hk,Proxy +DOMAIN-SUFFIX,chrlcg-hk.org,Proxy +DOMAIN-SUFFIX,chrome.com,Proxy +DOMAIN-SUFFIX,chromeadblock.com,Proxy +DOMAIN-SUFFIX,chromeexperiments.com,Proxy +DOMAIN-SUFFIX,chromercise.com,Proxy +DOMAIN-SUFFIX,chromium.org,Proxy +DOMAIN-SUFFIX,chubun.com,Proxy +DOMAIN-SUFFIX,chuizi.net,Proxy +DOMAIN-SUFFIX,circlethebayfortibet.org,Proxy +DOMAIN-SUFFIX,citizenlab.org,Proxy +DOMAIN-SUFFIX,citizenscommission.hk,Proxy +DOMAIN-SUFFIX,citizensradio.org,Proxy +DOMAIN-SUFFIX,city365.ca,Proxy +DOMAIN-SUFFIX,city9x.com,Proxy +DOMAIN-SUFFIX,civicparty.hk,Proxy +DOMAIN-SUFFIX,civilhrfront.org,Proxy +DOMAIN-SUFFIX,civilmedia.tw,Proxy +DOMAIN-SUFFIX,cjb.net,Proxy +DOMAIN-SUFFIX,ck101.com,Proxy +DOMAIN-SUFFIX,cl.d0z.net,Proxy +DOMAIN-SUFFIX,cl.ly,Proxy +DOMAIN-SUFFIX,cl.ufree.org,Proxy +DOMAIN-SUFFIX,classicalguitarblog.net,Proxy +DOMAIN-SUFFIX,classically.me,Proxy +DOMAIN-SUFFIX,clb.org.hk,Proxy +DOMAIN-SUFFIX,clearharmony.net,Proxy +DOMAIN-SUFFIX,clearwisdom.net,Proxy +DOMAIN-SUFFIX,clientsfromhell.net,Proxy +DOMAIN-SUFFIX,cling.omy.sg,Proxy +DOMAIN-SUFFIX,clipfish.de,Proxy +DOMAIN-SUFFIX,cloudflare.com,Proxy +DOMAIN-SUFFIX,cloudfront.net,Proxy +DOMAIN-SUFFIX,club1069.com,Proxy +DOMAIN-SUFFIX,cmi.org.tw,Proxy +DOMAIN-SUFFIX,cmoinc.org,Proxy +DOMAIN-SUFFIX,cms.gov,Proxy +DOMAIN-SUFFIX,cmule.com,Proxy +DOMAIN-SUFFIX,cmule.org,Proxy +DOMAIN-SUFFIX,cn.calameo.com,Proxy +DOMAIN-SUFFIX,cn.dayabook.com,Proxy +DOMAIN-SUFFIX,cn.fmnnow.com,Proxy +DOMAIN-SUFFIX,cn.giganews.com,Proxy +DOMAIN-SUFFIX,cn.ibtimes.com,Proxy +DOMAIN-SUFFIX,cn.reuters.com,Proxy +DOMAIN-SUFFIX,cn.streetvoice.com,Proxy +DOMAIN-SUFFIX,cn.uncyclopedia.wikia.com,Proxy +DOMAIN-SUFFIX,cn2.streetvoice.com,Proxy +DOMAIN-SUFFIX,cna.com.tw,Proxy +DOMAIN-SUFFIX,cnavista.com.tw,Proxy +DOMAIN-SUFFIX,cnd.org,Proxy +DOMAIN-SUFFIX,cnn.com,Proxy +DOMAIN-SUFFIX,cocoa.zonble.net,Proxy +DOMAIN-SUFFIX,cocoapods.org,Proxy +DOMAIN-SUFFIX,code1984.com,Proxy +DOMAIN-SUFFIX,codeboxapp.com,Proxy +DOMAIN-SUFFIX,codeshare.io,Proxy +DOMAIN-SUFFIX,codeskulptor.org,Proxy +DOMAIN-SUFFIX,collateralmurder.com,Proxy +DOMAIN-SUFFIX,collateralmurder.org,Proxy +DOMAIN-SUFFIX,commentshk.com,Proxy +DOMAIN-SUFFIX,compileheart.com,Proxy +DOMAIN-SUFFIX,conoyo.com,Proxy +DOMAIN-SUFFIX,contactmagazine.net,Proxy +DOMAIN-SUFFIX,contests.twilio.com,Proxy +DOMAIN-SUFFIX,convio.net,Proxy +DOMAIN-SUFFIX,coobay.com,Proxy +DOMAIN-SUFFIX,cookingtothegoodlife.com,Proxy +DOMAIN-SUFFIX,cool18.com,Proxy +DOMAIN-SUFFIX,coolaler.com,Proxy +DOMAIN-SUFFIX,coolder.com,Proxy +DOMAIN-SUFFIX,coolloud.org.tw,Proxy +DOMAIN-SUFFIX,corumcollege.com,Proxy +DOMAIN-SUFFIX,cotweet.com,Proxy +DOMAIN-SUFFIX,couchdbwiki.com,Proxy +DOMAIN-SUFFIX,coveringweb.com,Proxy +DOMAIN-SUFFIX,cpj.org,Proxy +DOMAIN-SUFFIX,crackle.com,Proxy +DOMAIN-SUFFIX,crashlytics.com,Proxy +DOMAIN-SUFFIX,crd-net.org,Proxy +DOMAIN-SUFFIX,creaders.net,Proxy +DOMAIN-SUFFIX,crossthewall.net,Proxy +DOMAIN-SUFFIX,crowy.net,Proxy +DOMAIN-SUFFIX,csdparty.com,Proxy +DOMAIN-SUFFIX,css.pixnet.in,Proxy +DOMAIN-SUFFIX,csuchen.de,Proxy +DOMAIN-SUFFIX,ctfriend.net,Proxy +DOMAIN-SUFFIX,ctheroux.com,Proxy +DOMAIN-SUFFIX,cthlo.github.io,Proxy +DOMAIN-SUFFIX,ctitv.com.tw,Proxy +DOMAIN-SUFFIX,cts.com.tw,Proxy +DOMAIN-SUFFIX,cubicle17.com,Proxy +DOMAIN-SUFFIX,cuhkacs.org,Proxy +DOMAIN-SUFFIX,cuihua.org,Proxy +DOMAIN-SUFFIX,cuiweiping.net,Proxy +DOMAIN-SUFFIX,culture.tw,Proxy +DOMAIN-SUFFIX,curvefish.com,Proxy +DOMAIN-SUFFIX,cw.com.tw,Proxy +DOMAIN-SUFFIX,cyberghost.natado.com,Proxy +DOMAIN-SUFFIX,cyberghostvpn.com,Proxy +DOMAIN-SUFFIX,cynscribe.com,Proxy +DOMAIN-SUFFIX,cytode.us,Proxy +DOMAIN-SUFFIX,dabr.co.uk,Proxy +DOMAIN-SUFFIX,dabr.me,Proxy +DOMAIN-SUFFIX,dabr.mobi,Proxy +DOMAIN-SUFFIX,dadazim.com,Proxy +DOMAIN-SUFFIX,dadi360.com,Proxy +DOMAIN-SUFFIX,dafagood.com,Proxy +DOMAIN-SUFFIX,dafahao.com,Proxy +DOMAIN-SUFFIX,dailidaili.com,Proxy +DOMAIN-SUFFIX,dailymotion.com,Proxy +DOMAIN-SUFFIX,dailynews.sina.com,Proxy +DOMAIN-SUFFIX,dajiyuan.com,Proxy +DOMAIN-SUFFIX,dajiyuan.eu,Proxy +DOMAIN-SUFFIX,dajusha.baywords.com,Proxy +DOMAIN-SUFFIX,dalailama.com,Proxy +DOMAIN-SUFFIX,dalailama.ru,Proxy +DOMAIN-SUFFIX,dalailamaprotesters.info,Proxy +DOMAIN-SUFFIX,dalailamavisit.org.nz,Proxy +DOMAIN-SUFFIX,dalailamaworld.com,Proxy +DOMAIN-SUFFIX,dalianmeng.org,Proxy +DOMAIN-SUFFIX,daliulian.org,Proxy +DOMAIN-SUFFIX,danwei.org,Proxy +DOMAIN-SUFFIX,daolan.net,Proxy +DOMAIN-SUFFIX,darpa.mil,Proxy +DOMAIN-SUFFIX,data-vocabulary.org,Proxy +DOMAIN-SUFFIX,date.fm,Proxy +DOMAIN-SUFFIX,david-kilgour.com,Proxy +DOMAIN-SUFFIX,davidslog.com,Proxy +DOMAIN-SUFFIX,daxa.cn,Proxy +DOMAIN-SUFFIX,dayaarmongol.ning.com,Proxy +DOMAIN-SUFFIX,daylife.com,Proxy +DOMAIN-SUFFIX,dcard.tw,Proxy +DOMAIN-SUFFIX,ddc.com.tw,Proxy +DOMAIN-SUFFIX,de-sci.org,Proxy +DOMAIN-SUFFIX,deck.ly,Proxy +DOMAIN-SUFFIX,default.secureserver.net,Proxy +DOMAIN-SUFFIX,delcamp.net,Proxy +DOMAIN-SUFFIX,delicious.com,Proxy +DOMAIN-SUFFIX,demo.opera-mini.net,Proxy +DOMAIN-SUFFIX,democrats.org,Proxy +DOMAIN-SUFFIX,derekhsu.homeip.net,Proxy +DOMAIN-SUFFIX,desc.se,Proxy +DOMAIN-SUFFIX,designerol.com,Proxy +DOMAIN-SUFFIX,destiny.xfiles.to,Proxy +DOMAIN-SUFFIX,deutsche-welle.de,Proxy +DOMAIN-SUFFIX,dev102.com,Proxy +DOMAIN-SUFFIX,developers.box.net,Proxy +DOMAIN-SUFFIX,devio.us,Proxy +DOMAIN-SUFFIX,devpn.com,Proxy +DOMAIN-SUFFIX,dfanning.com,Proxy +DOMAIN-SUFFIX,dfas.mil,Proxy +DOMAIN-SUFFIX,dharamsalanet.com,Proxy +DOMAIN-SUFFIX,diaoyuislands.org,Proxy +DOMAIN-SUFFIX,digicert.com,Proxy +DOMAIN-SUFFIX,digiland.tw,Proxy +DOMAIN-SUFFIX,digitalnomadsproject.org,Proxy +DOMAIN-SUFFIX,digitalocean.com,Proxy +DOMAIN-SUFFIX,diigo.com,Proxy +DOMAIN-SUFFIX,dimitrik.free.fr,Proxy +DOMAIN-SUFFIX,dingoonity.org,Proxy +DOMAIN-SUFFIX,dipity.com,Proxy +DOMAIN-SUFFIX,directcreative.com,Proxy +DOMAIN-SUFFIX,discogs.com,Proxy +DOMAIN-SUFFIX,discuss.com.hk,Proxy +DOMAIN-SUFFIX,disneyrollergirl.net,Proxy +DOMAIN-SUFFIX,disp.cc,Proxy +DOMAIN-SUFFIX,dit-inc.us,Proxy +DOMAIN-SUFFIX,dizhidizhi.com,Proxy +DOMAIN-SUFFIX,dizhuzhishang.com,Proxy +DOMAIN-SUFFIX,djangosnippets.org,Proxy +DOMAIN-SUFFIX,dl-laby.jp,Proxy +DOMAIN-SUFFIX,dl.box.net,Proxy +DOMAIN-SUFFIX,dlsite.com,Proxy +DOMAIN-SUFFIX,dmcdn.net,Proxy +DOMAIN-SUFFIX,dmm.co.jp,Proxy +DOMAIN-SUFFIX,dns2go.com,Proxy +DOMAIN-SUFFIX,dnscrypt.org,Proxy +DOMAIN-SUFFIX,dnsimple.com,Proxy +DOMAIN-SUFFIX,dnssec.net,Proxy +DOMAIN-SUFFIX,do.co,Proxy +DOMAIN-SUFFIX,docker.com,Proxy +DOMAIN-SUFFIX,docs.chef.io,Proxy +DOMAIN-SUFFIX,docs.docker.com,Proxy +DOMAIN-SUFFIX,dogfartnetwork.com,Proxy +DOMAIN-SUFFIX,dojin.com,Proxy +DOMAIN-SUFFIX,dok-forum.net,Proxy +DOMAIN-SUFFIX,dolc.de,Proxy +DOMAIN-SUFFIX,dolf.org.hk,Proxy +DOMAIN-SUFFIX,dollf.com,Proxy +DOMAIN-SUFFIX,domain.club.tw,Proxy +DOMAIN-SUFFIX,domainhelp.search.com,Proxy +DOMAIN-SUFFIX,dongde.com,Proxy +DOMAIN-SUFFIX,dongtaiwang.com,Proxy +DOMAIN-SUFFIX,dongtaiwang.net,Proxy +DOMAIN-SUFFIX,dongyangjing.com,Proxy +DOMAIN-SUFFIX,dontfilter.us,Proxy +DOMAIN-SUFFIX,dotheyfolloweachother.com,Proxy +DOMAIN-SUFFIX,dotplane.com,Proxy +DOMAIN-SUFFIX,dotsub.com,Proxy +DOMAIN-SUFFIX,doubleaf.com,Proxy +DOMAIN-SUFFIX,dougscripts.com,Proxy +DOMAIN-SUFFIX,dowei.org,Proxy +DOMAIN-SUFFIX,download.aircrack-ng.org,Proxy +DOMAIN-SUFFIX,download.ithome.com.tw,Proxy +DOMAIN-SUFFIX,doxygen.org,Proxy +DOMAIN-SUFFIX,dphk.org,Proxy +DOMAIN-SUFFIX,dpp.org.tw,Proxy +DOMAIN-SUFFIX,draw.io,Proxy +DOMAIN-SUFFIX,dreammask.org,Proxy +DOMAIN-SUFFIX,drepung.org,Proxy +DOMAIN-SUFFIX,drewolanoff.com,Proxy +DOMAIN-SUFFIX,drgan.net,Proxy +DOMAIN-SUFFIX,dribbble.com,Proxy +DOMAIN-SUFFIX,droplr.com,Proxy +DOMAIN-SUFFIX,drsunacademy.com,Proxy +DOMAIN-SUFFIX,drtuber.com,Proxy +DOMAIN-SUFFIX,dscn.info,Proxy +DOMAIN-SUFFIX,dtiblog.com,Proxy +DOMAIN-SUFFIX,dtic.mil,Proxy +DOMAIN-SUFFIX,dtiserv2.com,Proxy +DOMAIN-SUFFIX,duckduckgo.com,Proxy +DOMAIN-SUFFIX,duckload.com,Proxy +DOMAIN-SUFFIX,duckmylife.com,Proxy +DOMAIN-SUFFIX,duihua.org,Proxy +DOMAIN-SUFFIX,duihuahrjournal.org,Proxy +DOMAIN-SUFFIX,duoweitimes.com,Proxy +DOMAIN-SUFFIX,duping.net,Proxy +DOMAIN-SUFFIX,duplicati.com,Proxy +DOMAIN-SUFFIX,dupola.com,Proxy +DOMAIN-SUFFIX,dupola.net,Proxy +DOMAIN-SUFFIX,dvorak.org,Proxy +DOMAIN-SUFFIX,dw-world.com,Proxy +DOMAIN-SUFFIX,dw-world.de,Proxy +DOMAIN-SUFFIX,dw.com,Proxy +DOMAIN-SUFFIX,dw.de,Proxy +DOMAIN-SUFFIX,dwheeler.com,Proxy +DOMAIN-SUFFIX,dwnews.com,Proxy +DOMAIN-SUFFIX,dwnews.net,Proxy +DOMAIN-SUFFIX,dy24k.info,Proxy +DOMAIN-SUFFIX,dynawebinc.com,Proxy +DOMAIN-SUFFIX,dyndns.org,Proxy +DOMAIN-SUFFIX,dzze.com,Proxy +DOMAIN-SUFFIX,e-classical.com.tw,Proxy +DOMAIN-SUFFIX,e-gold.com,Proxy +DOMAIN-SUFFIX,e-info.org.tw,Proxy +DOMAIN-SUFFIX,e-traderland.net,Proxy +DOMAIN-SUFFIX,e123.hk,Proxy +DOMAIN-SUFFIX,ea.com.cn,Proxy +DOMAIN-SUFFIX,eamonnbrennan.com,Proxy +DOMAIN-SUFFIX,earthquake.usgs.gov,Proxy +DOMAIN-SUFFIX,eastturkestan.com,Proxy +DOMAIN-SUFFIX,eastturkistan-gov.org,Proxy +DOMAIN-SUFFIX,eastturkistan.net,Proxy +DOMAIN-SUFFIX,eastturkistangovernmentinexile.us,Proxy +DOMAIN-SUFFIX,ebookbrowse.com,Proxy +DOMAIN-SUFFIX,ebookee.com,Proxy +DOMAIN-SUFFIX,echofon.com,Proxy +DOMAIN-SUFFIX,ecministry.net,Proxy +DOMAIN-SUFFIX,ecsm.vs.com,Proxy +DOMAIN-SUFFIX,edgecastcdn.net,Proxy +DOMAIN-SUFFIX,edicypages.com,Proxy +DOMAIN-SUFFIX,editmysite.com,Proxy +DOMAIN-SUFFIX,edoors.com,Proxy +DOMAIN-SUFFIX,edubridge.com,Proxy +DOMAIN-SUFFIX,eevpn.com,Proxy +DOMAIN-SUFFIX,efcc.org.hk,Proxy +DOMAIN-SUFFIX,efksoft.com,Proxy +DOMAIN-SUFFIX,efmoe.com,Proxy +DOMAIN-SUFFIX,eic-av.com,Proxy +DOMAIN-SUFFIX,electionsmeter.com,Proxy +DOMAIN-SUFFIX,elementaryos.org,Proxy +DOMAIN-SUFFIX,elgoog.im,Proxy +DOMAIN-SUFFIX,elpais.com,Proxy +DOMAIN-SUFFIX,eltondisney.com,Proxy +DOMAIN-SUFFIX,emacsblog.org,Proxy +DOMAIN-SUFFIX,embedly.com,Proxy +DOMAIN-SUFFIX,embr.in,Proxy +DOMAIN-SUFFIX,emory.edu,Proxy +DOMAIN-SUFFIX,emule-ed2k.com,Proxy +DOMAIN-SUFFIX,emuparadise.me,Proxy +DOMAIN-SUFFIX,en.favotter.net,Proxy +DOMAIN-SUFFIX,en.hao123.com,Proxy +DOMAIN-SUFFIX,en.wikipedia.org,Proxy +DOMAIN-SUFFIX,enewstree.com,Proxy +DOMAIN-SUFFIX,engadget.com,Proxy +DOMAIN-SUFFIX,englishfromengland.co.uk,Proxy +DOMAIN-SUFFIX,enormego.com,Proxy +DOMAIN-SUFFIX,entermap.com,Proxy +DOMAIN-SUFFIX,episcopalchurch.org,Proxy +DOMAIN-SUFFIX,epochtimestr.com,Proxy +DOMAIN-SUFFIX,epochweekly.com,Proxy +DOMAIN-SUFFIX,erabaru.net,Proxy +DOMAIN-SUFFIX,erepublik.com,Proxy +DOMAIN-SUFFIX,erights.net,Proxy +DOMAIN-SUFFIX,eriversoft.com,Proxy +DOMAIN-SUFFIX,erktv.com,Proxy +DOMAIN-SUFFIX,ernestmandel.org,Proxy +DOMAIN-SUFFIX,eslite.com,Proxy +DOMAIN-SUFFIX,etaa.org.au,Proxy +DOMAIN-SUFFIX,etaiwannews.com,Proxy +DOMAIN-SUFFIX,etizer.org,Proxy +DOMAIN-SUFFIX,etools.ncol.com,Proxy +DOMAIN-SUFFIX,ettoday.net,Proxy +DOMAIN-SUFFIX,eulam.com,Proxy +DOMAIN-SUFFIX,eurekavpt.com,Proxy +DOMAIN-SUFFIX,evchk.wikia.com,Proxy +DOMAIN-SUFFIX,eventful.com,Proxy +DOMAIN-SUFFIX,everyday-carry.com,Proxy +DOMAIN-SUFFIX,exblog.jp,Proxy +DOMAIN-SUFFIX,expatshield.com,Proxy +DOMAIN-SUFFIX,exploader.net,Proxy +DOMAIN-SUFFIX,expressvpn.com,Proxy +DOMAIN-SUFFIX,extremetube.com,Proxy +DOMAIN-SUFFIX,eyespirit.info,Proxy +DOMAIN-SUFFIX,eyevio.jp,Proxy +DOMAIN-SUFFIX,eyny.com,Proxy +DOMAIN-SUFFIX,ezpc.tk,Proxy +DOMAIN-SUFFIX,ezpeer.com,Proxy +DOMAIN-SUFFIX,fabric.io,Proxy +DOMAIN-SUFFIX,facesofnyfw.com,Proxy +DOMAIN-SUFFIX,facesoftibetanselfimmolators.info,Proxy +DOMAIN-SUFFIX,fail.hk,Proxy +DOMAIN-SUFFIX,faithfuleye.com,Proxy +DOMAIN-SUFFIX,faiththedog.info,Proxy +DOMAIN-SUFFIX,fakku.net,Proxy +DOMAIN-SUFFIX,falsefire.com,Proxy +DOMAIN-SUFFIX,falun-co.org,Proxy +DOMAIN-SUFFIX,falun-ny.net,Proxy +DOMAIN-SUFFIX,falunart.org,Proxy +DOMAIN-SUFFIX,falunasia.info,Proxy +DOMAIN-SUFFIX,falundafamuseum.org,Proxy +DOMAIN-SUFFIX,falungong.org.uk,Proxy +DOMAIN-SUFFIX,falunhr.org,Proxy +DOMAIN-SUFFIX,faluninfo.net,Proxy +DOMAIN-SUFFIX,falunpilipinas.net,Proxy +DOMAIN-SUFFIX,falunworld.net,Proxy +DOMAIN-SUFFIX,familyfed.org,Proxy +DOMAIN-SUFFIX,famunion.com,Proxy +DOMAIN-SUFFIX,fan-qiang.com,Proxy +DOMAIN-SUFFIX,fangbinxing.com,Proxy +DOMAIN-SUFFIX,fangeming.com,Proxy +DOMAIN-SUFFIX,fanglizhi.info,Proxy +DOMAIN-SUFFIX,fangong.org,Proxy +DOMAIN-SUFFIX,fangongheike.com,Proxy +DOMAIN-SUFFIX,fanqianghou.com,Proxy +DOMAIN-SUFFIX,fanqiangyakexi.net,Proxy +DOMAIN-SUFFIX,fanswong.com,Proxy +DOMAIN-SUFFIX,fanyue.info,Proxy +DOMAIN-SUFFIX,fapdu.com,Proxy +DOMAIN-SUFFIX,fastly.net,Proxy +DOMAIN-SUFFIX,fastpic.ru,Proxy +DOMAIN-SUFFIX,faststone.org,Proxy +DOMAIN-SUFFIX,favorious.com,Proxy +DOMAIN-SUFFIX,favstar.fm,Proxy +DOMAIN-SUFFIX,fawanghuihui.org,Proxy +DOMAIN-SUFFIX,faydao.com,Proxy +DOMAIN-SUFFIX,fb.com,Proxy +DOMAIN-SUFFIX,fb.me,Proxy +DOMAIN-SUFFIX,fbcdn.net,Proxy +DOMAIN-SUFFIX,fbsbx.com,Proxy +DOMAIN-SUFFIX,fc2.com,Proxy +DOMAIN-SUFFIX,fc2blog.net,Proxy +DOMAIN-SUFFIX,fdc89.jp,Proxy +DOMAIN-SUFFIX,feedblitz.com,Proxy +DOMAIN-SUFFIX,feedbooks.mobi,Proxy +DOMAIN-SUFFIX,feedburner.com,Proxy +DOMAIN-SUFFIX,feedly.com,Proxy +DOMAIN-SUFFIX,feeds.feedburner.com,Proxy +DOMAIN-SUFFIX,feeds.fileforum.com,Proxy +DOMAIN-SUFFIX,feeds2.feedburner.com,Proxy +DOMAIN-SUFFIX,feedzshare.com,Proxy +DOMAIN-SUFFIX,feelssh.com,Proxy +DOMAIN-SUFFIX,feer.com,Proxy +DOMAIN-SUFFIX,feitian-california.org,Proxy +DOMAIN-SUFFIX,feitianacademy.org,Proxy +DOMAIN-SUFFIX,felixcat.net,Proxy +DOMAIN-SUFFIX,feministteacher.com,Proxy +DOMAIN-SUFFIX,fengzhenghu.com,Proxy +DOMAIN-SUFFIX,ff.im,Proxy +DOMAIN-SUFFIX,fflick.com,Proxy +DOMAIN-SUFFIX,uncyclomedia.org,Proxy +DOMAIN-SUFFIX,filefactory.com,Proxy +DOMAIN-SUFFIX,files2me.com,Proxy +DOMAIN-SUFFIX,fileserve.com,Proxy +DOMAIN-SUFFIX,fillthesquare.org,Proxy +DOMAIN-SUFFIX,finalion.jp,Proxy +DOMAIN-SUFFIX,findbook.tw,Proxy +DOMAIN-SUFFIX,fingerdaily.com,Proxy +DOMAIN-SUFFIX,finler.net,Proxy +DOMAIN-SUFFIX,fireofliberty.org,Proxy +DOMAIN-SUFFIX,firstfivefollowers.com,Proxy +DOMAIN-SUFFIX,flecheinthepeche.fr,Proxy +DOMAIN-SUFFIX,fleshbot.com,Proxy +DOMAIN-SUFFIX,flickr.com,Proxy +DOMAIN-SUFFIX,flickrhivemind.net,Proxy +DOMAIN-SUFFIX,flightcaster.com,Proxy +DOMAIN-SUFFIX,flipboard.com,Proxy +DOMAIN-SUFFIX,focustaiwan.tw,Proxy +DOMAIN-SUFFIX,focusvpn.com,Proxy +DOMAIN-SUFFIX,fofg.org,Proxy +DOMAIN-SUFFIX,fofldfradio.org,Proxy +DOMAIN-SUFFIX,fooooo.com,Proxy +DOMAIN-SUFFIX,footwiball.com,Proxy +DOMAIN-SUFFIX,forum.baby-kingdom.com,Proxy +DOMAIN-SUFFIX,forum.cyberctm.com,Proxy +DOMAIN-SUFFIX,forum.idsam.com,Proxy +DOMAIN-SUFFIX,forum.iset.com.tw,Proxy +DOMAIN-SUFFIX,forum.my903.com,Proxy +DOMAIN-SUFFIX,forum.mymaji.com,Proxy +DOMAIN-SUFFIX,forum.omy.sg,Proxy +DOMAIN-SUFFIX,forum.palmislife.com,Proxy +DOMAIN-SUFFIX,forum.setty.com.tw,Proxy +DOMAIN-SUFFIX,forum.sina.com.hk,Proxy +DOMAIN-SUFFIX,forum.slime.com.tw,Proxy +DOMAIN-SUFFIX,forum.tvb.com,Proxy +DOMAIN-SUFFIX,forum4hk.com,Proxy +DOMAIN-SUFFIX,fotop.net,Proxy +DOMAIN-SUFFIX,fourface.nodesnoop.com,Proxy +DOMAIN-SUFFIX,fourthinternational.org,Proxy +DOMAIN-SUFFIX,foxdie.us,Proxy +DOMAIN-SUFFIX,foxgay.com,Proxy +DOMAIN-SUFFIX,foxsub.com,Proxy +DOMAIN-SUFFIX,foxtang.com,Proxy +DOMAIN-SUFFIX,fpmt-osel.org,Proxy +DOMAIN-SUFFIX,fpmt.org,Proxy +DOMAIN-SUFFIX,fpmt.tw,Proxy +DOMAIN-SUFFIX,fpmtmexico.org,Proxy +DOMAIN-SUFFIX,fqok.org,Proxy +DOMAIN-SUFFIX,fqrouter.com,Proxy +DOMAIN-SUFFIX,franklc.com,Proxy +DOMAIN-SUFFIX,freakshare.com,Proxy +DOMAIN-SUFFIX,fredwilson.vc,Proxy +DOMAIN-SUFFIX,free-gate.org,Proxy +DOMAIN-SUFFIX,free-hada-now.org,Proxy +DOMAIN-SUFFIX,free-ssh.com,Proxy +DOMAIN-SUFFIX,free.fr,Proxy +DOMAIN-SUFFIX,free4u.com.ar,Proxy +DOMAIN-SUFFIX,freealim.com,Proxy +DOMAIN-SUFFIX,freechal.com,Proxy +DOMAIN-SUFFIX,freedomcollection.org,Proxy +DOMAIN-SUFFIX,freedomhouse.org,Proxy +DOMAIN-SUFFIX,freeforums.org,Proxy +DOMAIN-SUFFIX,freegao.com,Proxy +DOMAIN-SUFFIX,freelotto.com,Proxy +DOMAIN-SUFFIX,freeman2.com,Proxy +DOMAIN-SUFFIX,freemoren.com,Proxy +DOMAIN-SUFFIX,freemorenews.com,Proxy +DOMAIN-SUFFIX,freenetproject.org,Proxy +DOMAIN-SUFFIX,freenewscn.com,Proxy +DOMAIN-SUFFIX,freeopenvpn.com,Proxy +DOMAIN-SUFFIX,freeoz.org,Proxy +DOMAIN-SUFFIX,freepik.com,Proxy +DOMAIN-SUFFIX,freessh.us,Proxy +DOMAIN-SUFFIX,freetibet.net,Proxy +DOMAIN-SUFFIX,freetibet.org,Proxy +DOMAIN-SUFFIX,freetibetanheroes.org,Proxy +DOMAIN-SUFFIX,freevpn.nl,Proxy +DOMAIN-SUFFIX,freewallpaper4.me,Proxy +DOMAIN-SUFFIX,freewebs.com,Proxy +DOMAIN-SUFFIX,freeweibo.com,Proxy +DOMAIN-SUFFIX,freexinwen.com,Proxy +DOMAIN-SUFFIX,friendfeed-media.com,Proxy +DOMAIN-SUFFIX,friendfeed.com,Proxy +DOMAIN-SUFFIX,friends-of-tibet.org,Proxy +DOMAIN-SUFFIX,friendsoftibet.org,Proxy +DOMAIN-SUFFIX,fring.com,Proxy +DOMAIN-SUFFIX,fringenetwork.com,Proxy +DOMAIN-SUFFIX,frommel.net,Proxy +DOMAIN-SUFFIX,frontlinedefenders.org,Proxy +DOMAIN-SUFFIX,fscked.org,Proxy +DOMAIN-SUFFIX,fsurf.com,Proxy +DOMAIN-SUFFIX,fuckcnnic.net,Proxy +DOMAIN-SUFFIX,fuckgfw.com,Proxy +DOMAIN-SUFFIX,fuckgfw.org,Proxy +DOMAIN-SUFFIX,fulue.com,Proxy +DOMAIN-SUFFIX,funf.tw,Proxy +DOMAIN-SUFFIX,funp.com,Proxy +DOMAIN-SUFFIX,furhhdl.org,Proxy +DOMAIN-SUFFIX,furinkan.com,Proxy +DOMAIN-SUFFIX,furl.net,Proxy +DOMAIN-SUFFIX,futureme.org,Proxy +DOMAIN-SUFFIX,futuremessage.org,Proxy +DOMAIN-SUFFIX,fuyin.net,Proxy +DOMAIN-SUFFIX,fw.cm,Proxy +DOMAIN-SUFFIX,fxnetworks.com,Proxy +DOMAIN-SUFFIX,fzh999.com,Proxy +DOMAIN-SUFFIX,fzh999.net,Proxy +DOMAIN-SUFFIX,g.e-hentai.org,Proxy +DOMAIN-SUFFIX,gabocorp.com,Proxy +DOMAIN-SUFFIX,gaeproxy.com,Proxy +DOMAIN-SUFFIX,gaforum.org,Proxy +DOMAIN-SUFFIX,galenwu.com,Proxy +DOMAIN-SUFFIX,game735.com,Proxy +DOMAIN-SUFFIX,gamebase.com.tw,Proxy +DOMAIN-SUFFIX,gamer.com.tw,Proxy +DOMAIN-SUFFIX,gamez.com.tw,Proxy +DOMAIN-SUFFIX,ganges.com,Proxy +DOMAIN-SUFFIX,gaoming.net,Proxy +DOMAIN-SUFFIX,gaopi.net,Proxy +DOMAIN-SUFFIX,gaozhisheng.net,Proxy +DOMAIN-SUFFIX,gaozhisheng.org,Proxy +DOMAIN-SUFFIX,gappp.org,Proxy +DOMAIN-SUFFIX,gardennetworks.com,Proxy +DOMAIN-SUFFIX,gardennetworks.org,Proxy +DOMAIN-SUFFIX,gartlive.com,Proxy +DOMAIN-SUFFIX,gather.com,Proxy +DOMAIN-SUFFIX,gaymap.cc,Proxy +DOMAIN-SUFFIX,gaytube.com,Proxy +DOMAIN-SUFFIX,gazotube.com,Proxy +DOMAIN-SUFFIX,gcc.org.hk,Proxy +DOMAIN-SUFFIX,gclooney.com,Proxy +DOMAIN-SUFFIX,gcpnews.com,Proxy +DOMAIN-SUFFIX,gdbt.net,Proxy +DOMAIN-SUFFIX,gdzf.org,Proxy +DOMAIN-SUFFIX,geek-art.net,Proxy +DOMAIN-SUFFIX,geekerhome.com,Proxy +DOMAIN-SUFFIX,geekmade.co.uk,Proxy +DOMAIN-SUFFIX,geekmanuals.com,Proxy +DOMAIN-SUFFIX,generesis.com,Proxy +DOMAIN-SUFFIX,gentlecuff.com,Proxy +DOMAIN-SUFFIX,genuitec.com,Proxy +DOMAIN-SUFFIX,geohot.com,Proxy +DOMAIN-SUFFIX,geometrictools.com,Proxy +DOMAIN-SUFFIX,get-digital-help.com,Proxy +DOMAIN-SUFFIX,getchu.com,Proxy +DOMAIN-SUFFIX,getcloudapp.com,Proxy +DOMAIN-SUFFIX,getcomposer.org,Proxy +DOMAIN-SUFFIX,getfoxyproxy.org,Proxy +DOMAIN-SUFFIX,getfreedur.com,Proxy +DOMAIN-SUFFIX,getgom.com,Proxy +DOMAIN-SUFFIX,getiton.com,Proxy +DOMAIN-SUFFIX,getjetso.com,Proxy +DOMAIN-SUFFIX,getlantern.org,Proxy +DOMAIN-SUFFIX,getnarrative.com,Proxy +DOMAIN-SUFFIX,getprismatic.com,Proxy +DOMAIN-SUFFIX,getsmartlinks.com,Proxy +DOMAIN-SUFFIX,getsocialscope.com,Proxy +DOMAIN-SUFFIX,getuploader.com,Proxy +DOMAIN-SUFFIX,getyouram.com,Proxy +DOMAIN-SUFFIX,gfw.org.ua,Proxy +DOMAIN-SUFFIX,ggpht.com,Proxy +DOMAIN-SUFFIX,ggssl.com,Proxy +DOMAIN-SUFFIX,ghconduit.com,Proxy +DOMAIN-SUFFIX,ghost.org,Proxy +DOMAIN-SUFFIX,ghut.org,Proxy +DOMAIN-SUFFIX,giga-web.jp,Proxy +DOMAIN-SUFFIX,gigporno.ru,Proxy +DOMAIN-SUFFIX,gimpshop.com,Proxy +DOMAIN-SUFFIX,girlbanker.com,Proxy +DOMAIN-SUFFIX,gist.github.com,Proxy +DOMAIN-SUFFIX,git-scm.com,Proxy +DOMAIN-SUFFIX,github.com,Proxy +DOMAIN-SUFFIX,github.io,Proxy +DOMAIN-SUFFIX,githubusercontent.com,Proxy +DOMAIN-SUFFIX,givemesomethingtoread.com,Proxy +DOMAIN-SUFFIX,glennhilton.com,Proxy +DOMAIN-SUFFIX,global.hkepc.com,Proxy +DOMAIN-SUFFIX,globaldelight.com,Proxy +DOMAIN-SUFFIX,globaljihad.net,Proxy +DOMAIN-SUFFIX,globalmuseumoncommunism.org,Proxy +DOMAIN-SUFFIX,globalrescue.hopto.org,Proxy +DOMAIN-SUFFIX,globalrescue.net,Proxy +DOMAIN-SUFFIX,globalvoicesonline.org,Proxy +DOMAIN-SUFFIX,gmbd.cn,Proxy +DOMAIN-SUFFIX,gmhz.org,Proxy +DOMAIN-SUFFIX,gmiddle.com,Proxy +DOMAIN-SUFFIX,gmiddle.net,Proxy +DOMAIN-SUFFIX,gmll.org,Proxy +DOMAIN-SUFFIX,gmodules.com,Proxy +DOMAIN-SUFFIX,gmozomg.izihost.org,Proxy +DOMAIN-SUFFIX,gnci.org.hk,Proxy +DOMAIN-SUFFIX,gnuradio.org,Proxy +DOMAIN-SUFFIX,goagent.biz,Proxy +DOMAIN-SUFFIX,goagentplus.com,Proxy +DOMAIN-SUFFIX,godaddy.com,Proxy +DOMAIN-SUFFIX,godfootsteps.org,Proxy +DOMAIN-SUFFIX,godsdirectcontact.org.tw,Proxy +DOMAIN-SUFFIX,gokbayrak.com,Proxy +DOMAIN-SUFFIX,golang.org,Proxy +DOMAIN-SUFFIX,goldbetsports.com,Proxy +DOMAIN-SUFFIX,goldenmelody.com.tw,Proxy +DOMAIN-SUFFIX,goldwave.com,Proxy +DOMAIN-SUFFIX,gongm.in,Proxy +DOMAIN-SUFFIX,gongmeng.info,Proxy +DOMAIN-SUFFIX,gongminliliang.com,Proxy +DOMAIN-SUFFIX,gongwt.com,Proxy +DOMAIN-SUFFIX,goodreaders.com,Proxy +DOMAIN-SUFFIX,goodreads.com,Proxy +DOMAIN-SUFFIX,goodtv.com.tw,Proxy +DOMAIN-SUFFIX,goodtv.tv,Proxy +DOMAIN-SUFFIX,goofind.com,Proxy +DOMAIN-SUFFIX,gopetition.com,Proxy +DOMAIN-SUFFIX,gospelherald.com,Proxy +DOMAIN-SUFFIX,gotw.ca,Proxy +DOMAIN-SUFFIX,gov.tw,Proxy +DOMAIN-SUFFIX,gpass1.com,Proxy +DOMAIN-SUFFIX,gplusexpertise.com,Proxy +DOMAIN-SUFFIX,grandtrial.org,Proxy +DOMAIN-SUFFIX,grangorz.org,Proxy +DOMAIN-SUFFIX,graphis.ne.jp,Proxy +DOMAIN-SUFFIX,gravatar.com,Proxy +DOMAIN-SUFFIX,graylog2.org,Proxy +DOMAIN-SUFFIX,greasespot.net,Proxy +DOMAIN-SUFFIX,great-roc.org,Proxy +DOMAIN-SUFFIX,greatfire.org,Proxy +DOMAIN-SUFFIX,greatroc.org,Proxy +DOMAIN-SUFFIX,greatroc.tw,Proxy +DOMAIN-SUFFIX,greatzhonghua.org,Proxy +DOMAIN-SUFFIX,greenparty.org.tw,Proxy +DOMAIN-SUFFIX,greenpeace.com.tw,Proxy +DOMAIN-SUFFIX,greenpeace.org,Proxy +DOMAIN-SUFFIX,greenvpn.net,Proxy +DOMAIN-SUFFIX,gs-discuss.com,Proxy +DOMAIN-SUFFIX,gstatic.com,Proxy +DOMAIN-SUFFIX,gtricks.com,Proxy +DOMAIN-SUFFIX,gu-chu-sum.org,Proxy +DOMAIN-SUFFIX,guancha.org,Proxy +DOMAIN-SUFFIX,guishan.org,Proxy +DOMAIN-SUFFIX,gun-world.net,Proxy +DOMAIN-SUFFIX,gunsamerica.com,Proxy +DOMAIN-SUFFIX,guomin.us,Proxy +DOMAIN-SUFFIX,gutteruncensored.com,Proxy +DOMAIN-SUFFIX,gvlib.com,Proxy +DOMAIN-SUFFIX,gvm.com.tw,Proxy +DOMAIN-SUFFIX,gvt0.com,Proxy +DOMAIN-SUFFIX,gvt1.com,Proxy +DOMAIN-SUFFIX,gyalwarinpoche.com,Proxy +DOMAIN-SUFFIX,gyatsostudio.com,Proxy +DOMAIN-SUFFIX,gzm.tv,Proxy +DOMAIN-SUFFIX,gzone-anime.info,Proxy +DOMAIN-SUFFIX,hacken.cc,Proxy +DOMAIN-SUFFIX,hackthatphone.net,Proxy +DOMAIN-SUFFIX,hahlo.com,Proxy +DOMAIN-SUFFIX,hakkatv.org.tw,Proxy +DOMAIN-SUFFIX,hanunyi.com,Proxy +DOMAIN-SUFFIX,happi-game-center.com,Proxy +DOMAIN-SUFFIX,haproxy.org,Proxy +DOMAIN-SUFFIX,hardsextube.com,Proxy +DOMAIN-SUFFIX,harunyahya.com,Proxy +DOMAIN-SUFFIX,hasaowall.com,Proxy +DOMAIN-SUFFIX,have8.com,Proxy +DOMAIN-SUFFIX,haxx.se,Proxy +DOMAIN-SUFFIX,hbogo.com,Proxy +DOMAIN-SUFFIX,hdtvb.net,Proxy +DOMAIN-SUFFIX,heartyit.com,Proxy +DOMAIN-SUFFIX,heatsale.com,Proxy +DOMAIN-SUFFIX,hecaitou.net,Proxy +DOMAIN-SUFFIX,hechaji.com,Proxy +DOMAIN-SUFFIX,heeact.edu.tw,Proxy +DOMAIN-SUFFIX,heix.pp.ru,Proxy +DOMAIN-SUFFIX,heiyo.info,Proxy +DOMAIN-SUFFIX,helloandroid.com,Proxy +DOMAIN-SUFFIX,hellonewyork.us,Proxy +DOMAIN-SUFFIX,helloqueer.com,Proxy +DOMAIN-SUFFIX,hellotxt.com,Proxy +DOMAIN-SUFFIX,hellouk.org,Proxy +DOMAIN-SUFFIX,help.linksalpha.com,Proxy +DOMAIN-SUFFIX,help.opera.com,Proxy +DOMAIN-SUFFIX,help.trello.com,Proxy +DOMAIN-SUFFIX,helpeachpeople.com,Proxy +DOMAIN-SUFFIX,helplinfen.com,Proxy +DOMAIN-SUFFIX,helpzhuling.org,Proxy +DOMAIN-SUFFIX,hen.bao.li,Proxy +DOMAIN-SUFFIX,heqinglian.net,Proxy +DOMAIN-SUFFIX,here4news.com,Proxy +DOMAIN-SUFFIX,heungkongdiscuss.com,Proxy +DOMAIN-SUFFIX,hexxeh.net,Proxy +DOMAIN-SUFFIX,hgseav.com,Proxy +DOMAIN-SUFFIX,hidden-advent.org,Proxy +DOMAIN-SUFFIX,hide.me,Proxy +DOMAIN-SUFFIX,hidecloud.com,Proxy +DOMAIN-SUFFIX,hideipvpn.com,Proxy +DOMAIN-SUFFIX,hidemyass.com,Proxy +DOMAIN-SUFFIX,higfw.com,Proxy +DOMAIN-SUFFIX,highcharts.com,Proxy +DOMAIN-SUFFIX,highrockmedia.com,Proxy +DOMAIN-SUFFIX,hihiforum.com,Proxy +DOMAIN-SUFFIX,hihistory.net,Proxy +DOMAIN-SUFFIX,hiitch.com,Proxy +DOMAIN-SUFFIX,hikinggfw.org,Proxy +DOMAIN-SUFFIX,himalayan-foundation.org,Proxy +DOMAIN-SUFFIX,himemix.com,Proxy +DOMAIN-SUFFIX,himemix.net,Proxy +DOMAIN-SUFFIX,hjclub.info,Proxy +DOMAIN-SUFFIX,hk-pub.com,Proxy +DOMAIN-SUFFIX,hk.geocities.com,Proxy +DOMAIN-SUFFIX,hk.gradconnection.com,Proxy +DOMAIN-SUFFIX,hk.jiepang.com,Proxy +DOMAIN-SUFFIX,hk.knowledge.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.myblog.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.news.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.rd.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.search.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.video.news.yahoo.com,Proxy +DOMAIN-SUFFIX,hk.yahoo.com,Proxy +DOMAIN-SUFFIX,hk32168.com,Proxy +DOMAIN-SUFFIX,hkbc.net,Proxy +DOMAIN-SUFFIX,hkbf.org,Proxy +DOMAIN-SUFFIX,hkchurch.org,Proxy +DOMAIN-SUFFIX,hkdailynews.com.hk,Proxy +DOMAIN-SUFFIX,hkday.net,Proxy +DOMAIN-SUFFIX,hkej.com,Proxy +DOMAIN-SUFFIX,hkepc.com,Proxy +DOMAIN-SUFFIX,hkfront.org,Proxy +DOMAIN-SUFFIX,hkg.westkit.net,Proxy +DOMAIN-SUFFIX,hkgolden.com,Proxy +DOMAIN-SUFFIX,hkgreenradio.org,Proxy +DOMAIN-SUFFIX,hkheadline.com,Proxy +DOMAIN-SUFFIX,hkhkhk.com,Proxy +DOMAIN-SUFFIX,hkjc.com,Proxy +DOMAIN-SUFFIX,hkjp.easyweb.hk,Proxy +DOMAIN-SUFFIX,hkjp.org,Proxy +DOMAIN-SUFFIX,hkptu.org,Proxy +DOMAIN-SUFFIX,hkreporter.com,Proxy +DOMAIN-SUFFIX,hkreporter.loved.hk,Proxy +DOMAIN-SUFFIX,hkupop.hku.hk,Proxy +DOMAIN-SUFFIX,hkwcc.org.hk,Proxy +DOMAIN-SUFFIX,hkzone.org,Proxy +DOMAIN-SUFFIX,hnjhj.com,Proxy +DOMAIN-SUFFIX,hocusfoc.us,Proxy +DOMAIN-SUFFIX,hola.com,Proxy +DOMAIN-SUFFIX,hola.org,Proxy +DOMAIN-SUFFIX,holyspiritspeaks.org,Proxy +DOMAIN-SUFFIX,holz.byethost8.com,Proxy +DOMAIN-SUFFIX,home.sina.com,Proxy +DOMAIN-SUFFIX,home.so-net.net.tw,Proxy +DOMAIN-SUFFIX,homeservershow.com,Proxy +DOMAIN-SUFFIX,hongmeimei.com,Proxy +DOMAIN-SUFFIX,hongzhi.li,Proxy +DOMAIN-SUFFIX,hootsuite.com,Proxy +DOMAIN-SUFFIX,hotfile.com,Proxy +DOMAIN-SUFFIX,hotpot.hk,Proxy +DOMAIN-SUFFIX,hotshame.com,Proxy +DOMAIN-SUFFIX,hotspotshield.com,Proxy +DOMAIN-SUFFIX,hougaige.com,Proxy +DOMAIN-SUFFIX,howtoforge.com,Proxy +DOMAIN-SUFFIX,howtogeek.com,Proxy +DOMAIN-SUFFIX,hqcdp.org,Proxy +DOMAIN-SUFFIX,hrcir.com,Proxy +DOMAIN-SUFFIX,hrw.org,Proxy +DOMAIN-SUFFIX,hsjp.net,Proxy +DOMAIN-SUFFIX,hsselite.com,Proxy +DOMAIN-SUFFIX,ht.ly,Proxy +DOMAIN-SUFFIX,htkou.net,Proxy +DOMAIN-SUFFIX,htl.li,Proxy +DOMAIN-SUFFIX,html5rocks.com,Proxy +DOMAIN-SUFFIX,htmldog.com,Proxy +DOMAIN-SUFFIX,htxt.it,Proxy +DOMAIN-SUFFIX,hua-yue.net,Proxy +DOMAIN-SUFFIX,huaglad.com,Proxy +DOMAIN-SUFFIX,huanghuagang.org,Proxy +DOMAIN-SUFFIX,huaren.us,Proxy +DOMAIN-SUFFIX,huaxia-news.com,Proxy +DOMAIN-SUFFIX,huaxiabao.org,Proxy +DOMAIN-SUFFIX,huaxin.ph,Proxy +DOMAIN-SUFFIX,hudatoriq.web.id,Proxy +DOMAIN-SUFFIX,hugoroy.eu,Proxy +DOMAIN-SUFFIX,huhaitai.com,Proxy +DOMAIN-SUFFIX,huhamhire.com,Proxy +DOMAIN-SUFFIX,hulu.com,Proxy +DOMAIN-SUFFIX,huluim.com,Proxy +DOMAIN-SUFFIX,humanrightsbriefing.org,Proxy +DOMAIN-SUFFIX,hung-ya.com,Proxy +DOMAIN-SUFFIX,hungerstrikeforaids.org,Proxy +DOMAIN-SUFFIX,huping.net,Proxy +DOMAIN-SUFFIX,hutianyi.net,Proxy +DOMAIN-SUFFIX,hutong9.net,Proxy +DOMAIN-SUFFIX,hwayue.org.tw,Proxy +DOMAIN-SUFFIX,hwinfo.com,Proxy +DOMAIN-SUFFIX,hxwq.org,Proxy +DOMAIN-SUFFIX,hybrid-analysis.com,Proxy +DOMAIN-SUFFIX,hyperrate.com,Proxy +DOMAIN-SUFFIX,hypeshell.com,Proxy +DOMAIN-SUFFIX,i-cable.com,Proxy +DOMAIN-SUFFIX,i1.hk,Proxy +DOMAIN-SUFFIX,i2p2.de,Proxy +DOMAIN-SUFFIX,i2runner.com,Proxy +DOMAIN-SUFFIX,ialmostlaugh.com,Proxy +DOMAIN-SUFFIX,ianslive.in,Proxy +DOMAIN-SUFFIX,iask.bz,Proxy +DOMAIN-SUFFIX,iask.ca,Proxy +DOMAIN-SUFFIX,ibiblio.org,Proxy +DOMAIN-SUFFIX,iblogserv-f.net,Proxy +DOMAIN-SUFFIX,ibros.org,Proxy +DOMAIN-SUFFIX,icij.org,Proxy +DOMAIN-SUFFIX,icl-fi.org,Proxy +DOMAIN-SUFFIX,iconfactory.com,Proxy +DOMAIN-SUFFIX,iconpaper.org,Proxy +DOMAIN-SUFFIX,icu-project.org,Proxy +DOMAIN-SUFFIX,id.hao123.com,Proxy +DOMAIN-SUFFIX,idemocracy.asia,Proxy +DOMAIN-SUFFIX,identi.ca,Proxy +DOMAIN-SUFFIX,idiomconnection.com,Proxy +DOMAIN-SUFFIX,idlcoyote.com,Proxy +DOMAIN-SUFFIX,idouga.com,Proxy +DOMAIN-SUFFIX,idv.tw,Proxy +DOMAIN-SUFFIX,ieasynews.net,Proxy +DOMAIN-SUFFIX,ied2k.net,Proxy +DOMAIN-SUFFIX,if.ttt,Proxy +DOMAIN-SUFFIX,ifan.cz.cc,Proxy +DOMAIN-SUFFIX,ifanqiang.com,Proxy +DOMAIN-SUFFIX,ifanr.com,Proxy +DOMAIN-SUFFIX,ifcss.org,Proxy +DOMAIN-SUFFIX,ifjc.org,Proxy +DOMAIN-SUFFIX,ifreewares.com,Proxy +DOMAIN-SUFFIX,ift.tt,Proxy +DOMAIN-SUFFIX,ifttt.com,Proxy +DOMAIN-SUFFIX,igfw.net,Proxy +DOMAIN-SUFFIX,ignitedetroit.net,Proxy +DOMAIN-SUFFIX,igvita.com,Proxy +DOMAIN-SUFFIX,ihakka.net,Proxy +DOMAIN-SUFFIX,iicns.com,Proxy +DOMAIN-SUFFIX,illusionfactory.com,Proxy +DOMAIN-SUFFIX,ilove80.be,Proxy +DOMAIN-SUFFIX,ilovelongtoes.com,Proxy +DOMAIN-SUFFIX,im.tv,Proxy +DOMAIN-SUFFIX,im88.tw,Proxy +DOMAIN-SUFFIX,imagefap.com,Proxy +DOMAIN-SUFFIX,imageflea.com,Proxy +DOMAIN-SUFFIX,imageoptim.com,Proxy +DOMAIN-SUFFIX,imageshack.us,Proxy +DOMAIN-SUFFIX,imagevenue.com,Proxy +DOMAIN-SUFFIX,imagezilla.net,Proxy +DOMAIN-SUFFIX,imdb.com,Proxy +DOMAIN-SUFFIX,img.dlsite.jp,Proxy +DOMAIN-SUFFIX,img.ly,Proxy +DOMAIN-SUFFIX,imgix.net,Proxy +DOMAIN-SUFFIX,imgur.com,Proxy +DOMAIN-SUFFIX,imkev.com,Proxy +DOMAIN-SUFFIX,imlive.com,Proxy +DOMAIN-SUFFIX,immigration.gov.tw,Proxy +DOMAIN-SUFFIX,incredibox.fr,Proxy +DOMAIN-SUFFIX,infinitylist.com,Proxy +DOMAIN-SUFFIX,infradead.org,Proxy +DOMAIN-SUFFIX,inmediahk.net,Proxy +DOMAIN-SUFFIX,innermongolia.org,Proxy +DOMAIN-SUFFIX,intellectuapp.com,Proxy +DOMAIN-SUFFIX,interestinglaugh.com,Proxy +DOMAIN-SUFFIX,interfaceaddiction.com,Proxy +DOMAIN-SUFFIX,internationalrivers.org,Proxy +DOMAIN-SUFFIX,internet.org,Proxy +DOMAIN-SUFFIX,internetdefenseleague.org,Proxy +DOMAIN-SUFFIX,internetfreedom.org,Proxy +DOMAIN-SUFFIX,internetpopculture.com,Proxy +DOMAIN-SUFFIX,inxian.com,Proxy +DOMAIN-SUFFIX,ipcf.org.tw,Proxy +DOMAIN-SUFFIX,iphone4hongkong.com,Proxy +DOMAIN-SUFFIX,iphonehacks.com,Proxy +DOMAIN-SUFFIX,iphonenews.cc,Proxy +DOMAIN-SUFFIX,iphonix.fr,Proxy +DOMAIN-SUFFIX,ipicture.ru,Proxy +DOMAIN-SUFFIX,ipobar.com,Proxy +DOMAIN-SUFFIX,ippotv.com,Proxy +DOMAIN-SUFFIX,iptorrents.com,Proxy +DOMAIN-SUFFIX,ipvanish.com,Proxy +DOMAIN-SUFFIX,iredmail.org,Proxy +DOMAIN-SUFFIX,iridiumcao.info,Proxy +DOMAIN-SUFFIX,ironbigfools.compython.net,Proxy +DOMAIN-SUFFIX,ironicsoftware.com,Proxy +DOMAIN-SUFFIX,ironpython.net,Proxy +DOMAIN-SUFFIX,isaacmao.com,Proxy +DOMAIN-SUFFIX,isgreat.org,Proxy +DOMAIN-SUFFIX,islam.org.hk,Proxy +DOMAIN-SUFFIX,islamicity.com,Proxy +DOMAIN-SUFFIX,ismaelan.com,Proxy +DOMAIN-SUFFIX,ismprofessional.net,Proxy +DOMAIN-SUFFIX,isohunt.com,Proxy +DOMAIN-SUFFIX,israbox.com,Proxy +DOMAIN-SUFFIX,istockphoto.com,Proxy +DOMAIN-SUFFIX,isunaffairs.com,Proxy +DOMAIN-SUFFIX,isuntv.com,Proxy +DOMAIN-SUFFIX,itaboo.info,Proxy +DOMAIN-SUFFIX,ithelp.ithome.com.tw,Proxy +DOMAIN-SUFFIX,its.caltech.edu,Proxy +DOMAIN-SUFFIX,itshidden.com,Proxy +DOMAIN-SUFFIX,itsliveradio.apple.com,Proxy +DOMAIN-SUFFIX,itweet.net,Proxy +DOMAIN-SUFFIX,iu45.com,Proxy +DOMAIN-SUFFIX,iuhrdf.org,Proxy +DOMAIN-SUFFIX,iverycd.com,Proxy +DOMAIN-SUFFIX,ixquick.com,Proxy +DOMAIN-SUFFIX,iyouport.com,Proxy +DOMAIN-SUFFIX,izaobao.us,Proxy +DOMAIN-SUFFIX,izles.net,Proxy +DOMAIN-SUFFIX,j.mp,Proxy +DOMAIN-SUFFIX,jalan.net,Proxy +DOMAIN-SUFFIX,japan-whores.com,Proxy +DOMAIN-SUFFIX,japanfirst.asianfreeforum.com,Proxy +DOMAIN-SUFFIX,javbus.com,Proxy +DOMAIN-SUFFIX,jayparkinsonmd.com,Proxy +DOMAIN-SUFFIX,jbtalks.cc,Proxy +DOMAIN-SUFFIX,jbtalks.com,Proxy +DOMAIN-SUFFIX,jbtalks.my,Proxy +DOMAIN-SUFFIX,jdwsy.com,Proxy +DOMAIN-SUFFIX,jeanyim.com,Proxy +DOMAIN-SUFFIX,jgoodies.com,Proxy +DOMAIN-SUFFIX,jiaoyou8.com,Proxy +DOMAIN-SUFFIX,jiehua.cz,Proxy +DOMAIN-SUFFIX,jieshibaobao.com,Proxy +DOMAIN-SUFFIX,jigong1024.com,Proxy +DOMAIN-SUFFIX,jimoparty.com,Proxy +DOMAIN-SUFFIX,jinbushe.org,Proxy +DOMAIN-SUFFIX,jingpin.org,Proxy +DOMAIN-SUFFIX,jitouch.com,Proxy +DOMAIN-SUFFIX,jkforum.net,Proxy +DOMAIN-SUFFIX,joachims.org,Proxy +DOMAIN-SUFFIX,jobso.tv,Proxy +DOMAIN-SUFFIX,joeedelman.com,Proxy +DOMAIN-SUFFIX,journalofdemocracy.org,Proxy +DOMAIN-SUFFIX,jp.hao123.com,Proxy +DOMAIN-SUFFIX,jpl.nasa.gov,Proxy +DOMAIN-SUFFIX,jpopforum.net,Proxy +DOMAIN-SUFFIX,jshint.com,Proxy +DOMAIN-SUFFIX,juliepost.com,Proxy +DOMAIN-SUFFIX,juliereyc.com,Proxy +DOMAIN-SUFFIX,junauza.com,Proxy +DOMAIN-SUFFIX,junefourth-20.net,Proxy +DOMAIN-SUFFIX,justfreevpn.com,Proxy +DOMAIN-SUFFIX,justtristan.com,Proxy +DOMAIN-SUFFIX,juyuange.org,Proxy +DOMAIN-SUFFIX,juziyue.com,Proxy +DOMAIN-SUFFIX,jwmusic.org,Proxy +DOMAIN-SUFFIX,jwpcdn.com,Proxy +DOMAIN-SUFFIX,jyxf.net,Proxy +DOMAIN-SUFFIX,jyzj.waqn.com,Proxy +DOMAIN-SUFFIX,k2.xrea.com,Proxy +DOMAIN-SUFFIX,ka-wai.com,Proxy +DOMAIN-SUFFIX,kagyuoffice.org,Proxy +DOMAIN-SUFFIX,kagyuoffice.org.tw,Proxy +DOMAIN-SUFFIX,kaiyuan.de,Proxy +DOMAIN-SUFFIX,kakao.com,Proxy +DOMAIN-SUFFIX,kanzhongguo.com,Proxy +DOMAIN-SUFFIX,kanzhongguo.eu,Proxy +DOMAIN-SUFFIX,karayou.com,Proxy +DOMAIN-SUFFIX,kat.cr,Proxy +DOMAIN-SUFFIX,kcsoftwares.com,Proxy +DOMAIN-SUFFIX,kechara.com,Proxy +DOMAIN-SUFFIX,keepandshare.com,Proxy +DOMAIN-SUFFIX,keepvid.com,Proxy +DOMAIN-SUFFIX,kendincos.net,Proxy +DOMAIN-SUFFIX,kenengba.com,Proxy +DOMAIN-SUFFIX,keontech.net,Proxy +DOMAIN-SUFFIX,khabdha.org,Proxy +DOMAIN-SUFFIX,khmusic.com.tw,Proxy +DOMAIN-SUFFIX,killwall.com,Proxy +DOMAIN-SUFFIX,kineox.free.fr,Proxy +DOMAIN-SUFFIX,kingdomsalvation.org,Proxy +DOMAIN-SUFFIX,kinghost.com,Proxy +DOMAIN-SUFFIX,kingstone.com.tw,Proxy +DOMAIN-SUFFIX,kissbbao.cn,Proxy +DOMAIN-SUFFIX,kiwi.kz,Proxy +DOMAIN-SUFFIX,klip.me,Proxy +DOMAIN-SUFFIX,kmt.org.tw,Proxy +DOMAIN-SUFFIX,knowledge.yahoo.com,Proxy +DOMAIN-SUFFIX,knowledgerush.com,Proxy +DOMAIN-SUFFIX,kodingen.com,Proxy +DOMAIN-SUFFIX,kompozer.net,Proxy +DOMAIN-SUFFIX,koolsolutions.com,Proxy +DOMAIN-SUFFIX,koornk.com,Proxy +DOMAIN-SUFFIX,kt.kcome.org,Proxy +DOMAIN-SUFFIX,kui.name,Proxy +DOMAIN-SUFFIX,kuliwang.com,Proxy +DOMAIN-SUFFIX,kun.im,Proxy +DOMAIN-SUFFIX,kurashsultan.com,Proxy +DOMAIN-SUFFIX,kurtmunger.com,Proxy +DOMAIN-SUFFIX,kusocity.com,Proxy +DOMAIN-SUFFIX,kwcg.ca,Proxy +DOMAIN-SUFFIX,kwongwah.com.my,Proxy +DOMAIN-SUFFIX,kyohk.net,Proxy +DOMAIN-SUFFIX,kzeng.info,Proxy +DOMAIN-SUFFIX,la-forum.org,Proxy +DOMAIN-SUFFIX,labiennale.org,Proxy +DOMAIN-SUFFIX,ladbrokes.com,Proxy +DOMAIN-SUFFIX,lagranepoca.com,Proxy +DOMAIN-SUFFIX,lalulalu.com,Proxy +DOMAIN-SUFFIX,lamenhu.com,Proxy +DOMAIN-SUFFIX,lancome.com,Proxy +DOMAIN-SUFFIX,laogai.org,Proxy +DOMAIN-SUFFIX,laomiu.com,Proxy +DOMAIN-SUFFIX,laoyang.info,Proxy +DOMAIN-SUFFIX,laptoplockdown.com,Proxy +DOMAIN-SUFFIX,laqingdan.net,Proxy +DOMAIN-SUFFIX,larsgeorge.com,Proxy +DOMAIN-SUFFIX,lastfm.es,Proxy +DOMAIN-SUFFIX,lastpass.com,Proxy +DOMAIN-SUFFIX,latelinenews.com,Proxy +DOMAIN-SUFFIX,latibet.org,Proxy +DOMAIN-SUFFIX,latimesblogs.latimes.com,Proxy +DOMAIN-SUFFIX,lazarsearlymusic.com,Proxy +DOMAIN-SUFFIX,leecheukyan.org,Proxy +DOMAIN-SUFFIX,legaltech.law.com,Proxy +DOMAIN-SUFFIX,leirentv.ca,Proxy +DOMAIN-SUFFIX,leisurecafe.ca,Proxy +DOMAIN-SUFFIX,lematin.ch,Proxy +DOMAIN-SUFFIX,lemonde.fr,Proxy +DOMAIN-SUFFIX,lenwhite.com,Proxy +DOMAIN-SUFFIX,lerosua.org,Proxy +DOMAIN-SUFFIX,lesoir.be,Proxy +DOMAIN-SUFFIX,lesscss.org,Proxy +DOMAIN-SUFFIX,letscorp.net,Proxy +DOMAIN-SUFFIX,liansi.org,Proxy +DOMAIN-SUFFIX,lianyue.net,Proxy +DOMAIN-SUFFIX,liaowangxizang.net,Proxy +DOMAIN-SUFFIX,lib.virginia.edu,Proxy +DOMAIN-SUFFIX,liberal.org.hk,Proxy +DOMAIN-SUFFIX,libertytimes.com.tw,Proxy +DOMAIN-SUFFIX,library.usc.cuhk.edu.hk,Proxy +DOMAIN-SUFFIX,licdn.com,Proxy +DOMAIN-SUFFIX,lich355.megabyet.net,Proxy +DOMAIN-SUFFIX,lidecheng.com,Proxy +DOMAIN-SUFFIX,life.fly4ever.me,Proxy +DOMAIN-SUFFIX,lifemiles.com,Proxy +DOMAIN-SUFFIX,limiao.net,Proxy +DOMAIN-SUFFIX,linglingfa.com,Proxy +DOMAIN-SUFFIX,lingvodics.com,Proxy +DOMAIN-SUFFIX,linkedin.com,Proxy +DOMAIN-SUFFIX,linkideo.com,Proxy +DOMAIN-SUFFIX,linksalpha.com,Proxy +DOMAIN-SUFFIX,linode.com,Proxy +DOMAIN-SUFFIX,linux-engineer.net,Proxy +DOMAIN-SUFFIX,linuxconfig.org,Proxy +DOMAIN-SUFFIX,linuxreviews.org,Proxy +DOMAIN-SUFFIX,linuxtoy.org,Proxy +DOMAIN-SUFFIX,lipuman.com,Proxy +DOMAIN-SUFFIX,list.ly,Proxy +DOMAIN-SUFFIX,listorious.com,Proxy +DOMAIN-SUFFIX,lists.debian.org,Proxy +DOMAIN-SUFFIX,lists.w3.org,Proxy +DOMAIN-SUFFIX,lithium.com,Proxy +DOMAIN-SUFFIX,littlebigdetails.com,Proxy +DOMAIN-SUFFIX,liu.lu,Proxy +DOMAIN-SUFFIX,liudejun.com,Proxy +DOMAIN-SUFFIX,liuhanyu.com,Proxy +DOMAIN-SUFFIX,liujianshu.com,Proxy +DOMAIN-SUFFIX,liuxiaotong.com,Proxy +DOMAIN-SUFFIX,liveleak.com,Proxy +DOMAIN-SUFFIX,livestation.com,Proxy +DOMAIN-SUFFIX,livestream.com,Proxy +DOMAIN-SUFFIX,livevideo.com,Proxy +DOMAIN-SUFFIX,livingonline.us,Proxy +DOMAIN-SUFFIX,livingstream.com,Proxy +DOMAIN-SUFFIX,lizhizhuangbi.com,Proxy +DOMAIN-SUFFIX,lkcn.net,Proxy +DOMAIN-SUFFIX,llnwd.net,Proxy +DOMAIN-SUFFIX,localpresshk.com,Proxy +DOMAIN-SUFFIX,lockdown.com,Proxy +DOMAIN-SUFFIX,lockestek.com,Proxy +DOMAIN-SUFFIX,lofi.e-hentai.org,Proxy +DOMAIN-SUFFIX,log.riku.me,Proxy +DOMAIN-SUFFIX,logbot.net,Proxy +DOMAIN-SUFFIX,logiqx.com,Proxy +DOMAIN-SUFFIX,logmike.com,Proxy +DOMAIN-SUFFIX,loiclemeur.com,Proxy +DOMAIN-SUFFIX,london.neighborhoodr.com,Proxy +DOMAIN-SUFFIX,longhair.hk,Proxy +DOMAIN-SUFFIX,longtermly.net,Proxy +DOMAIN-SUFFIX,lookatgame.com,Proxy +DOMAIN-SUFFIX,lookingglasstheatre.org,Proxy +DOMAIN-SUFFIX,lookpic.com,Proxy +DOMAIN-SUFFIX,looktoronto.com,Proxy +DOMAIN-SUFFIX,lotsawahouse.org,Proxy +DOMAIN-SUFFIX,lotuslight.org.tw,Proxy +DOMAIN-SUFFIX,lovequicksilver.com,Proxy +DOMAIN-SUFFIX,lrfz.com,Proxy +DOMAIN-SUFFIX,lrip.org,Proxy +DOMAIN-SUFFIX,lsd.org.hk,Proxy +DOMAIN-SUFFIX,lsforum.net,Proxy +DOMAIN-SUFFIX,lsm.org,Proxy +DOMAIN-SUFFIX,lsmchinese.org,Proxy +DOMAIN-SUFFIX,lsmkorean.org,Proxy +DOMAIN-SUFFIX,lsmradio.com,Proxy +DOMAIN-SUFFIX,lsxszzg.com,Proxy +DOMAIN-SUFFIX,ltn.com.tw,Proxy +DOMAIN-SUFFIX,luntan.zaobao.com,Proxy +DOMAIN-SUFFIX,lupm.org,Proxy +DOMAIN-SUFFIX,lushstories.com,Proxy +DOMAIN-SUFFIX,lvhai.org,Proxy +DOMAIN-SUFFIX,lvv2.com,Proxy +DOMAIN-SUFFIX,lyricsquote.com,Proxy +DOMAIN-SUFFIX,m-sport.co.uk,Proxy +DOMAIN-SUFFIX,m-team.cc,Proxy +DOMAIN-SUFFIX,m.oulove.org,Proxy +DOMAIN-SUFFIX,m.plixi.com,Proxy +DOMAIN-SUFFIX,m.slandr.net,Proxy +DOMAIN-SUFFIX,m.tweete.net,Proxy +DOMAIN-SUFFIX,ma.hao123.com,Proxy +DOMAIN-SUFFIX,mac.com,Proxy +DOMAIN-SUFFIX,macgamestore.com,Proxy +DOMAIN-SUFFIX,macrovpn.com,Proxy +DOMAIN-SUFFIX,macys.com,Proxy +DOMAIN-SUFFIX,mad-ar.ch,Proxy +DOMAIN-SUFFIX,madmenunbuttoned.com,Proxy +DOMAIN-SUFFIX,magazines.sina.com.tw,Proxy +DOMAIN-SUFFIX,maiio.net,Proxy +DOMAIN-SUFFIX,mail-archive.com,Proxy +DOMAIN-SUFFIX,mailchimp.com,Proxy +DOMAIN-SUFFIX,maiplus.com,Proxy +DOMAIN-SUFFIX,makemymood.com,Proxy +DOMAIN-SUFFIX,makzhou.warehouse333.com,Proxy +DOMAIN-SUFFIX,malaysiakini.com,Proxy +DOMAIN-SUFFIX,marc.info,Proxy +DOMAIN-SUFFIX,marco.org,Proxy +DOMAIN-SUFFIX,marguerite.su,Proxy +DOMAIN-SUFFIX,marines.mil,Proxy +DOMAIN-SUFFIX,marinsm.com,Proxy +DOMAIN-SUFFIX,markmail.org,Proxy +DOMAIN-SUFFIX,markmilian.com,Proxy +DOMAIN-SUFFIX,martau.com,Proxy +DOMAIN-SUFFIX,martincartoons.com,Proxy +DOMAIN-SUFFIX,martsangkagyuofficial.org,Proxy +DOMAIN-SUFFIX,maruta.be,Proxy +DOMAIN-SUFFIX,marxist.com,Proxy +DOMAIN-SUFFIX,marxist.net,Proxy +DOMAIN-SUFFIX,marxists.org,Proxy +DOMAIN-SUFFIX,mash.to,Proxy +DOMAIN-SUFFIX,mashable.com,Proxy +DOMAIN-SUFFIX,matainja.com,Proxy +DOMAIN-SUFFIX,mathiew-badimon.com,Proxy +DOMAIN-SUFFIX,matsushimakaede.com,Proxy +DOMAIN-SUFFIX,maturejp.com,Proxy +DOMAIN-SUFFIX,maxgif.com,Proxy +DOMAIN-SUFFIX,mayimayi.com,Proxy +DOMAIN-SUFFIX,mcadforums.com,Proxy +DOMAIN-SUFFIX,mcfog.com,Proxy +DOMAIN-SUFFIX,md-t.org,Proxy +DOMAIN-SUFFIX,mediafire.com,Proxy +DOMAIN-SUFFIX,meetup.com,Proxy +DOMAIN-SUFFIX,mefeedia.com,Proxy +DOMAIN-SUFFIX,megaporn.com,Proxy +DOMAIN-SUFFIX,megaproxy.com,Proxy +DOMAIN-SUFFIX,megarotic.com,Proxy +DOMAIN-SUFFIX,megaupload.com,Proxy +DOMAIN-SUFFIX,megavideo.com,Proxy +DOMAIN-SUFFIX,megurineluka.com,Proxy +DOMAIN-SUFFIX,meirixiaochao.com,Proxy +DOMAIN-SUFFIX,melon-peach.com,Proxy +DOMAIN-SUFFIX,meme.yahoo.com,Proxy +DOMAIN-SUFFIX,memedia.cn,Proxy +DOMAIN-SUFFIX,memehk.com,Proxy +DOMAIN-SUFFIX,memrijttm.org,Proxy +DOMAIN-SUFFIX,merit-times.com.tw,Proxy +DOMAIN-SUFFIX,mesotw.com,Proxy +DOMAIN-SUFFIX,metacafe.com,Proxy +DOMAIN-SUFFIX,metarthunter.com,Proxy +DOMAIN-SUFFIX,meteorshowersonline.com,Proxy +DOMAIN-SUFFIX,metro.taipei,Proxy +DOMAIN-SUFFIX,metrolife.ca,Proxy +DOMAIN-SUFFIX,mfxmedia.com,Proxy +DOMAIN-SUFFIX,mgoon.com,Proxy +DOMAIN-SUFFIX,mgstage.com,Proxy +DOMAIN-SUFFIX,mh4u.org,Proxy +DOMAIN-SUFFIX,mhradio.org,Proxy +DOMAIN-SUFFIX,michaelanti.com,Proxy +DOMAIN-SUFFIX,michaelmarketl.com,Proxy +DOMAIN-SUFFIX,middle-way.net,Proxy +DOMAIN-SUFFIX,mihk.hk,Proxy +DOMAIN-SUFFIX,mihua.org,Proxy +DOMAIN-SUFFIX,mike.cz.cc,Proxy +DOMAIN-SUFFIX,mimivip.com,Proxy +DOMAIN-SUFFIX,mimivv.com,Proxy +DOMAIN-SUFFIX,mindrolling.org,Proxy +DOMAIN-SUFFIX,minghui-a.org,Proxy +DOMAIN-SUFFIX,minghui-b.org,Proxy +DOMAIN-SUFFIX,minghui-school.org,Proxy +DOMAIN-SUFFIX,minghui.org,Proxy +DOMAIN-SUFFIX,mingjinglishi.com,Proxy +DOMAIN-SUFFIX,mingjingnews.com,Proxy +DOMAIN-SUFFIX,mingjingtimes.com,Proxy +DOMAIN-SUFFIX,mingpao.com,Proxy +DOMAIN-SUFFIX,mingpaocanada.com,Proxy +DOMAIN-SUFFIX,mingpaomonthly.com,Proxy +DOMAIN-SUFFIX,mingpaonews.com,Proxy +DOMAIN-SUFFIX,mingpaony.com,Proxy +DOMAIN-SUFFIX,mingpaosf.com,Proxy +DOMAIN-SUFFIX,mingpaotor.com,Proxy +DOMAIN-SUFFIX,mingpaovan.com,Proxy +DOMAIN-SUFFIX,mingshengbao.com,Proxy +DOMAIN-SUFFIX,minimalmac.com,Proxy +DOMAIN-SUFFIX,mininova.org,Proxy +DOMAIN-SUFFIX,ministrybooks.org,Proxy +DOMAIN-SUFFIX,minus.com,Proxy +DOMAIN-SUFFIX,minzhuhua.net,Proxy +DOMAIN-SUFFIX,minzhuzhanxian.com,Proxy +DOMAIN-SUFFIX,minzhuzhongguo.org,Proxy +DOMAIN-SUFFIX,miroguide.com,Proxy +DOMAIN-SUFFIX,mirrorbooks.com,Proxy +DOMAIN-SUFFIX,mitbbs.com,Proxy +DOMAIN-SUFFIX,mixedmedialabs.com,Proxy +DOMAIN-SUFFIX,mixero.com,Proxy +DOMAIN-SUFFIX,mixpod.com,Proxy +DOMAIN-SUFFIX,mixx.com,Proxy +DOMAIN-SUFFIX,mizzmona.com,Proxy +DOMAIN-SUFFIX,mjlsh.usc.cuhk.edu.hk,Proxy +DOMAIN-SUFFIX,mk5000.com,Proxy +DOMAIN-SUFFIX,mlcool.com,Proxy +DOMAIN-SUFFIX,mmaaxx.com,Proxy +DOMAIN-SUFFIX,mmmca.com,Proxy +DOMAIN-SUFFIX,mobatek.net,Proxy +DOMAIN-SUFFIX,mobile01.com,Proxy +DOMAIN-SUFFIX,mobileways.de,Proxy +DOMAIN-SUFFIX,moby.to,Proxy +DOMAIN-SUFFIX,mobypicture.com,Proxy +DOMAIN-SUFFIX,mockable.io,Proxy +DOMAIN-SUFFIX,modedamour.com,Proxy +DOMAIN-SUFFIX,modfetish.com,Proxy +DOMAIN-SUFFIX,modmyi.com,Proxy +DOMAIN-SUFFIX,mog.com,Proxy +DOMAIN-SUFFIX,molihua.org,Proxy +DOMAIN-SUFFIX,mondex.org,Proxy +DOMAIN-SUFFIX,monlamit.org,Proxy +DOMAIN-SUFFIX,morningsun.org,Proxy +DOMAIN-SUFFIX,movabletype.com,Proxy +DOMAIN-SUFFIX,moviefap.com,Proxy +DOMAIN-SUFFIX,moztw.org,Proxy +DOMAIN-SUFFIX,mp3ye.eu,Proxy +DOMAIN-SUFFIX,mpettis.com,Proxy +DOMAIN-SUFFIX,mpfinance.com,Proxy +DOMAIN-SUFFIX,mpinews.com,Proxy +DOMAIN-SUFFIX,mrdoob.com,Proxy +DOMAIN-SUFFIX,mrtweet.com,Proxy +DOMAIN-SUFFIX,msguancha.com,Proxy +DOMAIN-SUFFIX,mthruf.com,Proxy +DOMAIN-SUFFIX,mtw.tl,Proxy +DOMAIN-SUFFIX,multiply.com,Proxy +DOMAIN-SUFFIX,multiproxy.org,Proxy +DOMAIN-SUFFIX,multiupload.com,Proxy +DOMAIN-SUFFIX,muouju.com,Proxy +DOMAIN-SUFFIX,muselinks.co.jp,Proxy +DOMAIN-SUFFIX,muzi.com,Proxy +DOMAIN-SUFFIX,muzi.net,Proxy +DOMAIN-SUFFIX,muzu.tv,Proxy +DOMAIN-SUFFIX,mx981.com,Proxy +DOMAIN-SUFFIX,my-addr.com,Proxy +DOMAIN-SUFFIX,my-proxy.com,Proxy +DOMAIN-SUFFIX,my.keso.cn,Proxy +DOMAIN-SUFFIX,my.opera.com,Proxy +DOMAIN-SUFFIX,myactimes.com,Proxy +DOMAIN-SUFFIX,myaudiocast.com,Proxy +DOMAIN-SUFFIX,myav.com.tw,Proxy +DOMAIN-SUFFIX,mycould.com,Proxy +DOMAIN-SUFFIX,myeclipseide.com,Proxy +DOMAIN-SUFFIX,myequil.com,Proxy +DOMAIN-SUFFIX,myforum.com.hk,Proxy +DOMAIN-SUFFIX,myforum.com.uk,Proxy +DOMAIN-SUFFIX,myfreshnet.com,Proxy +DOMAIN-SUFFIX,myopenid.com,Proxy +DOMAIN-SUFFIX,myparagliding.com,Proxy +DOMAIN-SUFFIX,mypopescu.com,Proxy +DOMAIN-SUFFIX,myshare.url.com.tw,Proxy +DOMAIN-SUFFIX,mysinablog.com,Proxy +DOMAIN-SUFFIX,myspace.com,Proxy +DOMAIN-SUFFIX,naacoalition.org,Proxy +DOMAIN-SUFFIX,naitik.net,Proxy +DOMAIN-SUFFIX,nakido.com,Proxy +DOMAIN-SUFFIX,name.com,Proxy +DOMAIN-SUFFIX,namsisi.com,Proxy +DOMAIN-SUFFIX,nanyang.com,Proxy +DOMAIN-SUFFIX,nanyangpost.com,Proxy +DOMAIN-SUFFIX,nanzao.com,Proxy +DOMAIN-SUFFIX,naol.ca,Proxy +DOMAIN-SUFFIX,national-lottery.co.uk,Proxy +DOMAIN-SUFFIX,navicat.com,Proxy +DOMAIN-SUFFIX,navigeaters.com,Proxy +DOMAIN-SUFFIX,navy.mil,Proxy +DOMAIN-SUFFIX,nbc.com,Proxy +DOMAIN-SUFFIX,nccwatch.org.tw,Proxy +DOMAIN-SUFFIX,nch.com.tw,Proxy +DOMAIN-SUFFIX,ncn.org,Proxy +DOMAIN-SUFFIX,nde.de,Proxy +DOMAIN-SUFFIX,ndr.de,Proxy +DOMAIN-SUFFIX,ned.org,Proxy +DOMAIN-SUFFIX,nekoslovakia.net,Proxy +DOMAIN-SUFFIX,nemesis2.qx.net,Proxy +DOMAIN-SUFFIX,netcolony.com,Proxy +DOMAIN-SUFFIX,netflix.com,Proxy +DOMAIN-SUFFIX,netme.cc,Proxy +DOMAIN-SUFFIX,networkedblogs.com,Proxy +DOMAIN-SUFFIX,neverforget8964.org,Proxy +DOMAIN-SUFFIX,new-3lunch.net,Proxy +DOMAIN-SUFFIX,new-akiba.com,Proxy +DOMAIN-SUFFIX,newcenturymc.com,Proxy +DOMAIN-SUFFIX,newcenturynews.com,Proxy +DOMAIN-SUFFIX,newchen.com,Proxy +DOMAIN-SUFFIX,newgrounds.com,Proxy +DOMAIN-SUFFIX,newlandmagazine.com.au,Proxy +DOMAIN-SUFFIX,newmobilelife.com,Proxy +DOMAIN-SUFFIX,news.atebits.com,Proxy +DOMAIN-SUFFIX,news.bbc.co.uk,Proxy +DOMAIN-SUFFIX,news.cnyes.com,Proxy +DOMAIN-SUFFIX,news.ghostery.com,Proxy +DOMAIN-SUFFIX,news.msn.com.tw,Proxy +DOMAIN-SUFFIX,news.now.com,Proxy +DOMAIN-SUFFIX,news.omy.sg,Proxy +DOMAIN-SUFFIX,news.sinchew.com.my,Proxy +DOMAIN-SUFFIX,news.singtao.ca,Proxy +DOMAIN-SUFFIX,news100.com.tw,Proxy +DOMAIN-SUFFIX,newsancai.com,Proxy +DOMAIN-SUFFIX,newscn.org,Proxy +DOMAIN-SUFFIX,newsforums.bbc.co.uk,Proxy +DOMAIN-SUFFIX,newsminer.com,Proxy +DOMAIN-SUFFIX,newspeak.cc,Proxy +DOMAIN-SUFFIX,newstapa.org,Proxy +DOMAIN-SUFFIX,newtaiwan.com.tw,Proxy +DOMAIN-SUFFIX,newtalk.tw,Proxy +DOMAIN-SUFFIX,newyorktimes.com,Proxy +DOMAIN-SUFFIX,nextmedia.com,Proxy +DOMAIN-SUFFIX,nexton-net.jp,Proxy +DOMAIN-SUFFIX,nexttv.com.tw,Proxy +DOMAIN-SUFFIX,nf.id.au,Proxy +DOMAIN-SUFFIX,nga.mil,Proxy +DOMAIN-SUFFIX,ngensis.com,Proxy +DOMAIN-SUFFIX,ngrok.com,Proxy +DOMAIN-SUFFIX,nic.cz.cc,Proxy +DOMAIN-SUFFIX,nicovideo.jp,Proxy +DOMAIN-SUFFIX,nighost.org,Proxy +DOMAIN-SUFFIX,ninecommentaries.com,Proxy +DOMAIN-SUFFIX,nintendium.com,Proxy +DOMAIN-SUFFIX,niusnews.com,Proxy +DOMAIN-SUFFIX,njactb.org,Proxy +DOMAIN-SUFFIX,njuice.com,Proxy +DOMAIN-SUFFIX,nlfreevpn.com,Proxy +DOMAIN-SUFFIX,nobel.se,Proxy +DOMAIN-SUFFIX,nobelprize.org,Proxy +DOMAIN-SUFFIX,nobodycanstop.us,Proxy +DOMAIN-SUFFIX,nokogiri.org,Proxy +DOMAIN-SUFFIX,nokola.com,Proxy +DOMAIN-SUFFIX,noobbox.com,Proxy +DOMAIN-SUFFIX,norbulingka.org,Proxy +DOMAIN-SUFFIX,nordstrom.com,Proxy +DOMAIN-SUFFIX,nordstromimage.com,Proxy +DOMAIN-SUFFIX,notes.alexdong.com,Proxy +DOMAIN-SUFFIX,novelasia.com,Proxy +DOMAIN-SUFFIX,nownews.com,Proxy +DOMAIN-SUFFIX,nowtorrents.com,Proxy +DOMAIN-SUFFIX,noypf.com,Proxy +DOMAIN-SUFFIX,npa.go.jp,Proxy +DOMAIN-SUFFIX,nps.gov,Proxy +DOMAIN-SUFFIX,nrk.no,Proxy +DOMAIN-SUFFIX,nsc.gov.tw,Proxy +DOMAIN-SUFFIX,ntd.tv,Proxy +DOMAIN-SUFFIX,nubiles.net,Proxy +DOMAIN-SUFFIX,nuexpo.com,Proxy +DOMAIN-SUFFIX,nurgo-software.com,Proxy +DOMAIN-SUFFIX,nuuvem.com,Proxy +DOMAIN-SUFFIX,nuvid.com,Proxy +DOMAIN-SUFFIX,nuzcom.com,Proxy +DOMAIN-SUFFIX,nvquan.org,Proxy +DOMAIN-SUFFIX,nwtca.org,Proxy +DOMAIN-SUFFIX,ny.visiontimes.com,Proxy +DOMAIN-SUFFIX,nyaa.se,Proxy +DOMAIN-SUFFIX,nydus.ca,Proxy +DOMAIN-SUFFIX,nysingtao.com,Proxy +DOMAIN-SUFFIX,nyt.com,Proxy +DOMAIN-SUFFIX,nytco.com,Proxy +DOMAIN-SUFFIX,nytimes.com,Proxy +DOMAIN-SUFFIX,nytimg.com,Proxy +DOMAIN-SUFFIX,oasic.net,Proxy +DOMAIN-SUFFIX,oclp.hk,Proxy +DOMAIN-SUFFIX,ocsp.digicert.com,Proxy +DOMAIN-SUFFIX,october-review.org,Proxy +DOMAIN-SUFFIX,officeoftibet.com,Proxy +DOMAIN-SUFFIX,ogaoga.org,Proxy +DOMAIN-SUFFIX,oikos.com.tw,Proxy +DOMAIN-SUFFIX,oiktv.com,Proxy +DOMAIN-SUFFIX,oizoblog.com,Proxy +DOMAIN-SUFFIX,okayfreedom.com,Proxy +DOMAIN-SUFFIX,old-cat.net,Proxy +DOMAIN-SUFFIX,old.honeynet.org,Proxy +DOMAIN-SUFFIX,old.nabble.com,Proxy +DOMAIN-SUFFIX,olumpo.com,Proxy +DOMAIN-SUFFIX,olympicwatch.org,Proxy +DOMAIN-SUFFIX,omgili.com,Proxy +DOMAIN-SUFFIX,omnitalk.com,Proxy +DOMAIN-SUFFIX,omnitalk.org,Proxy +DOMAIN-SUFFIX,on.cc,Proxy +DOMAIN-SUFFIX,one.xthost.info,Proxy +DOMAIN-SUFFIX,onedrive.live.com,Proxy +DOMAIN-SUFFIX,onion.city,Proxy +DOMAIN-SUFFIX,onlylady.cn,Proxy +DOMAIN-SUFFIX,onmoon.com,Proxy +DOMAIN-SUFFIX,onmoon.net,Proxy +DOMAIN-SUFFIX,ontrac.com,Proxy +DOMAIN-SUFFIX,oopsforum.com,Proxy +DOMAIN-SUFFIX,open-consoles-news.com,Proxy +DOMAIN-SUFFIX,open.com.hk,Proxy +DOMAIN-SUFFIX,opendemocracy.net,Proxy +DOMAIN-SUFFIX,openid.net,Proxy +DOMAIN-SUFFIX,openleaks.org,Proxy +DOMAIN-SUFFIX,openvpn.net,Proxy +DOMAIN-SUFFIX,openwebster.com,Proxy +DOMAIN-SUFFIX,openwrt.org,Proxy +DOMAIN-SUFFIX,opml.radiotime.com,Proxy +DOMAIN-SUFFIX,opnir.com,Proxy +DOMAIN-SUFFIX,orchidbbs.com,Proxy +DOMAIN-SUFFIX,organharvestinvestigation.net,Proxy +DOMAIN-SUFFIX,orient-doll.com,Proxy +DOMAIN-SUFFIX,orientaldaily.com.my,Proxy +DOMAIN-SUFFIX,orientaldaily.on.cc,Proxy +DOMAIN-SUFFIX,orn.jp,Proxy +DOMAIN-SUFFIX,orzistic.org,Proxy +DOMAIN-SUFFIX,osaka69.com,Proxy +DOMAIN-SUFFIX,osfoora.com,Proxy +DOMAIN-SUFFIX,osmdroid.net,Proxy +DOMAIN-SUFFIX,ourdearamy.com,Proxy +DOMAIN-SUFFIX,oursogo.com,Proxy +DOMAIN-SUFFIX,oursteps.com.au,Proxy +DOMAIN-SUFFIX,overlapr.com,Proxy +DOMAIN-SUFFIX,ow.ly,Proxy +DOMAIN-SUFFIX,owind.com,Proxy +DOMAIN-SUFFIX,owl.li,Proxy +DOMAIN-SUFFIX,oxid.it,Proxy +DOMAIN-SUFFIX,oyax.com,Proxy +DOMAIN-SUFFIX,ozchinese.com,Proxy +DOMAIN-SUFFIX,ozyoyo.com,Proxy +DOMAIN-SUFFIX,p-cdn.com,Proxy +DOMAIN-SUFFIX,pacificpoker.com,Proxy +DOMAIN-SUFFIX,packages.debian.org,Proxy +DOMAIN-SUFFIX,packetix.net,Proxy +DOMAIN-SUFFIX,paddle.com,Proxy +DOMAIN-SUFFIX,padmanet.com,Proxy +DOMAIN-SUFFIX,page.bid.yahoo.com,Proxy +DOMAIN-SUFFIX,page2rss.com,Proxy +DOMAIN-SUFFIX,pagodabox.com,Proxy +DOMAIN-SUFFIX,paint.net,Proxy +DOMAIN-SUFFIX,palacemoon.com,Proxy +DOMAIN-SUFFIX,paljorpublications.com,Proxy +DOMAIN-SUFFIX,pandora.com,Proxy +DOMAIN-SUFFIX,pandora.tv,Proxy +DOMAIN-SUFFIX,panluan.net,Proxy +DOMAIN-SUFFIX,panoramio.com,Proxy +DOMAIN-SUFFIX,pao-pao.net,Proxy +DOMAIN-SUFFIX,paper-replika.com,Proxy +DOMAIN-SUFFIX,paper.li,Proxy +DOMAIN-SUFFIX,paperb.us,Proxy +DOMAIN-SUFFIX,parade.com,Proxy +DOMAIN-SUFFIX,parislemon.com,Proxy +DOMAIN-SUFFIX,parkansky.com,Proxy +DOMAIN-SUFFIX,passion.com,Proxy +DOMAIN-SUFFIX,passiontimes.hk,Proxy +DOMAIN-SUFFIX,pastebin.com,Proxy +DOMAIN-SUFFIX,pastie.org,Proxy +DOMAIN-SUFFIX,pbs.org,Proxy +DOMAIN-SUFFIX,pbwiki.com,Proxy +DOMAIN-SUFFIX,pbworks.com,Proxy +DOMAIN-SUFFIX,pbxes.com,Proxy +DOMAIN-SUFFIX,pbxes.org,Proxy +DOMAIN-SUFFIX,pcdiscuss.com,Proxy +DOMAIN-SUFFIX,pcdvd.com.tw,Proxy +DOMAIN-SUFFIX,pchome.com.tw,Proxy +DOMAIN-SUFFIX,pcij.org,Proxy +DOMAIN-SUFFIX,pct.org.tw,Proxy +DOMAIN-SUFFIX,pdetails.com,Proxy +DOMAIN-SUFFIX,pdproxy.com,Proxy +DOMAIN-SUFFIX,pds.nasa.gov,Proxy +DOMAIN-SUFFIX,peace.ca,Proxy +DOMAIN-SUFFIX,peacefire.org,Proxy +DOMAIN-SUFFIX,peacehall.com,Proxy +DOMAIN-SUFFIX,pearlher.org,Proxy +DOMAIN-SUFFIX,peeasian.com,Proxy +DOMAIN-SUFFIX,peerpong.com,Proxy +DOMAIN-SUFFIX,pekingduck.org,Proxy +DOMAIN-SUFFIX,pengyulong.com,Proxy +DOMAIN-SUFFIX,penthouse.com,Proxy +DOMAIN-SUFFIX,peopo.org,Proxy +DOMAIN-SUFFIX,percy.in,Proxy +DOMAIN-SUFFIX,perfectgirls.net,Proxy +DOMAIN-SUFFIX,perfectvpn.net,Proxy +DOMAIN-SUFFIX,perfspot.com,Proxy +DOMAIN-SUFFIX,perlhowto.com,Proxy +DOMAIN-SUFFIX,persecutionblog.com,Proxy +DOMAIN-SUFFIX,phayul.com,Proxy +DOMAIN-SUFFIX,philly.com,Proxy +DOMAIN-SUFFIX,photo.utom.us,Proxy +DOMAIN-SUFFIX,photodharma.net,Proxy +DOMAIN-SUFFIX,photofocus.com,Proxy +DOMAIN-SUFFIX,photos.dailyme.com,Proxy +DOMAIN-SUFFIX,phuquocservices.com,Proxy +DOMAIN-SUFFIX,picidae.net,Proxy +DOMAIN-SUFFIX,picturedip.com,Proxy +DOMAIN-SUFFIX,pictures.playboy.com,Proxy +DOMAIN-SUFFIX,picturesocial.com,Proxy +DOMAIN-SUFFIX,pidown.com,Proxy +DOMAIN-SUFFIX,pign.net,Proxy +DOMAIN-SUFFIX,pimg.tw,Proxy +DOMAIN-SUFFIX,pin6.com,Proxy +DOMAIN-SUFFIX,pinboard.in,Proxy +DOMAIN-SUFFIX,ping.fm,Proxy +DOMAIN-SUFFIX,pinimg.com,Proxy +DOMAIN-SUFFIX,pinoy-n.com,Proxy +DOMAIN-SUFFIX,pinporn.com,Proxy +DOMAIN-SUFFIX,pinterest.com,Proxy +DOMAIN-SUFFIX,pioneer-worker.forums-free.com,Proxy +DOMAIN-SUFFIX,piposay.com,Proxy +DOMAIN-SUFFIX,piring.com,Proxy +DOMAIN-SUFFIX,pixelqi.com,Proxy +DOMAIN-SUFFIX,pixnet.net,Proxy +DOMAIN-SUFFIX,pk.com,Proxy +DOMAIN-SUFFIX,placemix.com,Proxy +DOMAIN-SUFFIX,planetsuzy.org,Proxy +DOMAIN-SUFFIX,playboy.com,Proxy +DOMAIN-SUFFIX,playpcesor.com,Proxy +DOMAIN-SUFFIX,plays.com.tw,Proxy +DOMAIN-SUFFIX,plm.org.hk,Proxy +DOMAIN-SUFFIX,plunder.com,Proxy +DOMAIN-SUFFIX,plurktop.mmdays.com,Proxy +DOMAIN-SUFFIX,plus28.com,Proxy +DOMAIN-SUFFIX,plusbb.com,Proxy +DOMAIN-SUFFIX,pmates.com,Proxy +DOMAIN-SUFFIX,po2b.com,Proxy +DOMAIN-SUFFIX,podictionary.com,Proxy +DOMAIN-SUFFIX,pokerstars.com,Proxy +DOMAIN-SUFFIX,politicalconsultation.org,Proxy +DOMAIN-SUFFIX,popapp.in,Proxy +DOMAIN-SUFFIX,popularpages.net,Proxy +DOMAIN-SUFFIX,popvote.hk,Proxy +DOMAIN-SUFFIX,porn.com,Proxy +DOMAIN-SUFFIX,porn2.com,Proxy +DOMAIN-SUFFIX,pornbase.org,Proxy +DOMAIN-SUFFIX,pornhd.com,Proxy +DOMAIN-SUFFIX,pornhub.com,Proxy +DOMAIN-SUFFIX,pornmm.net,Proxy +DOMAIN-SUFFIX,pornoxo.com,Proxy +DOMAIN-SUFFIX,pornrapidshare.com,Proxy +DOMAIN-SUFFIX,pornstarclub.com,Proxy +DOMAIN-SUFFIX,porntube.com,Proxy +DOMAIN-SUFFIX,pornvisit.com,Proxy +DOMAIN-SUFFIX,portablevpn.nl,Proxy +DOMAIN-SUFFIX,pose.com,Proxy +DOMAIN-SUFFIX,post.anyu.org,Proxy +DOMAIN-SUFFIX,post.ly,Proxy +DOMAIN-SUFFIX,post852.com,Proxy +DOMAIN-SUFFIX,postadult.com,Proxy +DOMAIN-SUFFIX,posterous.com,Proxy +DOMAIN-SUFFIX,power.com,Proxy +DOMAIN-SUFFIX,powerapple.com,Proxy +DOMAIN-SUFFIX,powercx.com,Proxy +DOMAIN-SUFFIX,powerpointninja.com,Proxy +DOMAIN-SUFFIX,premeforwindows7.com,Proxy +DOMAIN-SUFFIX,presentationzen.com,Proxy +DOMAIN-SUFFIX,prestige-av.com,Proxy +DOMAIN-SUFFIX,prisoneralert.com,Proxy +DOMAIN-SUFFIX,pritunl.com,Proxy +DOMAIN-SUFFIX,privacybox.de,Proxy +DOMAIN-SUFFIX,privateinternetaccess.com,Proxy +DOMAIN-SUFFIX,privatepaste.com,Proxy +DOMAIN-SUFFIX,privatetunnel.com,Proxy +DOMAIN-SUFFIX,privoxy.org,Proxy +DOMAIN-SUFFIX,procopytips.com,Proxy +DOMAIN-SUFFIX,proctoru.com,Proxy +DOMAIN-SUFFIX,prosiben.de,Proxy +DOMAIN-SUFFIX,provideocoalition.com,Proxy +DOMAIN-SUFFIX,proxifier.com,Proxy +DOMAIN-SUFFIX,proxomitron.info,Proxy +DOMAIN-SUFFIX,proxy.org,Proxy +DOMAIN-SUFFIX,proxypy.net,Proxy +DOMAIN-SUFFIX,proxyroad.com,Proxy +DOMAIN-SUFFIX,prozz.net,Proxy +DOMAIN-SUFFIX,psblog.name,Proxy +DOMAIN-SUFFIX,psiphon.ca,Proxy +DOMAIN-SUFFIX,psiphon.civisec.org,Proxy +DOMAIN-SUFFIX,pts.org.tw,Proxy +DOMAIN-SUFFIX,ptt.cc,Proxy +DOMAIN-SUFFIX,pubu.com.tw,Proxy +DOMAIN-SUFFIX,puffinbrowser.com,Proxy +DOMAIN-SUFFIX,puffstore.com,Proxy +DOMAIN-SUFFIX,pullfolio.com,Proxy +DOMAIN-SUFFIX,pulse.yahoo.com,Proxy +DOMAIN-SUFFIX,pure18.com,Proxy +DOMAIN-SUFFIX,pureconcepts.net,Proxy +DOMAIN-SUFFIX,pureinsight.org,Proxy +DOMAIN-SUFFIX,purepdf.com,Proxy +DOMAIN-SUFFIX,purevpn.com,Proxy +DOMAIN-SUFFIX,putlocker.com,Proxy +DOMAIN-SUFFIX,putty.org,Proxy +DOMAIN-SUFFIX,puttycm.free.fr,Proxy +DOMAIN-SUFFIX,pwned.com,Proxy +DOMAIN-SUFFIX,pypi.python.org,Proxy +DOMAIN-SUFFIX,python.com,Proxy +DOMAIN-SUFFIX,python.com.tw,Proxy +DOMAIN-SUFFIX,qanote.com,Proxy +DOMAIN-SUFFIX,qi-gong.me,Proxy +DOMAIN-SUFFIX,qidian.ca,Proxy +DOMAIN-SUFFIX,qienkuen.org,Proxy +DOMAIN-SUFFIX,qiwen.lu,Proxy +DOMAIN-SUFFIX,qixianglu.cn,Proxy +DOMAIN-SUFFIX,qkshare.com,Proxy +DOMAIN-SUFFIX,qoos.com,Proxy +DOMAIN-SUFFIX,qq.co.za,Proxy +DOMAIN-SUFFIX,qstatus.com,Proxy +DOMAIN-SUFFIX,qtrac.eu,Proxy +DOMAIN-SUFFIX,qtweeter.com,Proxy +DOMAIN-SUFFIX,quadedge.com,Proxy +DOMAIN-SUFFIX,quitccp.net,Proxy +DOMAIN-SUFFIX,quitccp.org,Proxy +DOMAIN-SUFFIX,quora.com,Proxy +DOMAIN-SUFFIX,quran.com,Proxy +DOMAIN-SUFFIX,qusi8.net,Proxy +DOMAIN-SUFFIX,qvodzy.org,Proxy +DOMAIN-SUFFIX,qxbbs.org,Proxy +DOMAIN-SUFFIX,radicalparty.org,Proxy +DOMAIN-SUFFIX,radiko.jp,Proxy +DOMAIN-SUFFIX,radioaustralia.net.au,Proxy +DOMAIN-SUFFIX,radiohilight.net,Proxy +DOMAIN-SUFFIX,radiovaticana.org,Proxy +DOMAIN-SUFFIX,radiovncr.com,Proxy +DOMAIN-SUFFIX,ranyunfei.com,Proxy +DOMAIN-SUFFIX,rapbull.net,Proxy +DOMAIN-SUFFIX,rapidgator.net,Proxy +DOMAIN-SUFFIX,rapidshare8.com,Proxy +DOMAIN-SUFFIX,rapidsharedata.com,Proxy +DOMAIN-SUFFIX,rcinet.ca,Proxy +DOMAIN-SUFFIX,rconversation.blogs.com,Proxy +DOMAIN-SUFFIX,rd.io,Proxy +DOMAIN-SUFFIX,rdio.com,Proxy +DOMAIN-SUFFIX,read100.com,Proxy +DOMAIN-SUFFIX,readingtimes.com.tw,Proxy +DOMAIN-SUFFIX,readmoo.com,Proxy +DOMAIN-SUFFIX,realcourage.org,Proxy +DOMAIN-SUFFIX,realraptalk.com,Proxy +DOMAIN-SUFFIX,recaptcha.net,Proxy +DOMAIN-SUFFIX,recordhistory.org,Proxy +DOMAIN-SUFFIX,redtube.com,Proxy +DOMAIN-SUFFIX,referer.us,Proxy +DOMAIN-SUFFIX,reflectivecode.com,Proxy +DOMAIN-SUFFIX,rekrytointipalvelut.info,Proxy +DOMAIN-SUFFIX,relaxbbs.com,Proxy +DOMAIN-SUFFIX,releaseinternational.org,Proxy +DOMAIN-SUFFIX,religioustolerance.org,Proxy +DOMAIN-SUFFIX,renminbao.com,Proxy +DOMAIN-SUFFIX,renyurenquan.org,Proxy +DOMAIN-SUFFIX,research.jmsc.hku.hk,Proxy +DOMAIN-SUFFIX,ressim.net,Proxy +DOMAIN-SUFFIX,retweeteffect.com,Proxy +DOMAIN-SUFFIX,retweetist.com,Proxy +DOMAIN-SUFFIX,retweetrank.com,Proxy +DOMAIN-SUFFIX,reuters.com,Proxy +DOMAIN-SUFFIX,revleft.com,Proxy +DOMAIN-SUFFIX,revver.com,Proxy +DOMAIN-SUFFIX,rfa.org,Proxy +DOMAIN-SUFFIX,rfamobile.org,Proxy +DOMAIN-SUFFIX,rferl.org,Proxy +DOMAIN-SUFFIX,rfi.fr,Proxy +DOMAIN-SUFFIX,rfi.my,Proxy +DOMAIN-SUFFIX,rhcloud.com,Proxy +DOMAIN-SUFFIX,riitek.com,Proxy +DOMAIN-SUFFIX,riku.me,Proxy +DOMAIN-SUFFIX,rileyguide.com,Proxy +DOMAIN-SUFFIX,ritouki.jp,Proxy +DOMAIN-SUFFIX,rlwlw.com,Proxy +DOMAIN-SUFFIX,rmjdw.com,Proxy +DOMAIN-SUFFIX,rnw.nl,Proxy +DOMAIN-SUFFIX,robtex.com,Proxy +DOMAIN-SUFFIX,robustnessiskey.com,Proxy +DOMAIN-SUFFIX,rocmp.org,Proxy +DOMAIN-SUFFIX,rojo.com,Proxy +DOMAIN-SUFFIX,ronjoneswriter.com,Proxy +DOMAIN-SUFFIX,roodo.com,Proxy +DOMAIN-SUFFIX,rotten.com,Proxy +DOMAIN-SUFFIX,rsf.org,Proxy +DOMAIN-SUFFIX,rssmeme.com,Proxy +DOMAIN-SUFFIX,rthk.hk,Proxy +DOMAIN-SUFFIX,rthk.hk.edgesuite.net,Proxy +DOMAIN-SUFFIX,rthk.org.hk,Proxy +DOMAIN-SUFFIX,rti.org.tw,Proxy +DOMAIN-SUFFIX,ruanyifeng.com,Proxy +DOMAIN-SUFFIX,rushbee.com,Proxy +DOMAIN-SUFFIX,rutube.ru,Proxy +DOMAIN-SUFFIX,ruyiseek.com,Proxy +DOMAIN-SUFFIX,rxhj.net,Proxy +DOMAIN-SUFFIX,s-cute.com,Proxy +DOMAIN-SUFFIX,s-dragon.org,Proxy +DOMAIN-SUFFIX,s.xiaod.in,Proxy +DOMAIN-SUFFIX,s1heng.com,Proxy +DOMAIN-SUFFIX,s4miniarchive.com,Proxy +DOMAIN-SUFFIX,s8forum.com,Proxy +DOMAIN-SUFFIX,sa.hao123.com,Proxy +DOMAIN-SUFFIX,sacom.hk,Proxy +DOMAIN-SUFFIX,sadpanda.us,Proxy +DOMAIN-SUFFIX,saiq.me,Proxy +DOMAIN-SUFFIX,sakuralive.com,Proxy +DOMAIN-SUFFIX,salvation.org.hk,Proxy +DOMAIN-SUFFIX,samair.ru,Proxy +DOMAIN-SUFFIX,sambhota.org,Proxy +DOMAIN-SUFFIX,sammyjs.org,Proxy +DOMAIN-SUFFIX,samsoff.es,Proxy +DOMAIN-SUFFIX,sandnoble.com,Proxy +DOMAIN-SUFFIX,sankaizok.com,Proxy +DOMAIN-SUFFIX,sanmin.com.tw,Proxy +DOMAIN-SUFFIX,sapikachu.net,Proxy +DOMAIN-SUFFIX,savemedia.com,Proxy +DOMAIN-SUFFIX,savevid.com,Proxy +DOMAIN-SUFFIX,say2.info,Proxy +DOMAIN-SUFFIX,sbnation.com,Proxy +DOMAIN-SUFFIX,scalatest.org,Proxy +DOMAIN-SUFFIX,sciencemag.org,Proxy +DOMAIN-SUFFIX,scim.ag,Proxy +DOMAIN-SUFFIX,scmp.com,Proxy +DOMAIN-SUFFIX,scribd.com,Proxy +DOMAIN-SUFFIX,scriptspot.com,Proxy +DOMAIN-SUFFIX,seapuff.com,Proxy +DOMAIN-SUFFIX,secretgarden.no,Proxy +DOMAIN-SUFFIX,secure.wikimedia.org,Proxy +DOMAIN-SUFFIX,securitykiss.com,Proxy +DOMAIN-SUFFIX,seesmic.com,Proxy +DOMAIN-SUFFIX,seevpn.com,Proxy +DOMAIN-SUFFIX,seezone.net,Proxy +DOMAIN-SUFFIX,sejie.com,Proxy +DOMAIN-SUFFIX,sendoid.com,Proxy +DOMAIN-SUFFIX,sendspace.com,Proxy +DOMAIN-SUFFIX,sephora.com,Proxy +DOMAIN-SUFFIX,sesawe.net,Proxy +DOMAIN-SUFFIX,sesawe.org,Proxy +DOMAIN-SUFFIX,sethwklein.net,Proxy +DOMAIN-SUFFIX,sevenload.com,Proxy +DOMAIN-SUFFIX,sex-11.com,Proxy +DOMAIN-SUFFIX,sex.com,Proxy +DOMAIN-SUFFIX,sex3.com,Proxy +DOMAIN-SUFFIX,sex8.cc,Proxy +DOMAIN-SUFFIX,sexandsubmission.com,Proxy +DOMAIN-SUFFIX,sexhu.com,Proxy +DOMAIN-SUFFIX,sexhuang.com,Proxy +DOMAIN-SUFFIX,sexinsex.net,Proxy +DOMAIN-SUFFIX,sf.net,Proxy +DOMAIN-SUFFIX,sfileydy.com,Proxy +DOMAIN-SUFFIX,sftuk.org,Proxy +DOMAIN-SUFFIX,sha7.info,Proxy +DOMAIN-SUFFIX,shadow.ma,Proxy +DOMAIN-SUFFIX,shadowsocks.org,Proxy +DOMAIN-SUFFIX,shahamat-english.com,Proxy +DOMAIN-SUFFIX,shangfang.org,Proxy +DOMAIN-SUFFIX,shapeservices.com,Proxy +DOMAIN-SUFFIX,share.ovi.com,Proxy +DOMAIN-SUFFIX,share.skype.com,Proxy +DOMAIN-SUFFIX,share.youthwant.com.tw,Proxy +DOMAIN-SUFFIX,sharebee.com,Proxy +DOMAIN-SUFFIX,sharecool.org,Proxy +DOMAIN-SUFFIX,sharkdolphin.com,Proxy +DOMAIN-SUFFIX,sharpdaily.com.hk,Proxy +DOMAIN-SUFFIX,sharpdaily.hk,Proxy +DOMAIN-SUFFIX,shat-tibet.com,Proxy +DOMAIN-SUFFIX,shaunthesheep.com,Proxy +DOMAIN-SUFFIX,sheikyermami.com,Proxy +DOMAIN-SUFFIX,shellmix.com,Proxy +DOMAIN-SUFFIX,shenshou.org,Proxy +DOMAIN-SUFFIX,shenyun.com,Proxy +DOMAIN-SUFFIX,shenyunperformingarts.org,Proxy +DOMAIN-SUFFIX,shenzhoufilm.com,Proxy +DOMAIN-SUFFIX,shifeike.blog125.fc2blog.net,Proxy +DOMAIN-SUFFIX,shinychan.com,Proxy +DOMAIN-SUFFIX,shitaotv.org,Proxy +DOMAIN-SUFFIX,shixiao.org,Proxy +DOMAIN-SUFFIX,shizhao.org,Proxy +DOMAIN-SUFFIX,shkspr.mobi,Proxy +DOMAIN-SUFFIX,shodanhq.com,Proxy +DOMAIN-SUFFIX,shopping.com,Proxy +DOMAIN-SUFFIX,showbiz.omy.sg,Proxy +DOMAIN-SUFFIX,showtime.jp,Proxy +DOMAIN-SUFFIX,shutterstock.com,Proxy +DOMAIN-SUFFIX,shwchurch3.com,Proxy +DOMAIN-SUFFIX,si.wsj.net,Proxy +DOMAIN-SUFFIX,sidelinesnews.com,Proxy +DOMAIN-SUFFIX,sidelinessportseatery.com,Proxy +DOMAIN-SUFFIX,simplecd.org,Proxy +DOMAIN-SUFFIX,simpleproductivityblog.com,Proxy +DOMAIN-SUFFIX,sin1.g.adnxs.com,Proxy +DOMAIN-SUFFIX,singaporepools.com.sg,Proxy +DOMAIN-SUFFIX,singtao.com,Proxy +DOMAIN-SUFFIX,sino-monthly.com,Proxy +DOMAIN-SUFFIX,sinoants.com,Proxy +DOMAIN-SUFFIX,sinocast.com,Proxy +DOMAIN-SUFFIX,sinocism.com,Proxy +DOMAIN-SUFFIX,sinomontreal.ca,Proxy +DOMAIN-SUFFIX,sinonet.ca,Proxy +DOMAIN-SUFFIX,sinopitt.info,Proxy +DOMAIN-SUFFIX,sinoquebec.com,Proxy +DOMAIN-SUFFIX,sipml5.org,Proxy +DOMAIN-SUFFIX,sis.xxx,Proxy +DOMAIN-SUFFIX,sis001.com,Proxy +DOMAIN-SUFFIX,sis001.us,Proxy +DOMAIN-SUFFIX,site90.net,Proxy +DOMAIN-SUFFIX,sitebro.tw,Proxy +DOMAIN-SUFFIX,sitekreator.com,Proxy +DOMAIN-SUFFIX,siteks.uk.to,Proxy +DOMAIN-SUFFIX,sitemaps.org,Proxy +DOMAIN-SUFFIX,sitetag.us,Proxy +DOMAIN-SUFFIX,sjum.cn,Proxy +DOMAIN-SUFFIX,skimtube.com,Proxy +DOMAIN-SUFFIX,skybet.com,Proxy +DOMAIN-SUFFIX,skyhighpremium.com,Proxy +DOMAIN-SUFFIX,skype.com,Proxy +DOMAIN-SUFFIX,skyvegas.com,Proxy +DOMAIN-SUFFIX,slack-files.com,Proxy +DOMAIN-SUFFIX,slack-msgs.com,Proxy +DOMAIN-SUFFIX,slack.com,Proxy +DOMAIN-SUFFIX,slacker.com,Proxy +DOMAIN-SUFFIX,slashdot.org,Proxy +DOMAIN-SUFFIX,slavasoft.com,Proxy +DOMAIN-SUFFIX,slheng.com,Proxy +DOMAIN-SUFFIX,slickvpn.com,Proxy +DOMAIN-SUFFIX,slideshare.net,Proxy +DOMAIN-SUFFIX,slinkset.com,Proxy +DOMAIN-SUFFIX,slutload.com,Proxy +DOMAIN-SUFFIX,smhric.org,Proxy +DOMAIN-SUFFIX,snapchat.com,Proxy +DOMAIN-SUFFIX,snaptu.com,Proxy +DOMAIN-SUFFIX,sndcdn.com,Proxy +DOMAIN-SUFFIX,sneakme.net,Proxy +DOMAIN-SUFFIX,snooper.co.uk,Proxy +DOMAIN-SUFFIX,snowlionpub.com,Proxy +DOMAIN-SUFFIX,so-ga.net,Proxy +DOMAIN-SUFFIX,so-news.com,Proxy +DOMAIN-SUFFIX,sobees.com,Proxy +DOMAIN-SUFFIX,soc.mil,Proxy +DOMAIN-SUFFIX,socialwhale.com,Proxy +DOMAIN-SUFFIX,sockslist.net,Proxy +DOMAIN-SUFFIX,sod.co.jp,Proxy +DOMAIN-SUFFIX,softether-download.com,Proxy +DOMAIN-SUFFIX,softether.co.jp,Proxy +DOMAIN-SUFFIX,softether.org,Proxy +DOMAIN-SUFFIX,softwarebychuck.com,Proxy +DOMAIN-SUFFIX,softwaredownload.gitbooks.io,Proxy +DOMAIN-SUFFIX,sogclub.com,Proxy +DOMAIN-SUFFIX,sogrady.me,Proxy +DOMAIN-SUFFIX,soh.tw,Proxy +DOMAIN-SUFFIX,sohcradio.com,Proxy +DOMAIN-SUFFIX,sohfrance.org,Proxy +DOMAIN-SUFFIX,sokamonline.com,Proxy +DOMAIN-SUFFIX,solozorro.tk,Proxy +DOMAIN-SUFFIX,somee.com,Proxy +DOMAIN-SUFFIX,songjianjun.com,Proxy +DOMAIN-SUFFIX,sonidodelaesperanza.org,Proxy +DOMAIN-SUFFIX,sopcast.com,Proxy +DOMAIN-SUFFIX,sopcast.org,Proxy +DOMAIN-SUFFIX,sorting-algorithms.com,Proxy +DOMAIN-SUFFIX,soumo.info,Proxy +DOMAIN-SUFFIX,soundcloud.com,Proxy +DOMAIN-SUFFIX,soundofhope.kr,Proxy +DOMAIN-SUFFIX,soundofhope.org,Proxy +DOMAIN-SUFFIX,soup.io,Proxy +DOMAIN-SUFFIX,soupofmedia.com,Proxy +DOMAIN-SUFFIX,sourceforge.net,Proxy +DOMAIN-SUFFIX,southnews.com.tw,Proxy +DOMAIN-SUFFIX,sowers.org.hk,Proxy +DOMAIN-SUFFIX,space-scape.com,Proxy +DOMAIN-SUFFIX,spankbang.com,Proxy +DOMAIN-SUFFIX,spankwire.com,Proxy +DOMAIN-SUFFIX,spapps.co,Proxy +DOMAIN-SUFFIX,spb.com,Proxy +DOMAIN-SUFFIX,speakerdeck.com,Proxy +DOMAIN-SUFFIX,speckleapp.com,Proxy +DOMAIN-SUFFIX,speedpluss.org,Proxy +DOMAIN-SUFFIX,spencertipping.com,Proxy +DOMAIN-SUFFIX,spinejs.com,Proxy +DOMAIN-SUFFIX,sports.williamhill.com,Proxy +DOMAIN-SUFFIX,springboardplatform.com,Proxy +DOMAIN-SUFFIX,sproutcore.com,Proxy +DOMAIN-SUFFIX,squarespace.com,Proxy +DOMAIN-SUFFIX,srcf.ucam.org,Proxy +DOMAIN-SUFFIX,ssense.com,Proxy +DOMAIN-SUFFIX,ssh91.com,Proxy +DOMAIN-SUFFIX,sstatic.net,Proxy +DOMAIN-SUFFIX,stackfile.com,Proxy +DOMAIN-SUFFIX,stackoverflow.com,Proxy +DOMAIN-SUFFIX,standupfortibet.org,Proxy +DOMAIN-SUFFIX,stanford.edu,Proxy +DOMAIN-SUFFIX,starp2p.com,Proxy +DOMAIN-SUFFIX,startpage.com,Proxy +DOMAIN-SUFFIX,state168.com,Proxy +DOMAIN-SUFFIX,static.apple.nextmedia.com,Proxy +DOMAIN-SUFFIX,static.byhours.com,Proxy +DOMAIN-SUFFIX,static.digg.com,Proxy +DOMAIN-SUFFIX,staticflickr.com,Proxy +DOMAIN-SUFFIX,status.twhirl.org,Proxy +DOMAIN-SUFFIX,steampowered.com,Proxy +DOMAIN-SUFFIX,steel-storm.com,Proxy +DOMAIN-SUFFIX,stepmania.com,Proxy +DOMAIN-SUFFIX,sthoo.com,Proxy +DOMAIN-SUFFIX,stickam.com,Proxy +DOMAIN-SUFFIX,stickeraction.com,Proxy +DOMAIN-SUFFIX,stonegames.net,Proxy +DOMAIN-SUFFIX,stoneip.info,Proxy +DOMAIN-SUFFIX,stoptibetcrisis.net,Proxy +DOMAIN-SUFFIX,storagenewsletter.com,Proxy +DOMAIN-SUFFIX,storify.com,Proxy +DOMAIN-SUFFIX,stoweboyd.com,Proxy +DOMAIN-SUFFIX,streamingthe.net,Proxy +DOMAIN-SUFFIX,strongvpn.com,Proxy +DOMAIN-SUFFIX,student.tw,Proxy +DOMAIN-SUFFIX,studentsforafreetibet.org,Proxy +DOMAIN-SUFFIX,stuffimreading.com,Proxy +DOMAIN-SUFFIX,stuffimreading.net,Proxy +DOMAIN-SUFFIX,stumbleupon.com,Proxy +DOMAIN-SUFFIX,stupidbeauty.com,Proxy +DOMAIN-SUFFIX,stupidvideos.com,Proxy +DOMAIN-SUFFIX,subacme.rerouted.org,Proxy +DOMAIN-SUFFIX,sublimetext.com,Proxy +DOMAIN-SUFFIX,sufeng.org,Proxy +DOMAIN-SUFFIX,sugarsync.com,Proxy +DOMAIN-SUFFIX,summify.com,Proxy +DOMAIN-SUFFIX,sun1911.com,Proxy +DOMAIN-SUFFIX,sunporno.com,Proxy +DOMAIN-SUFFIX,suoluo.org,Proxy +DOMAIN-SUFFIX,supertweet.net,Proxy +DOMAIN-SUFFIX,surfeasy.com.au,Proxy +DOMAIN-SUFFIX,surrenderat20.net,Proxy +DOMAIN-SUFFIX,suyangg.com,Proxy +DOMAIN-SUFFIX,svwind.com,Proxy +DOMAIN-SUFFIX,sweux.com,Proxy +DOMAIN-SUFFIX,swift-tools.net,Proxy +DOMAIN-SUFFIX,sydneytoday.com,Proxy +DOMAIN-SUFFIX,sylfoundation.org,Proxy +DOMAIN-SUFFIX,symauth.com,Proxy +DOMAIN-SUFFIX,symcb.com,Proxy +DOMAIN-SUFFIX,syncback.com,Proxy +DOMAIN-SUFFIX,sysadmin1138.net,Proxy +DOMAIN-SUFFIX,sysresccd.org,Proxy +DOMAIN-SUFFIX,sytes.net,Proxy +DOMAIN-SUFFIX,szbbs.net,Proxy +DOMAIN-SUFFIX,szetowah.org.hk,Proxy +DOMAIN-SUFFIX,t.co,Proxy +DOMAIN-SUFFIX,t.huhaitai.com,Proxy +DOMAIN-SUFFIX,t.kun.im,Proxy +DOMAIN-SUFFIX,t.neolee.cn,Proxy +DOMAIN-SUFFIX,t.orzdream.com,Proxy +DOMAIN-SUFFIX,t35.com,Proxy +DOMAIN-SUFFIX,t66y.com,Proxy +DOMAIN-SUFFIX,t88.ca,Proxy +DOMAIN-SUFFIX,taa-usa.org,Proxy +DOMAIN-SUFFIX,tablesgenerator.com,Proxy +DOMAIN-SUFFIX,tabtter.jp,Proxy +DOMAIN-SUFFIX,tacem.org,Proxy +DOMAIN-SUFFIX,tafaward.com,Proxy +DOMAIN-SUFFIX,tagwalk.com,Proxy +DOMAIN-SUFFIX,tagxedo.com,Proxy +DOMAIN-SUFFIX,tahr.org.tw,Proxy +DOMAIN-SUFFIX,taipei.gov.tw,Proxy +DOMAIN-SUFFIX,taipeisociety.org,Proxy +DOMAIN-SUFFIX,taiwan-sex.com,Proxy +DOMAIN-SUFFIX,taiwandaily.net,Proxy +DOMAIN-SUFFIX,taiwankiss.com,Proxy + +DOMAIN-SUFFIX,taiwannews.com.tw,Proxy +DOMAIN-SUFFIX,taiwanonline.cc,Proxy +DOMAIN-SUFFIX,taiwantp.net,Proxy +DOMAIN-SUFFIX,taiwantt.org.tw,Proxy +DOMAIN-SUFFIX,taiwanus.net,Proxy +DOMAIN-SUFFIX,taiwanyes.com,Proxy +DOMAIN-SUFFIX,taiwanyes.ning.com,Proxy +DOMAIN-SUFFIX,talk853.com,Proxy +DOMAIN-SUFFIX,talkboxapp.com,Proxy +DOMAIN-SUFFIX,tamiaode.tk,Proxy +DOMAIN-SUFFIX,tanc.org,Proxy +DOMAIN-SUFFIX,tangben.com,Proxy +DOMAIN-SUFFIX,taolun.info,Proxy +DOMAIN-SUFFIX,tap11.com,Proxy +DOMAIN-SUFFIX,tapbots.com,Proxy +DOMAIN-SUFFIX,target.com,Proxy +DOMAIN-SUFFIX,tarr.uspto.gov,Proxy +DOMAIN-SUFFIX,taup.net,Proxy +DOMAIN-SUFFIX,taup.org.tw,Proxy +DOMAIN-SUFFIX,taweet.com,Proxy +DOMAIN-SUFFIX,tbpic.info,Proxy +DOMAIN-SUFFIX,tbsec.org,Proxy +DOMAIN-SUFFIX,tbsn.org,Proxy +DOMAIN-SUFFIX,tbsseattle.org,Proxy +DOMAIN-SUFFIX,tccwonline.org,Proxy +DOMAIN-SUFFIX,tcewf.org,Proxy +DOMAIN-SUFFIX,tchrd.org,Proxy +DOMAIN-SUFFIX,tcno.net,Proxy +DOMAIN-SUFFIX,tdesktop.com,Proxy +DOMAIN-SUFFIX,teamseesmic.com,Proxy +DOMAIN-SUFFIX,teashark.com,Proxy +DOMAIN-SUFFIX,tech2.in.com,Proxy +DOMAIN-SUFFIX,techcrunch.com,Proxy +DOMAIN-SUFFIX,techlifeweb.com,Proxy +DOMAIN-SUFFIX,techparaiso.com,Proxy +DOMAIN-SUFFIX,teck.in,Proxy +DOMAIN-SUFFIX,teensinasia.com,Proxy +DOMAIN-SUFFIX,telecomspace.com,Proxy +DOMAIN-SUFFIX,telegraph.co.uk,Proxy +DOMAIN-SUFFIX,tenacy.com,Proxy +DOMAIN-SUFFIX,tetronics.com,Proxy +DOMAIN-SUFFIX,tew.org,Proxy +DOMAIN-SUFFIX,th.hao123.com,Proxy +DOMAIN-SUFFIX,the-sun.on.cc,Proxy +DOMAIN-SUFFIX,theampfactory.com,Proxy +DOMAIN-SUFFIX,theappleblog.com,Proxy +DOMAIN-SUFFIX,theatrum-belli.com,Proxy +DOMAIN-SUFFIX,thebcomplex.com,Proxy +DOMAIN-SUFFIX,theblemish.com,Proxy +DOMAIN-SUFFIX,thebobs.com,Proxy +DOMAIN-SUFFIX,thebodyshop-usa.com,Proxy +DOMAIN-SUFFIX,thecoveteur.com,Proxy +DOMAIN-SUFFIX,thedailywh.at,Proxy +DOMAIN-SUFFIX,thedieline.com,Proxy +DOMAIN-SUFFIX,thediplomat.com,Proxy +DOMAIN-SUFFIX,thedw.us,Proxy +DOMAIN-SUFFIX,thefourtheye.in,Proxy +DOMAIN-SUFFIX,thefrontier.hk,Proxy +DOMAIN-SUFFIX,thegatesnotes.com,Proxy +DOMAIN-SUFFIX,thegioitinhoc.vn,Proxy +DOMAIN-SUFFIX,theguardian.co,Proxy +DOMAIN-SUFFIX,theguardian.com,Proxy +DOMAIN-SUFFIX,thehots.info,Proxy +DOMAIN-SUFFIX,thehousenews.com,Proxy +DOMAIN-SUFFIX,thehun.net,Proxy +DOMAIN-SUFFIX,thehungrydudes.com,Proxy +DOMAIN-SUFFIX,theinitium.com,Proxy +DOMAIN-SUFFIX,theinternetwishlist.com,Proxy +DOMAIN-SUFFIX,thelifeyoucansave.com,Proxy +DOMAIN-SUFFIX,thelius.org,Proxy +DOMAIN-SUFFIX,thenewslens.com,Proxy +DOMAIN-SUFFIX,thepiratebay.org,Proxy +DOMAIN-SUFFIX,thepiratebay.se,Proxy +DOMAIN-SUFFIX,theqii.info,Proxy +DOMAIN-SUFFIX,thereallove.kr,Proxy +DOMAIN-SUFFIX,thesartorialist.com,Proxy +DOMAIN-SUFFIX,thesnippetapp.com,Proxy +DOMAIN-SUFFIX,thespeeder.com,Proxy +DOMAIN-SUFFIX,thestandnews.com,Proxy +DOMAIN-SUFFIX,thetibetconnection.org,Proxy +DOMAIN-SUFFIX,thetibetmuseum.org,Proxy +DOMAIN-SUFFIX,thetibetpost.com,Proxy +DOMAIN-SUFFIX,thetrotskymovie.com,Proxy +DOMAIN-SUFFIX,thevivekspot.com,Proxy +DOMAIN-SUFFIX,thewgo.org,Proxy +DOMAIN-SUFFIX,thinkingtaiwan.com,Proxy +DOMAIN-SUFFIX,thisav.com,Proxy +DOMAIN-SUFFIX,thisiswhyyouarefat.com,Proxy +DOMAIN-SUFFIX,thkphoto.com,Proxy +DOMAIN-SUFFIX,thomasbernhard.org,Proxy +DOMAIN-SUFFIX,threatchaos.com,Proxy +DOMAIN-SUFFIX,throughnightsfire.com,Proxy +DOMAIN-SUFFIX,thumbr.io,Proxy +DOMAIN-SUFFIX,thumbzilla.com,Proxy +DOMAIN-SUFFIX,thywords.com,Proxy +DOMAIN-SUFFIX,tiananmenmother.org,Proxy +DOMAIN-SUFFIX,tiananmenuniv.com,Proxy +DOMAIN-SUFFIX,tiananmenuniv.net,Proxy +DOMAIN-SUFFIX,tiandixing.org,Proxy +DOMAIN-SUFFIX,tianhuayuan.com,Proxy +DOMAIN-SUFFIX,tianlawoffice.com,Proxy +DOMAIN-SUFFIX,tiantibooks.org,Proxy +DOMAIN-SUFFIX,tianzhu.org,Proxy +DOMAIN-SUFFIX,tidyread.com,Proxy +DOMAIN-SUFFIX,tiffanyarment.com,Proxy +DOMAIN-SUFFIX,time.com,Proxy +DOMAIN-SUFFIX,times.hinet.net,Proxy +DOMAIN-SUFFIX,tinychat.com,Proxy +DOMAIN-SUFFIX,tinypaste.com,Proxy +DOMAIN-SUFFIX,tistory.com,Proxy +DOMAIN-SUFFIX,tjholowaychuk.com,Proxy +DOMAIN-SUFFIX,tkcs-collins.com,Proxy +DOMAIN-SUFFIX,tkforum.tk,Proxy +DOMAIN-SUFFIX,tl.gd,Proxy +DOMAIN-SUFFIX,tldp.org,Proxy +DOMAIN-SUFFIX,tmagazine.com,Proxy +DOMAIN-SUFFIX,tmi.me,Proxy +DOMAIN-SUFFIX,tnaflix.com,Proxy +DOMAIN-SUFFIX,tnp.org,Proxy +DOMAIN-SUFFIX,togetter.com,Proxy +DOMAIN-SUFFIX,tokyo-247.com,Proxy +DOMAIN-SUFFIX,tokyo-hot.com,Proxy +DOMAIN-SUFFIX,tokyocn.com,Proxy +DOMAIN-SUFFIX,tomayko.com,Proxy +DOMAIN-SUFFIX,tomsc.com,Proxy +DOMAIN-SUFFIX,tono-oka.jp,Proxy +DOMAIN-SUFFIX,tonyyan.net,Proxy +DOMAIN-SUFFIX,toodoc.com,Proxy +DOMAIN-SUFFIX,toonel.net,Proxy +DOMAIN-SUFFIX,topic.youthwant.com.tw,Proxy +DOMAIN-SUFFIX,topnews.in,Proxy +DOMAIN-SUFFIX,topshare.us,Proxy +DOMAIN-SUFFIX,topshareware.com,Proxy +DOMAIN-SUFFIX,topstyle4.com,Proxy +DOMAIN-SUFFIX,topsy.com,Proxy +DOMAIN-SUFFIX,toptip.ca,Proxy +DOMAIN-SUFFIX,tor.blingblingsquad.net,Proxy +DOMAIN-SUFFIX,tor.updatestar.com,Proxy +DOMAIN-SUFFIX,tora.to,Proxy +DOMAIN-SUFFIX,torproject.org,Proxy +DOMAIN-SUFFIX,torrentcrazy.com,Proxy +DOMAIN-SUFFIX,torrentproject.se,Proxy +DOMAIN-SUFFIX,torrentz.eu,Proxy +DOMAIN-SUFFIX,torvpn.com,Proxy +DOMAIN-SUFFIX,tosh.comedycentral.com,Proxy +DOMAIN-SUFFIX,touch99.com,Proxy +DOMAIN-SUFFIX,toutfr.com,Proxy +DOMAIN-SUFFIX,tpi.org.tw,Proxy +DOMAIN-SUFFIX,trans.wenweipo.com,Proxy +DOMAIN-SUFFIX,transgressionism.org,Proxy +DOMAIN-SUFFIX,transparency.org,Proxy +DOMAIN-SUFFIX,travelinlocal.com,Proxy +DOMAIN-SUFFIX,treemall.com.tw,Proxy +DOMAIN-SUFFIX,trendsmap.com,Proxy +DOMAIN-SUFFIX,trialofccp.org,Proxy +DOMAIN-SUFFIX,tripod.com,Proxy +DOMAIN-SUFFIX,trouw.nl,Proxy +DOMAIN-SUFFIX,trt.net.tr,Proxy +DOMAIN-SUFFIX,trtc.com.tw,Proxy +DOMAIN-SUFFIX,trulyergonomic.com,Proxy +DOMAIN-SUFFIX,trustedbi.com,Proxy +DOMAIN-SUFFIX,truth101.co.tv,Proxy +DOMAIN-SUFFIX,truthcn.com,Proxy +DOMAIN-SUFFIX,truveo.com,Proxy +DOMAIN-SUFFIX,tsctv.net,Proxy +DOMAIN-SUFFIX,tsdr.uspto.gov,Proxy +DOMAIN-SUFFIX,tsemtulku.com,Proxy +DOMAIN-SUFFIX,tsquare.tv,Proxy +DOMAIN-SUFFIX,tsu.org.tw,Proxy +DOMAIN-SUFFIX,tsunagarumon.com,Proxy +DOMAIN-SUFFIX,tsuru-bird.net,Proxy +DOMAIN-SUFFIX,tt-rss.org,Proxy +DOMAIN-SUFFIX,tt1069.com,Proxy +DOMAIN-SUFFIX,tttan.com,Proxy +DOMAIN-SUFFIX,tu8964.com,Proxy +DOMAIN-SUFFIX,tuanzt.com,Proxy +DOMAIN-SUFFIX,tube.com,Proxy +DOMAIN-SUFFIX,tube8.com,Proxy +DOMAIN-SUFFIX,tube911.com,Proxy +DOMAIN-SUFFIX,tubecao.com,Proxy +DOMAIN-SUFFIX,tubewolf.com,Proxy +DOMAIN-SUFFIX,tui.orzdream.com,Proxy +DOMAIN-SUFFIX,tuidang.net,Proxy +DOMAIN-SUFFIX,tuidang.org,Proxy +DOMAIN-SUFFIX,tumblr.awflasher.com,Proxy +DOMAIN-SUFFIX,tumblr.com,Proxy +DOMAIN-SUFFIX,tumblweed.org,Proxy +DOMAIN-SUFFIX,tumutanzi.com,Proxy +DOMAIN-SUFFIX,tunein.com,Proxy +DOMAIN-SUFFIX,tunnelbear.com,Proxy +DOMAIN-SUFFIX,tuo8.hk,Proxy +DOMAIN-SUFFIX,tuo8.org,Proxy +DOMAIN-SUFFIX,turbobit.net,Proxy +DOMAIN-SUFFIX,turningtorso.com,Proxy +DOMAIN-SUFFIX,turntable.fm,Proxy +DOMAIN-SUFFIX,tuxtraining.com,Proxy +DOMAIN-SUFFIX,tuzaijidi.com,Proxy +DOMAIN-SUFFIX,tv-intros.com,Proxy +DOMAIN-SUFFIX,tv.com,Proxy +DOMAIN-SUFFIX,tv.on.cc,Proxy +DOMAIN-SUFFIX,tvants.com,Proxy +DOMAIN-SUFFIX,tvb.com,Proxy +DOMAIN-SUFFIX,tvboxnow.com,Proxy +DOMAIN-SUFFIX,tvider.com,Proxy +DOMAIN-SUFFIX,tvunetworks.com,Proxy +DOMAIN-SUFFIX,tw-npo.org,Proxy +DOMAIN-SUFFIX,tw.gigacircle.com,Proxy +DOMAIN-SUFFIX,tw.hao123.com,Proxy +DOMAIN-SUFFIX,tw.jiepang.com,Proxy +DOMAIN-SUFFIX,tw.knowledge.yahoo.com,Proxy +DOMAIN-SUFFIX,tw.myblog.yahoo.com,Proxy +DOMAIN-SUFFIX,tw.news.yahoo.com,Proxy +DOMAIN-SUFFIX,tw.streetvoice.com,Proxy +DOMAIN-SUFFIX,tw.voa.mobi,Proxy +DOMAIN-SUFFIX,tw.yahoo.com,Proxy +DOMAIN-SUFFIX,tw01.org,Proxy +DOMAIN-SUFFIX,twa.sh,Proxy +DOMAIN-SUFFIX,twapperkeeper.com,Proxy +DOMAIN-SUFFIX,twaud.io,Proxy +DOMAIN-SUFFIX,twbbs.net.tw,Proxy +DOMAIN-SUFFIX,twbbs.org,Proxy +DOMAIN-SUFFIX,twbbs.tw,Proxy +DOMAIN-SUFFIX,twblogger.com,Proxy +DOMAIN-SUFFIX,tweepguide.com,Proxy +DOMAIN-SUFFIX,tweeplike.me,Proxy +DOMAIN-SUFFIX,tweepmag.com,Proxy +DOMAIN-SUFFIX,tweepml.org,Proxy +DOMAIN-SUFFIX,tweetbackup.com,Proxy +DOMAIN-SUFFIX,tweetboard.com,Proxy +DOMAIN-SUFFIX,tweetboner.biz,Proxy +DOMAIN-SUFFIX,tweetdeck.com,Proxy +DOMAIN-SUFFIX,tweete.net,Proxy +DOMAIN-SUFFIX,tweetedtimes.com,Proxy +DOMAIN-SUFFIX,tweetmeme.com,Proxy +DOMAIN-SUFFIX,tweetmylast.fm,Proxy +DOMAIN-SUFFIX,tweetphoto.com,Proxy +DOMAIN-SUFFIX,tweetrans.com,Proxy +DOMAIN-SUFFIX,tweetree.com,Proxy +DOMAIN-SUFFIX,tweets.seraph.me,Proxy +DOMAIN-SUFFIX,tweetwally.com,Proxy +DOMAIN-SUFFIX,tweetymail.com,Proxy +DOMAIN-SUFFIX,twerkingbutt.com,Proxy +DOMAIN-SUFFIX,twftp.org,Proxy +DOMAIN-SUFFIX,twibase.com,Proxy +DOMAIN-SUFFIX,twibble.de,Proxy +DOMAIN-SUFFIX,twibbon.com,Proxy +DOMAIN-SUFFIX,twibs.com,Proxy +DOMAIN-SUFFIX,twicsy.com,Proxy +DOMAIN-SUFFIX,twifan.com,Proxy +DOMAIN-SUFFIX,twiffo.com,Proxy +DOMAIN-SUFFIX,twiggit.org,Proxy +DOMAIN-SUFFIX,twillo.com,Proxy +DOMAIN-SUFFIX,twilog.org,Proxy +DOMAIN-SUFFIX,twimbow.com,Proxy +DOMAIN-SUFFIX,twindexx.com,Proxy +DOMAIN-SUFFIX,twip.me,Proxy +DOMAIN-SUFFIX,twipple.jp,Proxy +DOMAIN-SUFFIX,twishort.com,Proxy +DOMAIN-SUFFIX,twistar.cc,Proxy +DOMAIN-SUFFIX,twister.net.co,Proxy +DOMAIN-SUFFIX,twisterio.com,Proxy +DOMAIN-SUFFIX,twisternow.com,Proxy +DOMAIN-SUFFIX,twistory.net,Proxy +DOMAIN-SUFFIX,twit2d.com,Proxy +DOMAIN-SUFFIX,twitbrowser.net,Proxy +DOMAIN-SUFFIX,twitcause.com,Proxy +DOMAIN-SUFFIX,twitgether.com,Proxy +DOMAIN-SUFFIX,twitgoo.com,Proxy +DOMAIN-SUFFIX,twitiq.com,Proxy +DOMAIN-SUFFIX,twitlonger.com,Proxy +DOMAIN-SUFFIX,twitoaster.com,Proxy +DOMAIN-SUFFIX,twitonmsn.com,Proxy +DOMAIN-SUFFIX,twitpic.com,Proxy +DOMAIN-SUFFIX,twitreferral.com,Proxy +DOMAIN-SUFFIX,twitstat.com,Proxy +DOMAIN-SUFFIX,twittbot.net,Proxy +DOMAIN-SUFFIX,twitturk.com,Proxy +DOMAIN-SUFFIX,twitturly.com,Proxy +DOMAIN-SUFFIX,twitvid.com,Proxy +DOMAIN-SUFFIX,twitzap.com,Proxy +DOMAIN-SUFFIX,twiyia.com,Proxy +DOMAIN-SUFFIX,twreg.info,Proxy +DOMAIN-SUFFIX,twstar.net,Proxy +DOMAIN-SUFFIX,twt.fm,Proxy +DOMAIN-SUFFIX,twt.tl,Proxy +DOMAIN-SUFFIX,twtkr.com,Proxy +DOMAIN-SUFFIX,twtr2src.ogaoga.org,Proxy +DOMAIN-SUFFIX,twtrland.com,Proxy +DOMAIN-SUFFIX,twttr.com,Proxy +DOMAIN-SUFFIX,twurl.nl,Proxy +DOMAIN-SUFFIX,twyac.org,Proxy +DOMAIN-SUFFIX,tycool.com,Proxy +DOMAIN-SUFFIX,tynsoe.org,Proxy +DOMAIN-SUFFIX,typekit.net,Proxy +DOMAIN-SUFFIX,typepad.com,Proxy +DOMAIN-SUFFIX,tzangms.com,Proxy +DOMAIN-SUFFIX,ub0.cc,Proxy +DOMAIN-SUFFIX,uberproxy.net,Proxy +DOMAIN-SUFFIX,ubnt.com,Proxy +DOMAIN-SUFFIX,ubuntu.com,Proxy +DOMAIN-SUFFIX,ucdc1998.org,Proxy +DOMAIN-SUFFIX,uderzo.it,Proxy +DOMAIN-SUFFIX,udn.com,Proxy +DOMAIN-SUFFIX,uforadio.com.tw,Proxy +DOMAIN-SUFFIX,ufreevpn.com,Proxy +DOMAIN-SUFFIX,ugo.com,Proxy +DOMAIN-SUFFIX,uhrp.org,Proxy +DOMAIN-SUFFIX,uighur.nl,Proxy +DOMAIN-SUFFIX,uighurbiz.net,Proxy +DOMAIN-SUFFIX,ukchinese.com,Proxy +DOMAIN-SUFFIX,ukliferadio.co.uk,Proxy +DOMAIN-SUFFIX,ulike.net,Proxy +DOMAIN-SUFFIX,ultravpn.fr,Proxy +DOMAIN-SUFFIX,ultraxs.com,Proxy +DOMAIN-SUFFIX,umich.edu,Proxy +DOMAIN-SUFFIX,unblock.cn.com,Proxy +DOMAIN-SUFFIX,unblocksit.es,Proxy +DOMAIN-SUFFIX,unholyknight.com,Proxy +DOMAIN-SUFFIX,uni-due.de,Proxy +DOMAIN-SUFFIX,uni.cc,Proxy +DOMAIN-SUFFIX,unicode.org,Proxy +DOMAIN-SUFFIX,unification.org.tw,Proxy +DOMAIN-SUFFIX,uninstallapp.org,Proxy +DOMAIN-SUFFIX,uniteddaily.com.my,Proxy +DOMAIN-SUFFIX,unix100.com,Proxy +DOMAIN-SUFFIX,unknownspace.org,Proxy +DOMAIN-SUFFIX,unpo.org,Proxy +DOMAIN-SUFFIX,uocn.org,Proxy +DOMAIN-SUFFIX,upcoming.yahoo.com,Proxy +DOMAIN-SUFFIX,upholdjustice.org,Proxy +DOMAIN-SUFFIX,upload.wikimedia.org,Proxy +DOMAIN-SUFFIX,upload4u.info,Proxy +DOMAIN-SUFFIX,uploaded.net,Proxy +DOMAIN-SUFFIX,uploaded.to,Proxy +DOMAIN-SUFFIX,uploadstation.com,Proxy +DOMAIN-SUFFIX,uproxy.org,Proxy +DOMAIN-SUFFIX,upwill.org,Proxy +DOMAIN-SUFFIX,urbanoutfitters.com,Proxy +DOMAIN-SUFFIX,urlborg.com,Proxy +DOMAIN-SUFFIX,urlparser.com,Proxy +DOMAIN-SUFFIX,us.to,Proxy +DOMAIN-SUFFIX,usacn.com,Proxy +DOMAIN-SUFFIX,users.skynet.be,Proxy +DOMAIN-SUFFIX,usfk.mil,Proxy +DOMAIN-SUFFIX,usinfo.state.gov,Proxy +DOMAIN-SUFFIX,usma.edu,Proxy +DOMAIN-SUFFIX,usmc.mil,Proxy +DOMAIN-SUFFIX,usmgtcg.ning.com,Proxy +DOMAIN-SUFFIX,ustream.tv,Proxy +DOMAIN-SUFFIX,ustwrap.info,Proxy +DOMAIN-SUFFIX,usus.cc,Proxy +DOMAIN-SUFFIX,uushare.com,Proxy +DOMAIN-SUFFIX,uwants.com,Proxy +DOMAIN-SUFFIX,uwants.net,Proxy +DOMAIN-SUFFIX,uyghur-j.org,Proxy +DOMAIN-SUFFIX,uyghuramerican.org,Proxy +DOMAIN-SUFFIX,uyghurcanadiansociety.org,Proxy +DOMAIN-SUFFIX,uyghurcongress.org,Proxy +DOMAIN-SUFFIX,uyghurensemble.co.uk,Proxy +DOMAIN-SUFFIX,uyghurpen.org,Proxy +DOMAIN-SUFFIX,uyghurpress.com,Proxy +DOMAIN-SUFFIX,uygur.fc2web.com,Proxy +DOMAIN-SUFFIX,uygur.org,Proxy +DOMAIN-SUFFIX,uymaarip.com,Proxy +DOMAIN-SUFFIX,v-state.org,Proxy +DOMAIN-SUFFIX,v70.us,Proxy +DOMAIN-SUFFIX,v7976888.info,Proxy +DOMAIN-SUFFIX,vaayoo.com,Proxy +DOMAIN-SUFFIX,value-domain.com,Proxy +DOMAIN-SUFFIX,van698.com,Proxy +DOMAIN-SUFFIX,vanemu.cn,Proxy +DOMAIN-SUFFIX,vanilla-jp.com,Proxy +DOMAIN-SUFFIX,vansky.com,Proxy +DOMAIN-SUFFIX,vapurl.com,Proxy +DOMAIN-SUFFIX,varnish-cache.org,Proxy +DOMAIN-SUFFIX,vatn.org,Proxy +DOMAIN-SUFFIX,vcf-online.org,Proxy +DOMAIN-SUFFIX,vcfbuilder.org,Proxy +DOMAIN-SUFFIX,vds.rightster.com,Proxy +DOMAIN-SUFFIX,veempiire.com,Proxy +DOMAIN-SUFFIX,vegorpedersen.com,Proxy +DOMAIN-SUFFIX,velkaepocha.sk,Proxy +DOMAIN-SUFFIX,venbbs.com,Proxy +DOMAIN-SUFFIX,ventureswell.com,Proxy +DOMAIN-SUFFIX,veoh.com,Proxy +DOMAIN-SUFFIX,verizon.net,Proxy +DOMAIN-SUFFIX,verybs.com,Proxy +DOMAIN-SUFFIX,vevo.com,Proxy +DOMAIN-SUFFIX,vft.com.tw,Proxy +DOMAIN-SUFFIX,viber.com,Proxy +DOMAIN-SUFFIX,video.aol.ca,Proxy +DOMAIN-SUFFIX,video.aol.co.uk,Proxy +DOMAIN-SUFFIX,video.aol.com,Proxy +DOMAIN-SUFFIX,video.ap.org,Proxy +DOMAIN-SUFFIX,video.fdbox.com,Proxy +DOMAIN-SUFFIX,video.foxbusiness.com,Proxy +DOMAIN-SUFFIX,video.tiscali.it,Proxy +DOMAIN-SUFFIX,video.yahoo.com,Proxy +DOMAIN-SUFFIX,videobam.com,Proxy +DOMAIN-SUFFIX,videomega.tv,Proxy +DOMAIN-SUFFIX,videomo.com,Proxy +DOMAIN-SUFFIX,videopediaworld.com,Proxy +DOMAIN-SUFFIX,vidoemo.com,Proxy +DOMAIN-SUFFIX,views.fm,Proxy +DOMAIN-SUFFIX,viki.com,Proxy +DOMAIN-SUFFIX,vimgolf.com,Proxy +DOMAIN-SUFFIX,vimperator.org,Proxy +DOMAIN-SUFFIX,vincnd.com,Proxy +DOMAIN-SUFFIX,vine.co,Proxy +DOMAIN-SUFFIX,vineapp.com,Proxy +DOMAIN-SUFFIX,vinniev.com,Proxy +DOMAIN-SUFFIX,vivatube.com,Proxy +DOMAIN-SUFFIX,vjmedia.com.hk,Proxy +DOMAIN-SUFFIX,vllcs.org,Proxy +DOMAIN-SUFFIX,vlog.xuite.net,Proxy +DOMAIN-SUFFIX,vmixcore.com,Proxy +DOMAIN-SUFFIX,vn.hao123.com,Proxy +DOMAIN-SUFFIX,vocn.tv,Proxy +DOMAIN-SUFFIX,voicetube.tw,Proxy +DOMAIN-SUFFIX,vot.org,Proxy +DOMAIN-SUFFIX,vox-cdn.com,Proxy +DOMAIN-SUFFIX,voy.com,Proxy +DOMAIN-SUFFIX,vporn.com,Proxy +DOMAIN-SUFFIX,vtunnel.com,Proxy +DOMAIN-SUFFIX,w.idaiwan.com,Proxy +DOMAIN-SUFFIX,w.org,Proxy +DOMAIN-SUFFIX,w3schools.com,Proxy +DOMAIN-SUFFIX,waffle1999.com,Proxy +DOMAIN-SUFFIX,wahas.com,Proxy +DOMAIN-SUFFIX,waigaobu.com,Proxy +DOMAIN-SUFFIX,waikeung.org,Proxy +DOMAIN-SUFFIX,waiwaier.com,Proxy +DOMAIN-SUFFIX,wallornot.org,Proxy +DOMAIN-SUFFIX,wallpapercasa.com,Proxy +DOMAIN-SUFFIX,wan-press.org,Proxy +DOMAIN-SUFFIX,wanderinghorse.net,Proxy +DOMAIN-SUFFIX,wangafu.net,Proxy +DOMAIN-SUFFIX,wangjinbo.org,Proxy +DOMAIN-SUFFIX,wanglixiong.com,Proxy +DOMAIN-SUFFIX,wangruoshui.net,Proxy +DOMAIN-SUFFIX,wangruowang.org,Proxy +DOMAIN-SUFFIX,want-daily.com,Proxy +DOMAIN-SUFFIX,wapedia.mobi,Proxy +DOMAIN-SUFFIX,waselpro.com,Proxy +DOMAIN-SUFFIX,washeng.net,Proxy +DOMAIN-SUFFIX,watchmygf.net,Proxy +DOMAIN-SUFFIX,wattpad.com,Proxy +DOMAIN-SUFFIX,wav.tv,Proxy +DOMAIN-SUFFIX,wdf5.com,Proxy +DOMAIN-SUFFIX,wearn.com,Proxy +DOMAIN-SUFFIX,web2project.net,Proxy +DOMAIN-SUFFIX,webbang.net,Proxy +DOMAIN-SUFFIX,webfee.tk,Proxy +DOMAIN-SUFFIX,weblagu.com,Proxy +DOMAIN-SUFFIX,webmproject.org,Proxy +DOMAIN-SUFFIX,webrtc.org,Proxy +DOMAIN-SUFFIX,webs-tv.net,Proxy +DOMAIN-SUFFIX,webshots.com,Proxy +DOMAIN-SUFFIX,websitepulse.com,Proxy +DOMAIN-SUFFIX,websnapr.com,Proxy +DOMAIN-SUFFIX,webworkerdaily.com,Proxy +DOMAIN-SUFFIX,weeewooo.net,Proxy +DOMAIN-SUFFIX,weekmag.info,Proxy +DOMAIN-SUFFIX,wefightcensorship.org,Proxy +DOMAIN-SUFFIX,wefong.com,Proxy +DOMAIN-SUFFIX,weiboleak.com,Proxy +DOMAIN-SUFFIX,weigegebyc.dreamhosters.com,Proxy +DOMAIN-SUFFIX,weijingsheng.org,Proxy +DOMAIN-SUFFIX,weiming.info,Proxy +DOMAIN-SUFFIX,weiquanwang.org,Proxy +DOMAIN-SUFFIX,weisuo.ws,Proxy +DOMAIN-SUFFIX,wellplacedpixels.com,Proxy +DOMAIN-SUFFIX,wemigrate.org,Proxy +DOMAIN-SUFFIX,wengewang.com,Proxy +DOMAIN-SUFFIX,wengewang.org,Proxy +DOMAIN-SUFFIX,wenhui.ch,Proxy +DOMAIN-SUFFIX,wenku.com,Proxy +DOMAIN-SUFFIX,wenxuecity.com,Proxy +DOMAIN-SUFFIX,wenyunchao.com,Proxy +DOMAIN-SUFFIX,wepn.info,Proxy +DOMAIN-SUFFIX,westca.com,Proxy +DOMAIN-SUFFIX,westernshugdensociety.org,Proxy +DOMAIN-SUFFIX,westernwolves.com,Proxy +DOMAIN-SUFFIX,westkit.net,Proxy +DOMAIN-SUFFIX,westpoint.edu,Proxy +DOMAIN-SUFFIX,wet123.com,Proxy +DOMAIN-SUFFIX,wetplace.com,Proxy +DOMAIN-SUFFIX,wetpussygames.com,Proxy +DOMAIN-SUFFIX,wexiaobo.org,Proxy +DOMAIN-SUFFIX,wezhiyong.org,Proxy +DOMAIN-SUFFIX,wezone.net,Proxy +DOMAIN-SUFFIX,wforum.com,Proxy +DOMAIN-SUFFIX,whatblocked.com,Proxy +DOMAIN-SUFFIX,whereiswerner.com,Proxy +DOMAIN-SUFFIX,wheretowatch.com,Proxy +DOMAIN-SUFFIX,whippedass.com,Proxy +DOMAIN-SUFFIX,whitebear.freebearblog.org,Proxy +DOMAIN-SUFFIX,who.is,Proxy +DOMAIN-SUFFIX,whydidyoubuymethat.com,Proxy +DOMAIN-SUFFIX,whylover.com,Proxy +DOMAIN-SUFFIX,whyx.org,Proxy +DOMAIN-SUFFIX,wiki.cnitter.com,Proxy +DOMAIN-SUFFIX,wiki.gamerp.jp,Proxy +DOMAIN-SUFFIX,wiki.jqueryui.com,Proxy +DOMAIN-SUFFIX,wiki.keso.cn,Proxy +DOMAIN-SUFFIX,wiki.moegirl.org,Proxy +DOMAIN-SUFFIX,wiki.oauth.net,Proxy +DOMAIN-SUFFIX,wiki.phonegap.com,Proxy +DOMAIN-SUFFIX,wikilivres.info,Proxy +DOMAIN-SUFFIX,wikiwiki.jp,Proxy +DOMAIN-SUFFIX,willw.net,Proxy +DOMAIN-SUFFIX,windowsphoneme.com,Proxy +DOMAIN-SUFFIX,wingamestore.com,Proxy +DOMAIN-SUFFIX,winwhispers.info,Proxy +DOMAIN-SUFFIX,wiredbytes.com,Proxy +DOMAIN-SUFFIX,wiredpen.com,Proxy +DOMAIN-SUFFIX,wireshark.org,Proxy +DOMAIN-SUFFIX,wisdompubs.org,Proxy +DOMAIN-SUFFIX,wisevid.com,Proxy +DOMAIN-SUFFIX,wistia.com,Proxy +DOMAIN-SUFFIX,wistia.net,Proxy +DOMAIN-SUFFIX,witnessleeteaching.com,Proxy +DOMAIN-SUFFIX,witopia.net,Proxy +DOMAIN-SUFFIX,wlx.sowiki.net,Proxy +DOMAIN-SUFFIX,wn.com,Proxy +DOMAIN-SUFFIX,wnacg.com,Proxy +DOMAIN-SUFFIX,wo.tc,Proxy +DOMAIN-SUFFIX,woeser.com,Proxy +DOMAIN-SUFFIX,woesermiddle-way.net,Proxy +DOMAIN-SUFFIX,wolfax.com,Proxy +DOMAIN-SUFFIX,woopie.jp,Proxy +DOMAIN-SUFFIX,woopie.tv,Proxy +DOMAIN-SUFFIX,wordboner.com,Proxy +DOMAIN-SUFFIX,wordpress.com,Proxy +DOMAIN-SUFFIX,wordsandturds.com,Proxy +DOMAIN-SUFFIX,workatruna.com,Proxy +DOMAIN-SUFFIX,workersthebig.net,Proxy +DOMAIN-SUFFIX,worldcat.org,Proxy +DOMAIN-SUFFIX,worldjournal.com,Proxy +DOMAIN-SUFFIX,worldnews01.com,Proxy +DOMAIN-SUFFIX,worstthingieverate.com,Proxy +DOMAIN-SUFFIX,wow-life.net,Proxy +DOMAIN-SUFFIX,wowlegacy.ml,Proxy +DOMAIN-SUFFIX,woxinghuiguo.com,Proxy +DOMAIN-SUFFIX,wozy.in,Proxy +DOMAIN-SUFFIX,wp.com,Proxy +DOMAIN-SUFFIX,wpoforum.com,Proxy +DOMAIN-SUFFIX,wqlhw.com,Proxy +DOMAIN-SUFFIX,wqyd.org,Proxy +DOMAIN-SUFFIX,wrangl.com,Proxy +DOMAIN-SUFFIX,wretch.cc,Proxy +DOMAIN-SUFFIX,writer.zoho.com,Proxy +DOMAIN-SUFFIX,wsgzao.github.io,Proxy +DOMAIN-SUFFIX,wsj.com,Proxy +DOMAIN-SUFFIX,wsj.net,Proxy +DOMAIN-SUFFIX,wsjemail.com,Proxy +DOMAIN-SUFFIX,wtfpeople.com,Proxy +DOMAIN-SUFFIX,wuala.com,Proxy +DOMAIN-SUFFIX,wuerkaixi.com,Proxy +DOMAIN-SUFFIX,wufi.org.tw,Proxy +DOMAIN-SUFFIX,wufoo.com,Proxy +DOMAIN-SUFFIX,wuguoguang.com,Proxy +DOMAIN-SUFFIX,wujie.net,Proxy +DOMAIN-SUFFIX,wujieliulan.com,Proxy +DOMAIN-SUFFIX,wukangrui.net,Proxy +DOMAIN-SUFFIX,wwitv.com,Proxy +DOMAIN-SUFFIX,www2.ohchr.org,Proxy +DOMAIN-SUFFIX,www2.rocketbbs.com,Proxy +DOMAIN-SUFFIX,wzyboy.im,Proxy +DOMAIN-SUFFIX,x-art.com,Proxy +DOMAIN-SUFFIX,x-berry.com,Proxy +DOMAIN-SUFFIX,x-wall.org,Proxy +DOMAIN-SUFFIX,x.xcity.jp,Proxy +DOMAIN-SUFFIX,x1949x.com,Proxy +DOMAIN-SUFFIX,x365x.com,Proxy +DOMAIN-SUFFIX,xa.yimg.com,Proxy +DOMAIN-SUFFIX,xanga.com,Proxy +DOMAIN-SUFFIX,xbabe.com,Proxy +DOMAIN-SUFFIX,xbookcn.com,Proxy +DOMAIN-SUFFIX,xcafe.in,Proxy +DOMAIN-SUFFIX,xcritic.com,Proxy +DOMAIN-SUFFIX,xfm.pp.ru,Proxy +DOMAIN-SUFFIX,xgmyd.com,Proxy +DOMAIN-SUFFIX,xh4n.cn,Proxy +DOMAIN-SUFFIX,xhamster.com,Proxy +DOMAIN-SUFFIX,xianqiao.net,Proxy +DOMAIN-SUFFIX,xiaochuncnjp.com,Proxy +DOMAIN-SUFFIX,xiaohexie.com,Proxy +DOMAIN-SUFFIX,xiaolan.me,Proxy +DOMAIN-SUFFIX,xiaoma.org,Proxy +DOMAIN-SUFFIX,xiezhua.com,Proxy +DOMAIN-SUFFIX,xing.com,Proxy +DOMAIN-SUFFIX,xinhuanet.org,Proxy +DOMAIN-SUFFIX,xinmiao.com.hk,Proxy +DOMAIN-SUFFIX,xinqimeng.over-blog.com,Proxy +DOMAIN-SUFFIX,xinsheng.net,Proxy +DOMAIN-SUFFIX,xinshijue.com,Proxy +DOMAIN-SUFFIX,xinyubbs.net,Proxy +DOMAIN-SUFFIX,xiongpian.com,Proxy +DOMAIN-SUFFIX,xizang-zhiye.org,Proxy +DOMAIN-SUFFIX,xjp.cc,Proxy +DOMAIN-SUFFIX,xlfmwz.info,Proxy +DOMAIN-SUFFIX,xml-training-guide.com,Proxy +DOMAIN-SUFFIX,xmovies.com,Proxy +DOMAIN-SUFFIX,xmusic.fm,Proxy +DOMAIN-SUFFIX,xnxx.com,Proxy +DOMAIN-SUFFIX,xpdo.net,Proxy +DOMAIN-SUFFIX,xpud.org,Proxy +DOMAIN-SUFFIX,xskywalker.com,Proxy +DOMAIN-SUFFIX,xtube.com,Proxy +DOMAIN-SUFFIX,xuchao.net,Proxy +DOMAIN-SUFFIX,xuchao.org,Proxy +DOMAIN-SUFFIX,xuzhiyong.net,Proxy +DOMAIN-SUFFIX,xuzhuoer.com,Proxy +DOMAIN-SUFFIX,xvedios.com,Proxy +DOMAIN-SUFFIX,xvideos.com,Proxy +DOMAIN-SUFFIX,xxbbx.com,Proxy +DOMAIN-SUFFIX,xxxx.com.au,Proxy +DOMAIN-SUFFIX,xys.dxiong.com,Proxy +DOMAIN-SUFFIX,xys.org,Proxy +DOMAIN-SUFFIX,xysblogs.org,Proxy +DOMAIN-SUFFIX,xyy69.com,Proxy +DOMAIN-SUFFIX,xyy69.info,Proxy +DOMAIN-SUFFIX,yahoo.com.hk,Proxy +DOMAIN-SUFFIX,yakbutterblues.com,Proxy +DOMAIN-SUFFIX,yam.com,Proxy +DOMAIN-SUFFIX,yangjianli.com,Proxy +DOMAIN-SUFFIX,yasni.co.uk,Proxy +DOMAIN-SUFFIX,yasukuni.or.jp,Proxy +DOMAIN-SUFFIX,ydy.com,Proxy +DOMAIN-SUFFIX,yeelou.com,Proxy +DOMAIN-SUFFIX,yeeyan.org,Proxy +DOMAIN-SUFFIX,yeeyi.com,Proxy +DOMAIN-SUFFIX,yegle.net,Proxy +DOMAIN-SUFFIX,yes123.com.tw,Proxy +DOMAIN-SUFFIX,yesasia.com,Proxy +DOMAIN-SUFFIX,yesasia.com.hk,Proxy +DOMAIN-SUFFIX,yfrog.com,Proxy +DOMAIN-SUFFIX,yhcw.net,Proxy +DOMAIN-SUFFIX,yi.org,Proxy +DOMAIN-SUFFIX,yibada.com,Proxy +DOMAIN-SUFFIX,yibaochina.com,Proxy +DOMAIN-SUFFIX,yidio.com,Proxy +DOMAIN-SUFFIX,yilubbs.com,Proxy +DOMAIN-SUFFIX,yipub.com,Proxy +DOMAIN-SUFFIX,yogichen.org,Proxy +DOMAIN-SUFFIX,yong.hu,Proxy +DOMAIN-SUFFIX,yorkbbs.ca,Proxy +DOMAIN-SUFFIX,youjizz.com,Proxy +DOMAIN-SUFFIX,youmaker.com,Proxy +DOMAIN-SUFFIX,youpai.org,Proxy +DOMAIN-SUFFIX,youporn.com,Proxy +DOMAIN-SUFFIX,youporngay.com,Proxy +DOMAIN-SUFFIX,your-freedom.net,Proxy +DOMAIN-SUFFIX,yourepeat.com,Proxy +DOMAIN-SUFFIX,yousendit.com,Proxy +DOMAIN-SUFFIX,youthbao.com,Proxy +DOMAIN-SUFFIX,youthnetradio.org,Proxy +DOMAIN-SUFFIX,youversion.com,Proxy +DOMAIN-SUFFIX,youxu.info,Proxy +DOMAIN-SUFFIX,ytht.net,Proxy +DOMAIN-SUFFIX,ytimg.com,Proxy +DOMAIN-SUFFIX,yuanming.net,Proxy +DOMAIN-SUFFIX,yuming.flnet.org,Proxy +DOMAIN-SUFFIX,yunchao.net,Proxy +DOMAIN-SUFFIX,yvesgeleyn.com,Proxy +DOMAIN-SUFFIX,yx51.net,Proxy +DOMAIN-SUFFIX,yyets.com,Proxy +DOMAIN-SUFFIX,yyii.org,Proxy +DOMAIN-SUFFIX,yymaya.com,Proxy +DOMAIN-SUFFIX,yzzk.com,Proxy +DOMAIN-SUFFIX,zacebook.com,Proxy +DOMAIN-SUFFIX,zannel.com,Proxy +DOMAIN-SUFFIX,zaobao.com,Proxy +DOMAIN-SUFFIX,zaobao.com.sg,Proxy +DOMAIN-SUFFIX,zaozon.com,Proxy +DOMAIN-SUFFIX,zarias.com,Proxy +DOMAIN-SUFFIX,zattoo.com,Proxy +DOMAIN-SUFFIX,zaurus.org.uk,Proxy +DOMAIN-SUFFIX,zdassets.com,Proxy +DOMAIN-SUFFIX,zdnet.com.tw,Proxy +DOMAIN-SUFFIX,zengjinyan.org,Proxy +DOMAIN-SUFFIX,zensur.freerk.com,Proxy +DOMAIN-SUFFIX,zeutch.com,Proxy +DOMAIN-SUFFIX,zfreet.com,Proxy +DOMAIN-SUFFIX,zgzcjj.net,Proxy +DOMAIN-SUFFIX,zh-tw.justin.tv,Proxy +DOMAIN-SUFFIX,zh-yue.wikipedia.org,Proxy +DOMAIN-SUFFIX,zh.m.wikipedia.org,Proxy +DOMAIN-SUFFIX,zh.netlog.com,Proxy +DOMAIN-SUFFIX,zh.pokerstrategy.com,Proxy +DOMAIN-SUFFIX,zh.uncyclopedia.wikia.com,Proxy +DOMAIN-SUFFIX,zh.wikibooks.org,Proxy +DOMAIN-SUFFIX,zh.wikinews.org,Proxy +DOMAIN-SUFFIX,zh.wikipedia.org,Proxy +DOMAIN-SUFFIX,zh.wikisource.org,Proxy +DOMAIN-SUFFIX,zhanbin.net,Proxy +DOMAIN-SUFFIX,zhangboli.net,Proxy +DOMAIN-SUFFIX,zhangtianliang.com,Proxy +DOMAIN-SUFFIX,zhao.jinhai.de,Proxy +DOMAIN-SUFFIX,zhenghui.org,Proxy +DOMAIN-SUFFIX,zhengwunet.org,Proxy +DOMAIN-SUFFIX,zhenlibu.info,Proxy +DOMAIN-SUFFIX,zhenxiang.biz,Proxy +DOMAIN-SUFFIX,zhinengluyou.com,Proxy +DOMAIN-SUFFIX,zhongguorenquan.org,Proxy +DOMAIN-SUFFIX,zhongguotese.net,Proxy +DOMAIN-SUFFIX,zhongmeng.org,Proxy +DOMAIN-SUFFIX,zhreader.com,Proxy +DOMAIN-SUFFIX,zhufeng.me,Proxy +DOMAIN-SUFFIX,zhuichaguoji.org,Proxy +DOMAIN-SUFFIX,ziddu.com,Proxy +DOMAIN-SUFFIX,zillionk.com,Proxy +DOMAIN-SUFFIX,zinio.com,Proxy +DOMAIN-SUFFIX,ziplib.com,Proxy +DOMAIN-SUFFIX,zkaip.com,Proxy +DOMAIN-SUFFIX,zlib.net,Proxy +DOMAIN-SUFFIX,zmw.cn,Proxy +DOMAIN-SUFFIX,zomobo.net,Proxy +DOMAIN-SUFFIX,zkcdn.net,Proxy +DOMAIN-SUFFIX,zonaeuropa.com,Proxy +DOMAIN-SUFFIX,zootool.com,Proxy +DOMAIN-SUFFIX,zoozle.net,Proxy +DOMAIN-SUFFIX,zozotown.com,Proxy +DOMAIN-SUFFIX,zshare.net,Proxy +DOMAIN-SUFFIX,zsrhao.com,Proxy +DOMAIN-SUFFIX,zuo.la,Proxy +DOMAIN-SUFFIX,zuobiao.me,Proxy +DOMAIN-SUFFIX,zuola.com,Proxy +DOMAIN-SUFFIX,zvereff.com,Proxy +DOMAIN-SUFFIX,zyzc9.com,Proxy + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + +# Amazon +DOMAIN-SUFFIX,amazon.com,Proxy +DOMAIN-SUFFIX,amazonaws.com,Proxy +DOMAIN-SUFFIX,glue-static.s3-external-3.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3-eu-west-1.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3.amazonaws.com,Proxy +DOMAIN-SUFFIX,images-amazon.com,Proxy +DOMAIN-SUFFIX,ssl-images-amazon.com,Proxy + +# TWITCH +DOMAIN-SUFFIX,ioam.de,Proxy + + +# KUVVA +DOMAIN-SUFFIX,kuvva.com,Proxy +DOMAIN-SUFFIX,twimg.com,Proxy +DOMAIN-SUFFIX,edgekey.net,Proxy + +# Line By @pikatse +DOMAIN-SUFFIX,line-cdn.net,Proxy +DOMAIN-SUFFIX,line.me,Proxy,force-remote-dns +DOMAIN-SUFFIX,line.naver.jp,Proxy,force-remote-dns +DOMAIN-SUFFIX,line-apps.com,Proxy,force-remote-dns + +# VOA +DOMAIN-SUFFIX,voacantonese.com,Proxy +DOMAIN-SUFFIX,voachinese.com,Proxy +DOMAIN-SUFFIX,voachineseblog.com,Proxy +DOMAIN-SUFFIX,voagd.com,Proxy +DOMAIN-SUFFIX,voanews.com,Proxy +DOMAIN-SUFFIX,voatibetan.com,Proxy +DOMAIN-SUFFIX,cn.voa.mobi,Proxy + + + +# Spotify By @LUDOVICFM +DOMAIN-SUFFIX,scorecardresearch.com,Proxy +DOMAIN-KEYWORD,scdn,Proxy +DOMAIN-KEYWORD,moatads,Proxy + +DOMAIN-KEYWORD,akamaistream,Proxy + +# TVB +DOMAIN-KEYWORD,tvb.com,Proxy + +# OTH +DOMAIN-KEYWORD,wikileaks,Proxy +DOMAIN-KEYWORD,wikimapia,Proxy +DOMAIN-KEYWORD,epochtimes,Proxy +DOMAIN-KEYWORD,uncyclopedia,Proxy +DOMAIN-KEYWORD,tibet,Proxy +DOMAIN-KEYWORD,fgmtv,Proxy +DOMAIN-KEYWORD,geocities,Proxy +DOMAIN-KEYWORD,savetibet,Proxy +DOMAIN-KEYWORD,ntdtv,Proxy +DOMAIN-KEYWORD,falundafa,Proxy +DOMAIN-KEYWORD,taiwannation,Proxy +DOMAIN-KEYWORD,rangzen,Proxy +DOMAIN-KEYWORD,bbc,Proxy +DOMAIN-KEYWORD,bloomberg,Proxy +DOMAIN-KEYWORD,appledaily,Proxy +DOMAIN-KEYWORD,chinaaid,Proxy +DOMAIN-KEYWORD,popyard,Proxy +DOMAIN-KEYWORD,raidcall,Proxy + + +# BLOGSPOT +DOMAIN-KEYWORD,blogspot,Proxy + + +DOMAIN-KEYWORD,akamaihd,Proxy,no-resolve +DOMAIN-KEYWORD,google,Proxy,force-remote-dns +DOMAIN-KEYWORD,facebook,Proxy,force-remote-dns +DOMAIN-KEYWORD,youtube,Proxy,force-remote-dns +DOMAIN-KEYWORD,twitter,Proxy,force-remote-dns +DOMAIN-KEYWORD,gmail,Proxy,force-remote-dns +DOMAIN-KEYWORD,instagram,Proxy,force-remote-dns +DOMAIN-KEYWORD,vimeo,Proxy,force-remote-dns +DOMAIN-KEYWORD,deviantart,Proxy,force-remote-dns +DOMAIN-KEYWORD,twitch,Proxy,force-remote-dns +DOMAIN-KEYWORD,jtvnw,Proxy,force-remote-dns +DOMAIN-KEYWORD,ttvnw,Proxy,force-remote-dns +DOMAIN-KEYWORD,dropbox,Proxy,force-remote-dns +DOMAIN-KEYWORD,telegram,Proxy,force-remote-dns +DOMAIN-KEYWORD,spotify,Proxy,force-remote-dns + + +# Telegram +IP-CIDR,91.108.56.0/22,Proxy,no-resolve +IP-CIDR,91.108.4.0/22,Proxy,no-resolve +IP-CIDR,109.239.140.0/24,Proxy,no-resolve +IP-CIDR,149.154.160.0/20,Proxy,no-resolve +IP-CIDR,101.227.14.0/24,REJECT,no-resolve +IP-CIDR,101.227.12.0/24,REJECT,no-resolve +IP-CIDR,111.63.135.146/32,REJECT,no-resolve +IP-CIDR,111.206.22.0/24,REJECT,no-resolve +IP-CIDR,121.251.255.237/32,REJECT,no-resolve +IP-CIDR,123.125.117.0/24,REJECT,no-resolve +IP-CIDR,123.125.118.0/24,REJECT,no-resolve +#IP-CIDR,111.206.13.0/24,REJECT,no-resolve + + +# LAN +IP-CIDR,10.0.0.0/8,DIRECT +IP-CIDR,100.64.0.0/10,DIRECT +IP-CIDR,127.0.0.0/8,DIRECT +IP-CIDR,172.0.0.0/8,DIRECT +IP-CIDR,192.168.0.0/16,DIRECT + + +GEOIP, CN, DIRECT +FINAL, Proxy + + + + +[URL Rewrite] +^.*splash.*$ test1 +^.*\/lego\/.*$ test2 +^http://www.google.cn http://www.google.com.hk +^http://m.baidu.com/s\?from=1099b&word= http://google.com/search\?q= +^http://www.baidu.com/s\?wd= http://google.com/search\?q= \ No newline at end of file diff --git a/Surf/surf.conf b/Surf/surf.conf new file mode 100644 index 0000000..25d7aa1 --- /dev/null +++ b/Surf/surf.conf @@ -0,0 +1,818 @@ +[General] +skip-proxy = 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 127.0.0.0/8,100.64.0.0/10, localhost, *.local, e.crashlytics.com +bypass-tun = 192.168.0.0/16,10.0.0.0/8, 172.16.0.0/12,169.254.0.0/16 +dns-server = system,119.29.29.29,223.6.6.6, 223.5.5.5 +loglevel = notify + +[Rule] +// UA +USER-AGENT,%E5%8D%B3%E5%88%BB,DIRECT +USER-AGENT,arrowio,DIRECT +USER-AGENT,balls,DIRECT +USER-AGENT,hide,DIRECT +USER-AGENT,MegaWerewolf,DIRECT +USER-AGENT,MicroMessenger,DIRECT +USER-AGENT,Moke,DIRECT +USER-AGENT,osee2unifiedRelease,DIRECT +USER-AGENT,QQ,DIRECT +USER-AGENT,Speedtest,DIRECT +USER-AGENT,TIM,DIRECT +USER-AGENT,WeChat,DIRECT + + + +DOMAIN-SUFFIX,appldnld.apple.com,DIRECT +DOMAIN-SUFFIX,mesu.apple.com,DIRECT +DOMAIN,capture.apple.com,DIRECT +#USER-AGENT,CriOS,Proxy +USER-AGENT,ph.telegra.Telegraph,Proxy +DOMAIN,pscp.tv,Proxy +DOMAIN,beta.itunes.apple.com,Proxy +DOMAIN,init.itunes.apple.com,DIRECT +DOMAIN,audio.itunes.apple.com,DIRECT +DOMAIN,iosapps.itunes.apple.com,DIRECT +DOMAIN,play.itunes.apple.com,DIRECT +DOMAIN,aod.itune.apple.com,DIRECT + +# Apple PACKAGE DIRECT +DOMAIN-SUFFIX,appldnld.apple.com,DIRECT +DOMAIN-SUFFIX,adcdownload.apple.com,DIRECT +DOMAIN-SUFFIX,lcdn-registration.apple.com,DIRECT +DOMAIN-SUFFIX,swcdn.apple.com,DIRECT +DOMAIN-SUFFIX,phobos.apple.com,DIRECT +DOMAIN-SUFFIX,ls.apple.com,DIRECT +DOMAIN-SUFFIX,cdn-apple.com,DIRECT + + +# Apple PACKAGE PROXY-B +# 建议直连,较高要求可以改变连接方式 +DOMAIN-SUFFIX,icloud.com,DIRECT +DOMAIN-SUFFIX,me.com,DIRECT +DOMAIN-SUFFIX,apple.com,DIRECT +DOMAIN-SUFFIX,itunes.apple.com,DIRECT +DOMAIN-SUFFIX,mzstatic.com,DIRECT + + + + +# SpeedTest +DOMAIN,ads.ookla.com,REJECT +DOMAIN,cdn.ads.ookla.com,REJECT + +# App Laugh Skin +DOMAIN,u1.img.mobile.sina.cn,REJECT + +# Qiushibaike +DOMAIN,mi.gdt.qq.com,REJECT + +# Sina +DOMAIN,sax.sina.cn,REJECT + +# Xunfei +DOMAIN,bj.imp.voiceads.cn,REJECT + +# Systemav +DOMAIN,m.madthumbs.com,REJECT + +# Google +DOMAIN,csi.gstatic.com,REJECT +DOMAIN,static.googleadsserving.cn,REJECT +DOMAIN,ads.google.com,REJECT +DOMAIN,afd.l.google.com,REJECT +DOMAIN,mobileads.google.com,REJECT +DOMAIN,pagead-tpc.l.google.com,REJECT +DOMAIN,pagead.google.com,REJECT +DOMAIN,pagead.l.google.com,REJECT +DOMAIN,partnerad.l.google.com,REJECT +DOMAIN,ads.youtube.com,REJECT +DOMAIN,ads.gmodules.com,REJECT +DOMAIN,badad.googleplex.com,REJECT +DOMAIN,www.googlecommerce.com,REJECT +DOMAIN,www.googletagmanager.com,REJECT +DOMAIN,service.urchin.com,REJECT + +# AutoHome +DOMAIN,adm3.autoimg.cn,REJECT +DOMAIN,adm0.autoimg.cn,REJECT +DOMAIN,img2.autoimg.cn,REJECT + +# Dropbox +DOMAIN,d.dropbox.com,REJECT +DOMAIN,dl-debug.dropbox.com,REJECT + +# Twitter +DOMAIN,syndication.twitter.com,REJECT +DOMAIN-SUFFIX,twitter.com,Proxy +# DSP +DOMAIN,dsp.lomark.cn,REJECT + +# VIU By +DOMAIN,stream-hk.viu.com,Proxy +DOMAIN,global.adserver.yahoo.com,REJECT + + +# CDN +DOMAIN,init.icloud-analysis.com, REJECT +DOMAIN,zhihu-analytics.zhihu.com,REJECT +DOMAIN,log.cmbchina.com,REJECT +DOMAIN,api.segment.io,REJECT +DOMAIN,api.instabug.com,REJECT +DOMAIN,adlog.flurry.com,REJECT +DOMAIN,ads.flurry.com,REJECT + + + +DOMAIN,r1.ykimg.com,REJECT +DOMAIN,v.gdt.qq.com,REJECT +DOMAIN,sd.domob.cn,REJECT + + + + + + + + + +# Taobao +DOMAIN,h5.m.taobao.com,DIRECT + +# Duolinguo +DOMAIN,api.mixpanel.com,DIRECT +DOMAIN,d2pur3iezf4d1j.cloudfront.net,DIRECT + +DOMAIN,wscdns.com,DIRECT + +# Synology +DOMAIN-SUFFIX,QuickConnect.to,DIRECT + +# Alipay +DOMAIN-SUFFIX,alipaylog.com,DIRECT + +# Taobao +DOMAIN-SUFFIX,taobaocdn.com,DIRECT +DOMAIN-SUFFIX,alicdn.com,DIRECT + +# 12306 +DOMAIN-SUFFIX,12306.cn,DIRECT + +# 17APP +DOMAIN-SUFFIX,17app.co,DIRECT + +# 126 +DOMAIN-SUFFIX,126.net,DIRECT +DOMAIN-SUFFIX,163.com,DIRECT +DOMAIN-SUFFIX,netnease.com,DIRECT + +# 360buy +DOMAIN-SUFFIX,360buyimg.com,DIRECT +#DOMAIN-SUFFIX,jd.com,DIRECT + +# ICBC +DOMAIN-SUFFIX,icbc.com,DIRECT + +# 10010 By ސސސސސސސސސސ +DOMAIN-SUFFIX,6-10010.com,DIRECT + + +# iMuzo +DOMAIN-SUFFIX,iheart.com,DIRECT +DOMAIN-SUFFIX,dongting.com,DIRECT +DOMAIN-SUFFIX,iyyin.com,DIRECT +DOMAIN-SUFFIX,openspeech.cn,DIRECT + + +# CDN +DOMAIN-SUFFIX,yunjiasu-cdn.net,DIRECT +DOMAIN-SUFFIX,8686c.com,DIRECT +DOMAIN-SUFFIX,ourdvs.com,DIRECT +DOMAIN-SUFFIX,spotilocal.com,DIRECT + +# CN DIRECT +DOMAIN-SUFFIX,cn,DIRECT + +# CHINA WHITE LIST +DOMAIN-SUFFIX,com.cn,DIRECT +DOMAIN-SUFFIX,edu.cn,DIRECT +DOMAIN-SUFFIX,org.cn,DIRECT +DOMAIN-SUFFIX,net.cn,DIRECT +DOMAIN-SUFFIX,gov.cn,DIRECT +DOMAIN-SUFFIX,weibo.cn,DIRECT +DOMAIN-SUFFIX,sina.cn,DIRECT +DOMAIN-SUFFIX,tbcdn.cn,DIRECT +DOMAIN-SUFFIX,sinajs.cn,DIRECT +DOMAIN-SUFFIX,amazon.cn,DIRECT +DOMAIN-SUFFIX,360.cn,DIRECT +DOMAIN-SUFFIX,flyme.cn,DIRECT +DOMAIN-SUFFIX,mtime.cn,DIRECT +DOMAIN-SUFFIX,ifanr.cn,DIRECT +DOMAIN-SUFFIX,kuwo.cn,DIRECT +DOMAIN-SUFFIX,kuaipan.cn,DIRECT +DOMAIN-SUFFIX,3g.cn,DIRECT +DOMAIN-SUFFIX,tianya.cn,DIRECT +DOMAIN-SUFFIX,url.cn,DIRECT +DOMAIN-SUFFIX,blued.cn,DIRECT +DOMAIN-SUFFIX,189.cn,DIRECT +DOMAIN-SUFFIX,10086.cn,DIRECT +DOMAIN-SUFFIX,10010.cn,DIRECT +DOMAIN-SUFFIX,uc.cn,DIRECT +DOMAIN-SUFFIX,damai.cn,DIRECT +DOMAIN-SUFFIX,suning.cn,DIRECT +DOMAIN-SUFFIX,liebao.cn,DIRECT +DOMAIN-SUFFIX,mifile.cn,DIRECT +DOMAIN-SUFFIX,voicecloud.cn,DIRECT +DOMAIN-SUFFIX,wps.cn,DIRECT +DOMAIN-SUFFIX,8684.cn,DIRECT +DOMAIN-SUFFIX,uniqlo.cn,DIRECT +DOMAIN-SUFFIX,ifeng.com,DIRECT +DOMAIN-SUFFIX,ifengimg.com,DIRECT +DOMAIN-SUFFIX,bbwc.cn,DIRECT +DOMAIN-SUFFIX,3.cn,DIRECT +DOMAIN-SUFFIX,maxthon.cn,DIRECT +DOMAIN-SUFFIX,xda.cn,DIRECT +DOMAIN-SUFFIX,cntv.cn,DIRECT +DOMAIN-SUFFIX,6.cn,DIRECT +DOMAIN-SUFFIX,meizu.cn,DIRECT +DOMAIN-SUFFIX,360doc.cn,DIRECT +DOMAIN-SUFFIX,sto.cn,DIRECT +DOMAIN-SUFFIX,xiaomi.cn,DIRECT +DOMAIN-SUFFIX,ccb.cn,DIRECT +DOMAIN-SUFFIX,macx.cn,DIRECT +DOMAIN-SUFFIX,d.cn,DIRECT +DOMAIN-SUFFIX,m1905.cn,DIRECT +DOMAIN-SUFFIX,t.cn,DIRECT +DOMAIN-SUFFIX,sh.cn,DIRECT +DOMAIN-SUFFIX,bong.cn,DIRECT +DOMAIN-SUFFIX,mafengwo.cn,DIRECT +DOMAIN-SUFFIX,ucloud.cn,DIRECT +DOMAIN-SUFFIX,xdf.cn,DIRECT +DOMAIN-SUFFIX,china.cn,DIRECT +DOMAIN-SUFFIX,ip.cn,DIRECT +DOMAIN-SUFFIX,news.cn,DIRECT +DOMAIN-SUFFIX,linux.cn,DIRECT +DOMAIN-SUFFIX,dict.cn,DIRECT +DOMAIN-SUFFIX,windowsazure.cn,DIRECT +DOMAIN-SUFFIX,dwz.cn,DIRECT +DOMAIN-SUFFIX,10010.com,DIRECT +DOMAIN-SUFFIX,115.com,DIRECT +DOMAIN-SUFFIX,123u.com,DIRECT +DOMAIN-SUFFIX,126.com,DIRECT +DOMAIN-SUFFIX,17173.com,DIRECT +DOMAIN-SUFFIX,178.com,DIRECT +DOMAIN-SUFFIX,17cdn.com,DIRECT +DOMAIN-SUFFIX,21cn.com,DIRECT +DOMAIN-SUFFIX,2288.org,DIRECT +DOMAIN-SUFFIX,3322.org,DIRECT +DOMAIN-SUFFIX,360doc.com,DIRECT +DOMAIN-SUFFIX,360safe.com,DIRECT +DOMAIN-SUFFIX,36kr.com,DIRECT +DOMAIN-SUFFIX,400gb.com,DIRECT +DOMAIN-SUFFIX,4399.com,DIRECT +DOMAIN-SUFFIX,51.la,DIRECT +DOMAIN-SUFFIX,51buy.com,DIRECT +DOMAIN-SUFFIX,51cto.com,DIRECT +DOMAIN-SUFFIX,51job.com,DIRECT +DOMAIN-SUFFIX,51jobcdn.com,DIRECT +DOMAIN-SUFFIX,5d6d.com,DIRECT +DOMAIN-SUFFIX,5d6d.net,DIRECT +DOMAIN-SUFFIX,61.com,DIRECT +DOMAIN-SUFFIX,6600.org,DIRECT +DOMAIN-SUFFIX,6rooms.com,DIRECT +DOMAIN-SUFFIX,7766.org,DIRECT +DOMAIN-SUFFIX,7k7k.com,DIRECT +DOMAIN-SUFFIX,8800.org,DIRECT +DOMAIN-SUFFIX,8866.org,DIRECT +DOMAIN-SUFFIX,90g.org,DIRECT +DOMAIN-SUFFIX,91.com,DIRECT +DOMAIN-SUFFIX,9966.org,DIRECT +DOMAIN-SUFFIX,acfun.tv,DIRECT +DOMAIN-SUFFIX,aicdn.com,DIRECT +DOMAIN-SUFFIX,ali213.net,DIRECT +DOMAIN-SUFFIX,alibaba.com,DIRECT +DOMAIN-SUFFIX,aliexpress.com,DIRECT +DOMAIN-SUFFIX,aliimg.com,DIRECT +DOMAIN-SUFFIX,alikunlun.com,DIRECT +DOMAIN-SUFFIX,alisoft.com,DIRECT +DOMAIN-SUFFIX,aliyun.com,DIRECT +DOMAIN-SUFFIX,aliyuncdn.com,DIRECT +DOMAIN-SUFFIX,aliyuncs.com,DIRECT +DOMAIN-SUFFIX,anzhi.com,DIRECT +DOMAIN-SUFFIX,appinn.com,DIRECT +DOMAIN-SUFFIX,apple.com,DIRECT +DOMAIN-SUFFIX,appsina.com,DIRECT +DOMAIN-SUFFIX,archlinuxcn.org,DIRECT +DOMAIN-SUFFIX,atpanel.com,DIRECT +DOMAIN-SUFFIX,baifendian.com,DIRECT +DOMAIN-SUFFIX,baihe.com,DIRECT +DOMAIN-SUFFIX,baixing.com,DIRECT +DOMAIN-SUFFIX,bdimg.com,DIRECT +DOMAIN-SUFFIX,bdstatic.com,DIRECT +DOMAIN-SUFFIX,bilibili.tv,DIRECT +DOMAIN-SUFFIX,blogbus.com,DIRECT +DOMAIN-SUFFIX,blueidea.com,DIRECT +DOMAIN-SUFFIX,ccb.com,DIRECT +DOMAIN-SUFFIX,cctv.com,DIRECT +DOMAIN-SUFFIX,cctvpic.com,DIRECT +DOMAIN-SUFFIX,cdn20.com,DIRECT +DOMAIN-SUFFIX,china.com,DIRECT +DOMAIN-SUFFIX,chinabyte.com,DIRECT +DOMAIN-SUFFIX,chinacache.com,DIRECT +DOMAIN-SUFFIX,chinacache.net,DIRECT +DOMAIN-SUFFIX,chinacaipu.com,DIRECT +DOMAIN-SUFFIX,chinagba.com,DIRECT +DOMAIN-SUFFIX,chinahr.com,DIRECT +DOMAIN-SUFFIX,chinajoy.net,DIRECT +DOMAIN-SUFFIX,chinamobile.com,DIRECT +DOMAIN-SUFFIX,chinanetcenter.com,DIRECT +DOMAIN-SUFFIX,chinanews.com,DIRECT +DOMAIN-SUFFIX,chinapnr.com,DIRECT +DOMAIN-SUFFIX,chinaren.com,DIRECT +DOMAIN-SUFFIX,chinaspeeds.net,DIRECT +DOMAIN-SUFFIX,chinaunix.net,DIRECT +DOMAIN-SUFFIX,chinaz.com,DIRECT +DOMAIN-SUFFIX,chint.com,DIRECT +DOMAIN-SUFFIX,chiphell.com,DIRECT +DOMAIN-SUFFIX,chuangxin.com,DIRECT +DOMAIN-SUFFIX,ci123.com,DIRECT +DOMAIN-SUFFIX,ciku5.com,DIRECT +DOMAIN-SUFFIX,citysbs.com,DIRECT +DOMAIN-SUFFIX,class.coursera.org,DIRECT +DOMAIN-SUFFIX,cloudcdn.net,DIRECT +DOMAIN-SUFFIX,cmbchina.com,DIRECT +DOMAIN-SUFFIX,cmfu.com,DIRECT +DOMAIN-SUFFIX,cmread.com,DIRECT +DOMAIN-SUFFIX,cmwb.com,DIRECT +DOMAIN-SUFFIX,cn.archive.ubuntu.com,DIRECT +DOMAIN-SUFFIX,cn.bing.com,DIRECT +DOMAIN-SUFFIX,cn.coremetrics.com,DIRECT +DOMAIN-SUFFIX,cn.debian.org,DIRECT +DOMAIN-SUFFIX,cn.msn.com,DIRECT +DOMAIN-SUFFIX,cnak2.englishtown.com,DIRECT +DOMAIN-SUFFIX,cnbeta.com,DIRECT +DOMAIN-SUFFIX,cnbetacdn.com,DIRECT +DOMAIN-SUFFIX,cnblogs.com,DIRECT +DOMAIN-SUFFIX,cnepub.com,DIRECT +DOMAIN-SUFFIX,cnzz.com,DIRECT +DOMAIN-SUFFIX,comsenz.com,DIRECT +DOMAIN-SUFFIX,csdn.net,DIRECT +DOMAIN-SUFFIX,ct10000.com,DIRECT +DOMAIN-SUFFIX,ctdisk.com,DIRECT +DOMAIN-SUFFIX,dangdang.com,DIRECT +DOMAIN-SUFFIX,dbank.com,DIRECT +DOMAIN-SUFFIX,dedecms.com,DIRECT +DOMAIN-SUFFIX,diandian.com,DIRECT +DOMAIN-SUFFIX,dianping.com,DIRECT +DOMAIN-SUFFIX,discuz.com,DIRECT +DOMAIN-SUFFIX,discuz.net,DIRECT +DOMAIN-SUFFIX,docin.com,DIRECT +DOMAIN-SUFFIX,donews.com,DIRECT +DOMAIN-SUFFIX,dospy.com,DIRECT +DOMAIN-SUFFIX,douban.com,DIRECT +DOMAIN-SUFFIX,douban.fm,DIRECT +DOMAIN-SUFFIX,duapp.com,DIRECT +DOMAIN-SUFFIX,duba.net,DIRECT +DOMAIN-SUFFIX,duomi.com,DIRECT +DOMAIN-SUFFIX,duote.com,DIRECT +DOMAIN-SUFFIX,duowan.com,DIRECT +DOMAIN-SUFFIX,egou.com,DIRECT +DOMAIN-SUFFIX,et8.org,DIRECT +DOMAIN-SUFFIX,etao.com,DIRECT +DOMAIN-SUFFIX,f3322.org,DIRECT +DOMAIN-SUFFIX,fantong.com,DIRECT +DOMAIN-SUFFIX,fenzhi.com,DIRECT +DOMAIN-SUFFIX,fhldns.com,DIRECT +DOMAIN-SUFFIX,ganji.com,DIRECT +DOMAIN-SUFFIX,gaopeng.com,DIRECT +DOMAIN-SUFFIX,geekpark.net,DIRECT +DOMAIN-SUFFIX,gfan.com,DIRECT +DOMAIN-SUFFIX,hacdn.net,DIRECT +DOMAIN-SUFFIX,hadns.net,DIRECT +DOMAIN-SUFFIX,hao123.com,DIRECT +DOMAIN-SUFFIX,hao123img.com,DIRECT +DOMAIN-SUFFIX,hc360.com,DIRECT +DOMAIN-SUFFIX,hdslb.com,DIRECT +DOMAIN-SUFFIX,hexun.com,DIRECT +DOMAIN-SUFFIX,hiapk.com,DIRECT +DOMAIN-SUFFIX,hichina.com,DIRECT +DOMAIN-SUFFIX,hoopchina.com,DIRECT +DOMAIN-SUFFIX,huanqiu.com,DIRECT +DOMAIN-SUFFIX,hudong.com,DIRECT +DOMAIN-SUFFIX,huochepiao.com,DIRECT +DOMAIN-SUFFIX,hupu.com,DIRECT +DOMAIN-SUFFIX,iask.com,DIRECT +DOMAIN-SUFFIX,iciba.com,DIRECT +DOMAIN-SUFFIX,idqqimg.com,DIRECT +DOMAIN-SUFFIX,ifanr.com,DIRECT +DOMAIN-SUFFIX,ijinshan.com,DIRECT +DOMAIN-SUFFIX,iqiyi.com,DIRECT +DOMAIN-SUFFIX,it168.com,DIRECT +DOMAIN-SUFFIX,itcpn.net,DIRECT +DOMAIN-SUFFIX,iteye.com,DIRECT +DOMAIN-SUFFIX,itouzi.com,DIRECT +DOMAIN-SUFFIX,jandan.net,DIRECT +DOMAIN-SUFFIX,jiashule.com,DIRECT +DOMAIN-SUFFIX,jiasule.com,DIRECT +DOMAIN-SUFFIX,jiathis.com,DIRECT +DOMAIN-SUFFIX,jiayuan.com,DIRECT +DOMAIN-SUFFIX,jiepang.com,DIRECT +DOMAIN-SUFFIX,jing.fm,DIRECT +DOMAIN-SUFFIX,jobbole.com,DIRECT +DOMAIN-SUFFIX,jstv.com,DIRECT +DOMAIN-SUFFIX,jumei.com,DIRECT +DOMAIN-SUFFIX,kaixin001.com,DIRECT +DOMAIN-SUFFIX,kandian.com,DIRECT +DOMAIN-SUFFIX,kandian.net,DIRECT +DOMAIN-SUFFIX,kanimg.com,DIRECT +DOMAIN-SUFFIX,kankanews.com,DIRECT +DOMAIN-SUFFIX,kdnet.net,DIRECT +DOMAIN-SUFFIX,koudai8.com,DIRECT +DOMAIN-SUFFIX,ku6.com,DIRECT +DOMAIN-SUFFIX,ku6cdn.com,DIRECT +DOMAIN-SUFFIX,ku6img.com,DIRECT +DOMAIN-SUFFIX,kuaidi100.com,DIRECT +DOMAIN-SUFFIX,kugou.com,DIRECT +DOMAIN-SUFFIX,lashou.com,DIRECT +DOMAIN-SUFFIX,letao.com,DIRECT +DOMAIN-SUFFIX,letv.com,DIRECT +DOMAIN-SUFFIX,lietou.com,DIRECT +DOMAIN-SUFFIX,linezing.com,DIRECT +DOMAIN-SUFFIX,loli.mg,DIRECT +DOMAIN-SUFFIX,loli.vg,DIRECT +DOMAIN-SUFFIX,lvping.com,DIRECT +DOMAIN-SUFFIX,lxdns.com,DIRECT +DOMAIN-SUFFIX,dns.weixin.qq.com,DIRECT +DOMAIN-SUFFIX,mangocity.com,DIRECT +DOMAIN-SUFFIX,mapbar.com,DIRECT +DOMAIN-SUFFIX,mcbbs.net,DIRECT +DOMAIN-SUFFIX,meilishuo.com,DIRECT +DOMAIN-SUFFIX,meituan.com,DIRECT +DOMAIN-SUFFIX,meituan.net,DIRECT +DOMAIN-SUFFIX,meizu.com,DIRECT +DOMAIN-SUFFIX,microsoft.com,DIRECT +DOMAIN-SUFFIX,miui.com,DIRECT +DOMAIN-SUFFIX,moe123.com,DIRECT +DOMAIN-SUFFIX,moegirl.org,DIRECT +DOMAIN-SUFFIX,mop.com,DIRECT +DOMAIN-SUFFIX,mtime.com,DIRECT +DOMAIN-SUFFIX,my-card.in,DIRECT +DOMAIN-SUFFIX,mydrivers.com,DIRECT +DOMAIN-SUFFIX,mzstatic.com,DIRECT +DOMAIN-SUFFIX,newsmth.net,DIRECT +DOMAIN-SUFFIX,ngacn.cc,DIRECT +DOMAIN-SUFFIX,nuomi.com,DIRECT +DOMAIN-SUFFIX,okbuy.com,DIRECT +DOMAIN-SUFFIX,optaim.com,DIRECT +DOMAIN-SUFFIX,oschina.net,DIRECT +DOMAIN-SUFFIX,paipai.com,DIRECT +DOMAIN-SUFFIX,pcbeta.com,DIRECT +DOMAIN-SUFFIX,pchome.net,DIRECT +DOMAIN-SUFFIX,pcpop.com,DIRECT +DOMAIN-SUFFIX,pengyou.com,DIRECT +DOMAIN-SUFFIX,phoenixlzx.com,DIRECT +DOMAIN-SUFFIX,phpwind.net,DIRECT +DOMAIN-SUFFIX,pingan.com,DIRECT +DOMAIN-SUFFIX,pool.ntp.org,DIRECT +DOMAIN-SUFFIX,pplive.com,DIRECT +DOMAIN-SUFFIX,pps.tv,DIRECT +DOMAIN-SUFFIX,ppstream.com,DIRECT +DOMAIN-SUFFIX,pptv.com,DIRECT +DOMAIN-SUFFIX,pubyun.com,DIRECT +DOMAIN-SUFFIX,qhimg.com,DIRECT +DOMAIN-SUFFIX,qianlong.com,DIRECT +DOMAIN-SUFFIX,qidian.com,DIRECT +DOMAIN-SUFFIX,qingdaonews.com,DIRECT +DOMAIN-SUFFIX,qiniu.com,DIRECT +DOMAIN-SUFFIX,qiniudn.com,DIRECT +DOMAIN-SUFFIX,qiushibaike.com,DIRECT +DOMAIN-SUFFIX,qiyi.com,DIRECT +DOMAIN-SUFFIX,qiyipic.com,DIRECT +DOMAIN-SUFFIX,qqmail.com,DIRECT +DOMAIN-SUFFIX,qstatic.com,DIRECT +DOMAIN-SUFFIX,qunar.com,DIRECT +DOMAIN-SUFFIX,qunarzz.com,DIRECT +DOMAIN-SUFFIX,qvbuy.com,DIRECT +DOMAIN-SUFFIX,renren.com,DIRECT +DOMAIN-SUFFIX,renrendai.com,DIRECT +DOMAIN-SUFFIX,rrfmn.com,DIRECT +DOMAIN-SUFFIX,rrimg.com,DIRECT +DOMAIN-SUFFIX,sanguosha.com,DIRECT +DOMAIN-SUFFIX,sdo.com,DIRECT +DOMAIN-SUFFIX,sina.com,DIRECT +DOMAIN-SUFFIX,sinaapp.com,DIRECT +DOMAIN-SUFFIX,sinaedge.com,DIRECT +DOMAIN-SUFFIX,sinajs.com,DIRECT +DOMAIN-SUFFIX,skycn.com,DIRECT +DOMAIN-SUFFIX,smzdm.com,DIRECT +DOMAIN-SUFFIX,sogou.com,DIRECT +DOMAIN-SUFFIX,sohu.com,DIRECT +DOMAIN-SUFFIX,soku.com,DIRECT +DOMAIN-SUFFIX,solidot.org,DIRECT +DOMAIN-SUFFIX,soso.com,DIRECT +DOMAIN-SUFFIX,soufun.com,DIRECT +DOMAIN-SUFFIX,soufunimg.com,DIRECT +DOMAIN-SUFFIX,staticfile.org,DIRECT +DOMAIN-SUFFIX,staticsdo.com,DIRECT +DOMAIN-SUFFIX,suning.com,DIRECT +DOMAIN-SUFFIX,szzfgjj.com,DIRECT +DOMAIN-SUFFIX,tanx.com,DIRECT +DOMAIN-SUFFIX,tbcache.com,DIRECT +DOMAIN-SUFFIX,tdimg.com,DIRECT +DOMAIN-SUFFIX,tencent.com,DIRECT +DOMAIN-SUFFIX,tenpay.com,DIRECT +DOMAIN-SUFFIX,tgbus.com,DIRECT +DOMAIN-SUFFIX,thawte.com,DIRECT +DOMAIN-SUFFIX,tiancity.com,DIRECT +DOMAIN-SUFFIX,tianyaui.com,DIRECT +DOMAIN-SUFFIX,tiexue.net,DIRECT +DOMAIN-SUFFIX,tmall.com,DIRECT +DOMAIN-SUFFIX,tmcdn.net,DIRECT +DOMAIN-SUFFIX,tom.com,DIRECT +DOMAIN-SUFFIX,tomonline-inc.com,DIRECT +DOMAIN-SUFFIX,tuan800.com,DIRECT +DOMAIN-SUFFIX,tuan800.net,DIRECT +DOMAIN-SUFFIX,tuanimg.com,DIRECT +DOMAIN-SUFFIX,tudou.com,DIRECT +DOMAIN-SUFFIX,tudouui.com,DIRECT +DOMAIN-SUFFIX,tuniu.com,DIRECT +DOMAIN-SUFFIX,u148.net,DIRECT +DOMAIN-SUFFIX,u17.com,DIRECT +DOMAIN-SUFFIX,ubuntu.com,DIRECT +DOMAIN-SUFFIX,ucjoy.com,DIRECT +DOMAIN-SUFFIX,uni-marketers.com,DIRECT +DOMAIN-SUFFIX,unionpay.com,DIRECT +DOMAIN-SUFFIX,unionpaysecure.com,DIRECT +DOMAIN-SUFFIX,upaiyun.com,DIRECT +DOMAIN-SUFFIX,upyun.com,DIRECT +DOMAIN-SUFFIX,uusee.com,DIRECT +DOMAIN-SUFFIX,uuu9.com,DIRECT +DOMAIN-SUFFIX,vaikan.com,DIRECT +DOMAIN-SUFFIX,vancl.com,DIRECT +DOMAIN-SUFFIX,vcimg.com,DIRECT +DOMAIN-SUFFIX,verycd.com,DIRECT +DOMAIN-SUFFIX,wandoujia.com,DIRECT +DOMAIN-SUFFIX,wdjimg.com,DIRECT +DOMAIN-SUFFIX,weibo.com,DIRECT +DOMAIN-SUFFIX,weiphone.com,DIRECT +DOMAIN-SUFFIX,weiyun.com,DIRECT +DOMAIN-SUFFIX,west263.com,DIRECT +DOMAIN-SUFFIX,wrating.com,DIRECT +DOMAIN-SUFFIX,wumii.com,DIRECT +DOMAIN-SUFFIX,xdcdn.net,DIRECT +DOMAIN-SUFFIX,xiachufang.com,DIRECT +DOMAIN-SUFFIX,xiami.com,DIRECT +DOMAIN-SUFFIX,xiami.net,DIRECT +DOMAIN-SUFFIX,xiaomi.com,DIRECT +DOMAIN-SUFFIX,xiaonei.com,DIRECT +DOMAIN-SUFFIX,xiazaiba.com,DIRECT +DOMAIN-SUFFIX,xici.net,DIRECT +DOMAIN-SUFFIX,xilu.com,DIRECT +DOMAIN-SUFFIX,xinhuanet.com,DIRECT +DOMAIN-SUFFIX,xinnet.com,DIRECT +DOMAIN-SUFFIX,xlpan.com,DIRECT +DOMAIN-SUFFIX,xnpic.com,DIRECT +DOMAIN-SUFFIX,xungou.com,DIRECT +DOMAIN-SUFFIX,xunlei.com,DIRECT +DOMAIN-SUFFIX,ydstatic.com,DIRECT +DOMAIN-SUFFIX,yesky.com,DIRECT +DOMAIN-SUFFIX,yeyou.com,DIRECT +DOMAIN-SUFFIX,yihaodian.com,DIRECT +DOMAIN-SUFFIX,yihaodianimg.com,DIRECT +DOMAIN-SUFFIX,yingjiesheng.com,DIRECT +DOMAIN-SUFFIX,yintai.com,DIRECT +DOMAIN-SUFFIX,yinyuetai.com,DIRECT +DOMAIN-SUFFIX,yiqifa.com,DIRECT +DOMAIN-SUFFIX,qingjie.me,DIRECT +DOMAIN-SUFFIX,yixun.com,DIRECT +DOMAIN-SUFFIX,ykimg.com,DIRECT +DOMAIN-SUFFIX,ynet.com,DIRECT +DOMAIN-SUFFIX,youdao.com,DIRECT +DOMAIN-SUFFIX,eqxiu.com,DIRECT +DOMAIN-SUFFIX,yougou.com,DIRECT +DOMAIN-SUFFIX,youku.com,DIRECT +DOMAIN-SUFFIX,yupoo.com,DIRECT +DOMAIN-SUFFIX,yy.com,DIRECT +DOMAIN-SUFFIX,zbjimg.com,DIRECT +DOMAIN-SUFFIX,zhaopin.com,DIRECT +DOMAIN-SUFFIX,zhi.hu,DIRECT +DOMAIN-SUFFIX,zhihu.com,DIRECT +DOMAIN-SUFFIX,zhimg.com,DIRECT +DOMAIN-SUFFIX,zhubajie.com,DIRECT +DOMAIN-SUFFIX,zongheng.com,DIRECT +DOMAIN-SUFFIX,v2ex.com,DIRECT +DOMAIN-SUFFIX,hi-pda.com,DIRECT +DOMAIN-SUFFIX,yhd.com,DIRECT +DOMAIN-SUFFIX,58cdn.com,DIRECT +DOMAIN-SUFFIX,avosapps.com,DIRECT +DOMAIN-SUFFIX,mob.com,DIRECT +DOMAIN-SUFFIX,same.com,DIRECT +DOMAIN-SUFFIX,toutiao.com,DIRECT +DOMAIN-SUFFIX,zaih.com,DIRECT +DOMAIN-SUFFIX,lantouzi.com,DIRECT +DOMAIN-SUFFIX,amap.com,DIRECT +DOMAIN-SUFFIX,haosou.com,DIRECT +DOMAIN-SUFFIX,huofu.com,DIRECT +DOMAIN-SUFFIX,5wei.com,DIRECT +DOMAIN-SUFFIX,travelrely.com,DIRECT +DOMAIN-SUFFIX,seekingalpha.com,DIRECT +DOMAIN-SUFFIX,appsflyer.com,DIRECT +DOMAIN-SUFFIX,nyt.com,Proxy +DOMAIN-SUFFIX,nytco.com,Proxy +DOMAIN-SUFFIX,nytimes.com,Proxy +DOMAIN-SUFFIX,nytimg.com,Proxy +DOMAIN-SUFFIX,nytstyle.com,Proxy +DOMAIN-SUFFIX,doubleclick.net,REJECT +DOMAIN-SUFFIX,googleadservices.com,REJECT + +DOMAIN-SUFFIX,actives.youku.com,REJECT +DOMAIN-SUFFIX,ad.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,atm.youku.com,REJECT +DOMAIN-SUFFIX,c.yes.youku.com,REJECT +DOMAIN-SUFFIX,lstat.youku.com,REJECT +DOMAIN-SUFFIX,lvip.youku.com,REJECT +DOMAIN-SUFFIX,p.l.youku.com,REJECT +DOMAIN-SUFFIX,r.l.youku.com,REJECT +DOMAIN-SUFFIX,stat.youku.com,REJECT +DOMAIN-SUFFIX,static.lstat.youku.com,REJECT +DOMAIN-SUFFIX,atm.youku.com,REJECT +DOMAIN-SUFFIX,ad.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,statis.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,ad.api.3g.youku.com,REJECT +DOMAIN-SUFFIX,count.atm.youku.com,REJECT + + +#DOMAIN-SUFFIX,gtimg.com,DIRECT + + +# Toutiao +#DOMAIN,ic.snssdk.com,REJECT + + +# Zhuishu +DOMAIN-SUFFIX,zhuishushenqi.com,DIRECT + +# Appzapp By @冯冯ryan_ +DOMAIN-KEYWORD,appzapp,DIRECT + +# CDN +DOMAIN-KEYWORD,ccgslb,DIRECT +DOMAIN-KEYWORD,chinacache,DIRECT + +# Duolinguo +DOMAIN-KEYWORD,duolingo,DIRECT + +# Synology +DOMAIN-KEYWORD,0x,DIRECT + +# Moke +DOMAIN-KEYWORD,moke,DIRECT +DOMAIN-KEYWORD,sinaimg,DIRECT + +# 12306 +DOMAIN-KEYWORD,steam,DIRECT +DOMAIN-KEYWORD,alipay,DIRECT +DOMAIN-KEYWORD,360buy,DIRECT +DOMAIN-KEYWORD,alimama,DIRECT + + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! + + +DOMAIN,g.co,Proxy +DOMAIN,goo.gl,Proxy + + +DOMAIN,app.adjust.com,Proxy +DOMAIN,api.weather.com,Proxy + +# Snapchat +DOMAIN,data.flurry.com,Proxy +DOMAIN,app.snapchat.com,Proxy + + +# 如果您喜欢,请在关注或转发时标注作者名称及地址,感谢您的支持! +DOMAIN-SUFFIX,ggpht.com,Proxy +DOMAIN-SUFFIX,fb.com,Proxy + +# Amazon +DOMAIN-SUFFIX,amazon.com,Proxy +DOMAIN-SUFFIX,amazonaws.com,Proxy +DOMAIN-SUFFIX,glue-static.s3-external-3.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3-eu-west-1.amazonaws.com,Proxy +DOMAIN-SUFFIX,s3.amazonaws.com,Proxy +DOMAIN-SUFFIX,images-amazon.com,Proxy +DOMAIN-SUFFIX,ssl-images-amazon.com,Proxy + +# TWITCH +DOMAIN-SUFFIX,ioam.de,Proxy + + +# KUVVA +DOMAIN-SUFFIX,kuvva.com,Proxy +DOMAIN-SUFFIX,twimg.com,Proxy +DOMAIN-SUFFIX,edgekey.net,Proxy + +# Line By @pikatse +DOMAIN-SUFFIX,line-cdn.net,Proxy +DOMAIN-SUFFIX,line.me,Proxy,force-remote-dns +DOMAIN-SUFFIX,line.naver.jp,Proxy,force-remote-dns +DOMAIN-SUFFIX,line-apps.com,Proxy,force-remote-dns + +# VOA +DOMAIN-SUFFIX,voacantonese.com,Proxy +DOMAIN-SUFFIX,voachinese.com,Proxy +DOMAIN-SUFFIX,voachineseblog.com,Proxy +DOMAIN-SUFFIX,voagd.com,Proxy +DOMAIN-SUFFIX,voanews.com,Proxy +DOMAIN-SUFFIX,voatibetan.com,Proxy +DOMAIN-SUFFIX,cn.voa.mobi,Proxy + +#FB +DOMAIN-SUFFIX,fbcdn.net,Proxy +DOMAIN-SUFFIX,t.co,Proxy +DOMAIN-SUFFIX,ggpht,Proxy +DOMAIN-SUFFIX,googleapis.com,Proxy +DOMAIN-SUFFIX,cdninstagram.com,Proxy +DOMAIN-SUFFIX,instagram.com,Proxy +DOMAIN-SUFFIX,tumblr,Proxy +DOMAIN-SUFFIX,yahoo.com,Proxy +DOMAIN-SUFFIX,wikipedia.org,Proxy +# Spotify By @LUDOVICFM +DOMAIN-SUFFIX,scorecardresearch.com,Proxy +DOMAIN-KEYWORD,scdn,Proxy +DOMAIN-KEYWORD,moatads,Proxy + +DOMAIN-KEYWORD,akamaistream,Proxy + +# TVB +DOMAIN-KEYWORD,tvb.com,Proxy + +# OTH +DOMAIN-KEYWORD,wikileaks,Proxy +DOMAIN-KEYWORD,wikimapia,Proxy +DOMAIN-KEYWORD,epochtimes,Proxy +DOMAIN-KEYWORD,uncyclopedia,Proxy +DOMAIN-KEYWORD,tibet,Proxy +DOMAIN-KEYWORD,fgmtv,Proxy +DOMAIN-KEYWORD,geocities,Proxy +DOMAIN-KEYWORD,savetibet,Proxy +DOMAIN-KEYWORD,ntdtv,Proxy +DOMAIN-KEYWORD,falundafa,Proxy +DOMAIN-KEYWORD,taiwannation,Proxy +DOMAIN-KEYWORD,rangzen,Proxy +DOMAIN-KEYWORD,bbc,Proxy +DOMAIN-KEYWORD,bloomberg,Proxy +DOMAIN-KEYWORD,appledaily,Proxy +DOMAIN-KEYWORD,chinaaid,Proxy +DOMAIN-KEYWORD,popyard,Proxy +DOMAIN-KEYWORD,raidcall,Proxy +DOMAIN-SUFFIX,qq.com,DIRECT + +# BLOGSPOT +DOMAIN-KEYWORD,blogspot,Proxy + + +DOMAIN-KEYWORD,akamaihd,Proxy,no-resolve +DOMAIN-KEYWORD,google,Proxy,force-remote-dns +DOMAIN-KEYWORD,facebook,Proxy,force-remote-dns +DOMAIN-KEYWORD,youtube,Proxy,force-remote-dns + +DOMAIN-KEYWORD,twitter,Proxy,force-remote-dns +DOMAIN-KEYWORD,gmail,Proxy,force-remote-dns +DOMAIN-KEYWORD,instagram,Proxy,force-remote-dns +DOMAIN-KEYWORD,vimeo,Proxy,force-remote-dns +DOMAIN-KEYWORD,deviantart,Proxy,force-remote-dns +DOMAIN-KEYWORD,twitch,Proxy,force-remote-dns +DOMAIN-KEYWORD,jtvnw,Proxy,force-remote-dns +DOMAIN-KEYWORD,ttvnw,Proxy,force-remote-dns +DOMAIN-KEYWORD,dropbox,Proxy,force-remote-dns +DOMAIN-KEYWORD,telegram,Proxy,force-remote-dns +DOMAIN-KEYWORD,spotify,Proxy,force-remote-dns + +DOMAIN,dc.letv.com,REJECT +DOMAIN,ark.letv.com,REJECT +# Telegram +IP-CIDR,91.108.56.0/22,Proxy,no-resolve +IP-CIDR,91.108.4.0/22,Proxy,no-resolve +IP-CIDR,109.239.140.0/24,Proxy,no-resolve +IP-CIDR,149.154.160.0/20,Proxy,no-resolve +IP-CIDR,101.227.14.0/24,REJECT,no-resolve +IP-CIDR,101.227.12.0/24,REJECT,no-resolve +IP-CIDR,111.63.135.146/32,REJECT,no-resolve +IP-CIDR,111.206.22.0/24,REJECT,no-resolve +IP-CIDR,121.251.255.237/32,REJECT,no-resolve +IP-CIDR,123.125.117.0/24,REJECT,no-resolve +IP-CIDR,123.125.118.0/24,REJECT,no-resolve +#IP-CIDR,111.206.13.0/24,REJECT,no-resolve + + +# LAN +IP-CIDR,10.0.0.0/8,DIRECT +IP-CIDR,100.64.0.0/10,DIRECT +IP-CIDR,127.0.0.0/8,DIRECT +IP-CIDR,172.16.0.0/12,DIRECT +IP-CIDR,192.168.0.0/16,DIRECT +IP-CIDR,169.254.0.0.0/16,DIRECT +IP-CIDR,17.0.0.0/8,DIRECT +GEOIP, CN, DIRECT +FINAL, Proxy diff --git a/Surf/thanks.txt b/Surf/thanks.txt new file mode 100644 index 0000000..54c52ea --- /dev/null +++ b/Surf/thanks.txt @@ -0,0 +1,71 @@ +This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). +libsodium +Copyright (c) 2013-2015 +Frank Denis +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +==================================================================== +lwIP +Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +This file is part of the lwIP TCP/IP stack. +Author: Adam Dunkels + +==================================================================== +MMDB-Swift +Author + +Lex Tang (Twitter: @lexrus) + +License +MMDB-Swift is available under the Apache License Version 2.0. See the LICENSE file for more info. +The GeoLite2 databases are distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. + +==================================================================== +NEKit +Author + +Copyright (c) 2016, Zhuhao Wang +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +* Neither the name of NEKit nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +==================================================================== +libkcp FEC enhanced KCP session library for iOS/Android in C++ +The MIT License (MIT) + +Copyright (c) 2016 Daniel Fu + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Surf/zh-Hans.lproj/InfoPlist.strings b/Surf/zh-Hans.lproj/InfoPlist.strings new file mode 100644 index 0000000..038c3f5 --- /dev/null +++ b/Surf/zh-Hans.lproj/InfoPlist.strings @@ -0,0 +1,8 @@ +/* + InfoPlist.strings + Surf + + Created by abigt on 2017/8/3. + Copyright © 2017年 A.BIG.T. All rights reserved. +*/ +CFBundleDisplayName = "西游"; diff --git a/Surf/zh-Hans.lproj/LaunchScreen.strings b/Surf/zh-Hans.lproj/LaunchScreen.strings new file mode 100644 index 0000000..834948a --- /dev/null +++ b/Surf/zh-Hans.lproj/LaunchScreen.strings @@ -0,0 +1,6 @@ + +/* Class = "UILabel"; text = " A.BIG.T Copyright © 2016-2017 "; ObjectID = "8ie-xW-0ye"; */ +"8ie-xW-0ye.text" = " A.BIG.T 版权所有 © 2016-2017 "; + +/* Class = "UILabel"; text = "Surfing"; ObjectID = "kId-c2-rCX"; */ +"kId-c2-rCX.text" = "Surfing"; diff --git a/Surf/zh-Hans.lproj/Localizable.strings b/Surf/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..62feae2 --- /dev/null +++ b/Surf/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,95 @@ +/* + Localizable.strings + Surf + + Created by abigt on 2017/8/3. + Copyright © 2017年 A.BIG.T. All rights reserved. +*/ + + +"Status" = "状态"; +"Stop" = "停止"; +"Disconnect" = "未连接"; +"Please Try Again" = "请重试"; +"Connected" = "已连接"; +"Connecting" = "链接中"; +"Disconnecting" = "断开中"; +"Reasserting" = "暂停"; +"Switch" = "开关"; +"Please add Proxy" = "请添加节点"; +"Config not Found,Please Add" = "未找到配置"; +"No Proxy Found" = "请添加节点"; +"Please Manual/QrCode Add Proxy" = "手工/扫描二维码添加"; +"Load Profile Error:" = "加载配置错误:"; +"Proxy Server" = "节点"; +"Chain Proxy" = "节点链"; +"Update A.BIG.T Cloud error,please try again" = "加载错误"; +"Type" = "类型"; +"Note:if enable TLS,Server value must domain name" = "Note:TLS 需要验证服务器证书"; +"Server" = "地址"; +"Port" = "端口"; +"Username" = "用户"; +"Password" = "密码"; +"TLS" = "TLS"; +"Proxy Config" = "编辑节点"; +"PROXY" = "代理"; +"Config Invalid!" = "信息无效,请重试"; +"Empty Password" = "密码不能为空"; +"NAME" = "标签"; +"PROXY" = "节点"; +"MISC" = "其他"; +"paramter" = "参数"; +"Cancel" = "取消"; +"Alert" = "提示"; +"Please Select Proxy Type" = "请选择类型"; +"One Time Auth" = "一次认证"; +"server address or ip" = "域名或者IP"; +"server port" = "端口"; +//"KCPTUN" , +"KCPTUN parameter" = "KCPTUN参数"; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +// +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +//"Please Try Again" = ""; +// +//"Please Try Again" = ""; +"Today Widget Flow" = "插件流量图"; +"Show Country Flag" = "显示国旗"; +"Today Widget Select" = "插件配置"; +"Request History" = "保存访问记录"; +"iCloud sync" = "Cloud备份"; +"Proxy Chain" = "Proxy Chain"; +"Theme" = "样式"; +"Advance" = "高级"; +"Purchase" = "购买功能"; +"Clean Cache" = "清除缓存"; +"Config Sample View" = "规则样例"; +"Config Manual Chinese Edition" = "规则中文说明"; +"Follow us on Twitter" = "关注推特"; +"Rate/Review On AppStore" = "好评"; +"Acknowledge" = "致谢"; +"Recent Requests" = "最近请求"; +"Rule Test Results" = "规则缓存"; +"Sessions" = "历史记录"; +"Help" = "帮助"; +"Rules" = "规则"; +"Analyze" = "分析"; +"Version " = "版本 "; +" (Build " = " (发布 "; +"Session Not Start" = "服务没有开启"; +"Session Running" = "服务已经开启,请稍后再试"; +"Disconnect On Sleep" = "睡眠断开VPN"; diff --git a/Surf/zh-Hans.lproj/Main.strings b/Surf/zh-Hans.lproj/Main.strings new file mode 100644 index 0000000..4e734f9 --- /dev/null +++ b/Surf/zh-Hans.lproj/Main.strings @@ -0,0 +1,225 @@ + +/* Class = "UILabel"; text = "TLS"; ObjectID = "09T-1f-Cyu"; */ +"09T-1f-Cyu.text" = "TLS"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "0CT-rs-Gae"; */ +"0CT-rs-Gae.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "0yJ-K4-y7m"; */ +"0yJ-K4-y7m.text" = "Title"; + +/* Class = "UIButton"; normalTitle = "Scan Qrcode Add"; ObjectID = "1Oo-50-jh8"; */ +"1Oo-50-jh8.normalTitle" = "扫描二维码"; + +/* Class = "UILabel"; text = "Notify"; ObjectID = "2Fb-W4-DT7"; */ +"2Fb-W4-DT7.text" = "Notify"; + +/* Class = "UITabBarItem"; title = "Item"; ObjectID = "3N7-Q8-YFo"; */ +"3N7-Q8-YFo.title" = "Item"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "41s-3R-nBj"; */ +"41s-3R-nBj.text" = "Title"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "4Ig-af-AvN"; */ +"4Ig-af-AvN.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "4iw-vT-QFw"; */ +"4iw-vT-QFw.text" = "Subtitle"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[0] = "APP"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[0]" = "应用"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[1] = "SUFFIX"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[1]" = "域名后缀"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[2] = "KEYWORD"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[2]" = "关键字"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[3] = "IP"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[3]" = "IP"; + +/* Class = "UISegmentedControl"; 5UT-7H-Ysl.segmentTitles[4] = "GEOIP"; ObjectID = "5UT-7H-Ysl"; */ +"5UT-7H-Ysl.segmentTitles[4]" = "GEOIP"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "5dp-7x-GC6"; */ +"5dp-7x-GC6.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Policy"; ObjectID = "5ix-Nm-68p"; */ +"5ix-Nm-68p.text" = "策略"; + +/* Class = "UILabel"; text = "Verbose"; ObjectID = "6Mm-db-dZz"; */ +"6Mm-db-dZz.text" = "Verbose"; + +/* Class = "UITextField"; placeholder = "require"; ObjectID = "7ev-xI-gWh"; */ +"7ev-xI-gWh.placeholder" = "必须"; + +/* Class = "UILabel"; text = "Type/HTTP/Socks5"; ObjectID = "8CL-uh-vWc"; */ +"8CL-uh-vWc.text" = "Type/HTTP/Socks5"; + +/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "9Xx-3o-qLS"; */ +"9Xx-3o-qLS.normalTitle" = "链接"; + +/* Class = "UIButton"; normalTitle = "Show Qrcode Image"; ObjectID = "9gK-jB-2te"; */ +"9gK-jB-2te.normalTitle" = "显示节点二维码"; + +/* Class = "UILabel"; text = "Proxy Name"; ObjectID = "A8I-dI-Z4j"; */ +"A8I-dI-Z4j.text" = "Proxy Name"; + +/* Class = "UITabBarItem"; title = "Rule"; ObjectID = "AqA-co-w8V"; */ +"AqA-co-w8V.title" = "Rule"; + +/* Class = "UILabel"; text = "CN"; ObjectID = "Csd-RI-rAl"; */ +"Csd-RI-rAl.text" = "CN"; + +/* Class = "UILabel"; text = "192.168.1.7 1080"; ObjectID = "E9y-1J-XbE"; */ +"E9y-1J-XbE.text" = "192.168.1.7 1080"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "IYN-Qk-G9g"; */ +"IYN-Qk-G9g.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Advance"; ObjectID = "KVp-vM-c1e"; */ +"KVp-vM-c1e.text" = "高级"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "Kr3-Pr-Vem"; */ +"Kr3-Pr-Vem.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "MSV-L8-XGM"; */ +"MSV-L8-XGM.text" = "Title"; + +/* Class = "UISegmentedControl"; NiM-y4-ptz.segmentTitles[0] = "http"; ObjectID = "NiM-y4-ptz"; */ +"NiM-y4-ptz.segmentTitles[0]" = "http"; + +/* Class = "UISegmentedControl"; NiM-y4-ptz.segmentTitles[1] = "socks5"; ObjectID = "NiM-y4-ptz"; */ +"NiM-y4-ptz.segmentTitles[1]" = "socks5"; + +/* Class = "UILabel"; text = "Acknowledge"; ObjectID = "QDO-BF-ann"; */ +"QDO-BF-ann.text" = "状态"; + +/* Class = "UITabBarItem"; title = "Switch"; ObjectID = "TLs-Ix-8w5"; */ +"TLs-Ix-8w5.title" = "切换"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Tmf-Uq-kDa"; */ +"Tmf-Uq-kDa.text" = "Title"; + +/* Class = "UILabel"; text = "Proxy Group"; ObjectID = "UGk-Vy-vu2"; */ +"UGk-Vy-vu2.text" = "代理组"; + +/* Class = "UILabel"; text = "Policy"; ObjectID = "aI8-X5-bJi"; */ +"aI8-X5-bJi.text" = "策略"; + +/* Class = "UITextField"; placeholder = "require"; ObjectID = "bjD-J7-VuI"; */ +"bjD-J7-VuI.placeholder" = "必须"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "bvt-dM-dgh"; */ +"bvt-dM-dgh.text" = "Label"; + +/* Class = "UILabel"; text = "notify"; ObjectID = "c6s-BB-TQH"; */ +"c6s-BB-TQH.text" = "notify"; + +/* Class = "UISegmentedControl"; caa-Zb-PbE.segmentTitles[0] = "TCP"; ObjectID = "caa-Zb-PbE"; */ +"caa-Zb-PbE.segmentTitles[0]" = "TCP"; + +/* Class = "UISegmentedControl"; caa-Zb-PbE.segmentTitles[1] = "Socks5"; ObjectID = "caa-Zb-PbE"; */ +"caa-Zb-PbE.segmentTitles[1]" = "Socks5"; + +/* Class = "UISegmentedControl"; caa-Zb-PbE.segmentTitles[2] = "HTTP"; ObjectID = "caa-Zb-PbE"; */ +"caa-Zb-PbE.segmentTitles[2]" = "HTTP"; + +/* Class = "UILabel"; text = "TLS"; ObjectID = "dP4-DJ-vDj"; */ +"dP4-DJ-vDj.text" = "TLS"; + +/* Class = "UITabBarItem"; title = "Item"; ObjectID = "dhh-OL-2ta"; */ +"dhh-OL-2ta.title" = "Item"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "esK-TU-CLm"; */ +"esK-TU-CLm.text" = "Title"; + +/* Class = "UILabel"; text = "Trace"; ObjectID = "fKC-AV-PRY"; */ +"fKC-AV-PRY.text" = "Trace"; + +/* Class = "UILabel"; text = "Info"; ObjectID = "fWx-fH-7hC"; */ +"fWx-fH-7hC.text" = "Info"; + +/* Class = "UILabel"; text = "If enable, all proxys will auto merge to proxy Group"; ObjectID = "gEQ-SU-jXR"; */ +"gEQ-SU-jXR.text" = "If enable, all proxys will auto merge to proxy Group"; + +/* Class = "UILabel"; text = "Buy Record"; ObjectID = "gxR-0n-kUL"; */ +"gxR-0n-kUL.text" = "Buy Record"; + +/* Class = "UILabel"; text = "L"; ObjectID = "h2l-39-STS"; */ +"h2l-39-STS.text" = "L"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "hc4-Kz-yBW"; */ +"hc4-Kz-yBW.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "hhs-PQ-Jra"; */ +"hhs-PQ-Jra.text" = "Label"; + +/* Class = "UIButton"; normalTitle = "Cancel"; ObjectID = "hiW-eo-bVS"; */ +"hiW-eo-bVS.normalTitle" = "取消"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "irE-gC-9HN"; */ +"irE-gC-9HN.text" = "Title"; + +/* Class = "UILabel"; text = "Status"; ObjectID = "j9O-5L-RzG"; */ +"j9O-5L-RzG.text" = "状态"; + +/* Class = "UILabel"; text = "notify"; ObjectID = "jL4-cZ-Woj"; */ +"jL4-cZ-Woj.text" = "notify"; + +/* Class = "UILabel"; text = "Proxy Name"; ObjectID = "jdE-XB-ddC"; */ +"jdE-XB-ddC.text" = "代理名称"; + +/* Class = "UITextView"; text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."; ObjectID = "ksj-Hi-416"; */ +"ksj-Hi-416.text" = "加载中"; + +/* Class = "UITextField"; placeholder = "Configuration Name"; ObjectID = "nmN-VT-pZg"; */ +"nmN-VT-pZg.placeholder" = "标签"; + +/* Class = "UITextField"; placeholder = "require"; ObjectID = "o0C-oO-0Hj"; */ +"o0C-oO-0Hj.placeholder" = "必须"; + +/* Class = "UILabel"; text = "L"; ObjectID = "o7k-nx-t9o"; */ +"o7k-nx-t9o.text" = "L"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "oLD-3B-mCd"; */ +"oLD-3B-mCd.text" = "Title"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "oNq-RI-QOE"; */ +"oNq-RI-QOE.text" = "Title"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "oXh-1m-G0w"; */ +"oXh-1m-G0w.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "pMl-By-U26"; */ +"pMl-By-U26.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "pea-EA-oWj"; */ +"pea-EA-oWj.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "sAk-AQ-pEw"; */ +"sAk-AQ-pEw.text" = "Title"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "sm3-gp-c4x"; */ +"sm3-gp-c4x.title" = "控制器"; + +/* Class = "UILabel"; text = "Warning"; ObjectID = "ssz-DM-XvQ"; */ +"ssz-DM-XvQ.text" = "警告"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "wGm-XI-tU9"; */ +"wGm-XI-tU9.text" = "Title"; + +/* Class = "UIButton"; normalTitle = "Album"; ObjectID = "wYf-ha-Uyi"; */ +"wYf-ha-Uyi.normalTitle" = "照片库"; + +/* Class = "UITableViewController"; title = "Proxy Group"; ObjectID = "wcT-oI-VtM"; */ +"wcT-oI-VtM.title" = "代理组"; + +/* Class = "UILabel"; text = "Log level "; ObjectID = "xNm-4u-KXC"; */ +"xNm-4u-KXC.text" = "日志等级"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "yyg-UZ-xh4"; */ +"yyg-UZ-xh4.text" = "Title"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "zz2-Zb-R72"; */ +"zz2-Zb-R72.text" = "Title"; diff --git a/Surf/zh-Hans.lproj/ana.strings b/Surf/zh-Hans.lproj/ana.strings new file mode 100644 index 0000000..979d176 --- /dev/null +++ b/Surf/zh-Hans.lproj/ana.strings @@ -0,0 +1,153 @@ + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "0L8-Tk-DNu"; */ +"0L8-Tk-DNu.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "0et-Ao-21C"; */ +"0et-Ao-21C.text" = "上传:"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "1VX-Sh-TYI"; */ +"1VX-Sh-TYI.text" = "Label"; + +/* Class = "UILabel"; text = "Rule Testing"; ObjectID = "1qA-Qp-a7f"; */ +"1qA-Qp-a7f.text" = "Rule Testing"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "3I0-eL-4WW"; */ +"3I0-eL-4WW.text" = "Title"; + +/* Class = "UITabBarItem"; title = "Analyze"; ObjectID = "49F-E9-XLp"; */ +"49F-E9-XLp.title" = "Analyze"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "6Lw-p1-kfH"; */ +"6Lw-p1-kfH.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Rule Testing"; ObjectID = "70x-fn-iXp"; */ +"70x-fn-iXp.text" = "Rule Testing"; + +/* Class = "UILabel"; text = "Transfer"; ObjectID = "73y-Av-kdv"; */ +"73y-Av-kdv.text" = "Transfer"; + +/* Class = "UILabel"; text = "Timing"; ObjectID = "7gj-VJ-LEI"; */ +"7gj-VJ-LEI.text" = "时间"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "EAT-ec-s8R"; */ +"EAT-ec-s8R.text" = "Download:"; + +/* Class = "UILabel"; text = "L"; ObjectID = "Ewi-TR-1PS"; */ +"Ewi-TR-1PS.text" = "L"; + +/* Class = "UILabel"; text = "REquest Header"; ObjectID = "GHc-x0-4Qk"; */ +"GHc-x0-4Qk.text" = "REquest Header"; + +/* Class = "UITextView"; text = "logo info "; ObjectID = "GJv-lC-J9C"; */ +"GJv-lC-J9C.text" = "logo info "; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "IO4-xz-7eJ"; */ +"IO4-xz-7eJ.text" = "Upload:"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "ITh-r5-rR5"; */ +"ITh-r5-rR5.text" = "Label"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "LWX-Xx-cfD"; */ +"LWX-Xx-cfD.text" = "Subtitle"; + +/* Class = "UILabel"; text = "L"; ObjectID = "Lfy-4E-S1f"; */ +"Lfy-4E-S1f.text" = "L"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "Lpj-9Y-NTI"; */ +"Lpj-9Y-NTI.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "MYi-Y5-T5f"; */ +"MYi-Y5-T5f.text" = "Label"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Pfh-fC-BR4"; */ +"Pfh-fC-BR4.text" = "Title"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Pjb-3z-tnO"; */ +"Pjb-3z-tnO.text" = "Title"; + +/* Class = "UILabel"; text = "Timing"; ObjectID = "QMh-ZJ-lae"; */ +"QMh-ZJ-lae.text" = "Timing"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "SkG-8a-v2A"; */ +"SkG-8a-v2A.text" = "Download:"; + +/* Class = "UILabel"; text = "L"; ObjectID = "VEL-Zx-cI5"; */ +"VEL-Zx-cI5.text" = "L"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "XM1-Fu-wzo"; */ +"XM1-Fu-wzo.text" = "Download:"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "XMa-y4-cOQ"; */ +"XMa-y4-cOQ.text" = "Label"; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "Z7P-wu-wpo"; */ +"Z7P-wu-wpo.text" = "Upload:"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "Zrm-IS-WV9"; */ +"Zrm-IS-WV9.text" = "Title"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "aJ5-Vf-lrM"; */ +"aJ5-Vf-lrM.text" = "Download:"; + +/* Class = "UILabel"; text = "Upload:"; ObjectID = "bIh-Wc-3c3"; */ +"bIh-Wc-3c3.text" = "Upload:"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "emA-hx-ZeC"; */ +"emA-hx-ZeC.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Establish"; ObjectID = "f6c-qP-rRP"; */ +"f6c-qP-rRP.text" = "Establish"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "grS-rQ-WIL"; */ +"grS-rQ-WIL.text" = "Download:"; + +/* Class = "UILabel"; text = "IP Routing"; ObjectID = "h4d-xC-nbC"; */ +"h4d-xC-nbC.text" = "IP Routing"; + +/* Class = "UILabel"; text = "Transfer"; ObjectID = "hkO-Td-0gL"; */ +"hkO-Td-0gL.text" = "Transfer"; + +/* Class = "UILabel"; text = "REquest Header"; ObjectID = "k2l-uA-O8S"; */ +"k2l-uA-O8S.text" = "REquest Header"; + +/* Class = "UILabel"; text = "L"; ObjectID = "kdb-dn-pIx"; */ +"kdb-dn-pIx.text" = "L"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "kzj-nL-SJo"; */ +"kzj-nL-SJo.text" = "Subtitle"; + +/* Class = "UILabel"; text = "Traffice Usage"; ObjectID = "nyy-oa-eRH"; */ +"nyy-oa-eRH.text" = "流量"; + +/* Class = "UILabel"; text = "IP Routing"; ObjectID = "ozq-lF-gOx"; */ +"ozq-lF-gOx.text" = "路由"; + +/* Class = "UILabel"; text = "Subtitle"; ObjectID = "r8L-Ct-ivs"; */ +"r8L-Ct-ivs.text" = "Subtitle"; + +/* Class = "UILabel"; text = "L"; ObjectID = "s3c-D5-ePg"; */ +"s3c-D5-ePg.text" = "L"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "sJN-ng-to0"; */ +"sJN-ng-to0.text" = "Title"; + +/* Class = "UILabel"; text = "L"; ObjectID = "smB-zL-dVS"; */ +"smB-zL-dVS.text" = "L"; + +/* Class = "UILabel"; text = "Traffice Usage"; ObjectID = "srJ-C5-rL0"; */ +"srJ-C5-rL0.text" = "流量"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "wCF-yO-AEh"; */ +"wCF-yO-AEh.text" = "Title"; + +/* Class = "UILabel"; text = "Download:"; ObjectID = "wKI-Nd-XNA"; */ +"wKI-Nd-XNA.text" = "Download:"; + +/* Class = "UIButton"; normalTitle = "Delete All"; ObjectID = "wYD-Sb-iBf"; */ +"wYD-Sb-iBf.normalTitle" = "Delete All"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "wdN-fx-Hjg"; */ +"wdN-fx-Hjg.text" = "Title"; + +/* Class = "UILabel"; text = "Establish"; ObjectID = "yrc-rh-64Y"; */ +"yrc-rh-64Y.text" = "Establish"; diff --git a/Surf/zh-Hans.lproj/help.strings b/Surf/zh-Hans.lproj/help.strings new file mode 100644 index 0000000..7ed6720 --- /dev/null +++ b/Surf/zh-Hans.lproj/help.strings @@ -0,0 +1,54 @@ + +/* Class = "UIButton"; normalTitle = "Upgrade"; ObjectID = "0WS-dd-6zy"; */ +"0WS-dd-6zy.normalTitle" = "升级"; + +/* Class = "UILabel"; text = "0"; ObjectID = "776-u6-juV"; */ +"776-u6-juV.text" = "0"; + +/* Class = "UITextView"; text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."; ObjectID = "7ki-V5-eyJ"; */ +"7ki-V5-eyJ.text" = "加载中.."; + +/* Class = "UILabel"; text = "Acknowledge"; ObjectID = "8NQ-ib-iyf"; */ +"8NQ-ib-iyf.text" = "致谢"; + +/* Class = "UILabel"; text = "Enable"; ObjectID = "FeP-6c-EAC"; */ +"FeP-6c-EAC.text" = "开关"; + +/* Class = "UILabel"; text = "iCload sync"; ObjectID = "Jk7-3l-3ab"; */ +"Jk7-3l-3ab.text" = "iCload备份"; + +/* Class = "UITextField"; placeholder = "Domain Name"; ObjectID = "MXR-V9-RAx"; */ +"MXR-V9-RAx.placeholder" = "输入域名"; + +/* Class = "UILabel"; text = "Version 1.0 (build 100)"; ObjectID = "PG4-Hq-Xqj"; */ +"PG4-Hq-Xqj.text" = "Version 1.0 (build 100)"; + +/* Class = "UINavigationItem"; title = "Root View Controller"; ObjectID = "T12-u0-5JD"; */ +"T12-u0-5JD.title" = "Root View Controller"; + +/* Class = "UILabel"; text = "Enable GEOIP base ruler\nEnable FINAL ruler"; ObjectID = "UFS-Mu-wgH"; */ +"UFS-Mu-wgH.text" = "Enable GEOIP base ruler\nEnable FINAL ruler"; + +/* Class = "UITextView"; text = "sample"; ObjectID = "UHr-fR-rbx"; */ +"UHr-fR-rbx.text" = "例子"; + +/* Class = "UILabel"; text = "❤️"; ObjectID = "YIn-as-YM7"; */ +"YIn-as-YM7.text" = "❤️"; + +/* Class = "UITabBarItem"; title = "Help"; ObjectID = "YWX-8y-Enf"; */ +"YWX-8y-Enf.title" = "帮助"; + +/* Class = "UITableViewController"; title = "About"; ObjectID = "cT2-If-XNE"; */ +"cT2-If-XNE.title" = "关于"; + +/* Class = "UILabel"; text = "❤️"; ObjectID = "crt-Sf-BgH"; */ +"crt-Sf-BgH.text" = "❤️"; + +/* Class = "UILabel"; text = "0"; ObjectID = "hik-Yh-zX4"; */ +"hik-Yh-zX4.text" = "0"; + +/* Class = "UILabel"; text = "Acknowledge"; ObjectID = "qfl-kj-hcC"; */ +"qfl-kj-hcC.text" = "致谢"; + +/* Class = "UILabel"; text = "Title"; ObjectID = "sNQ-KS-TtS"; */ +"sNQ-KS-TtS.text" = "Title"; diff --git a/SurfToday-Bridging-Header.h b/SurfToday-Bridging-Header.h new file mode 100644 index 0000000..bcbc2e9 --- /dev/null +++ b/SurfToday-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +//#import diff --git a/SurfToday/Base.lproj/MainInterface.storyboard b/SurfToday/Base.lproj/MainInterface.storyboard new file mode 100644 index 0000000..5d2482b --- /dev/null +++ b/SurfToday/Base.lproj/MainInterface.storyboard @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + Ionicons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SurfToday/Info.plist b/SurfToday/Info.plist new file mode 100644 index 0000000..a00ba29 --- /dev/null +++ b/SurfToday/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + A.BIG.T + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIcons + + CFBundleIcons~ipad + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 4.0 + CFBundleSignature + ???? + CFBundleVersion + 805 + Fabric + + APIKey + + Kits + + + KitInfo + + KitName + Crashlytics + + + + NSExtension + + NSExtensionMainStoryboard + MainInterface + NSExtensionPointIdentifier + com.apple.widget-extension + + UIAppFonts + + ionicons.ttf + + + diff --git a/SurfToday/TodayViewController.swift b/SurfToday/TodayViewController.swift new file mode 100644 index 0000000..6982610 --- /dev/null +++ b/SurfToday/TodayViewController.swift @@ -0,0 +1,974 @@ +// +// TodayViewController.swift +// SurfToday +// +// Created by 孔祥波 on 16/2/9. +// Copyright © 2016年 abigt. All rights reserved. +// + +import UIKit +import NotificationCenter +import NetworkExtension +import SwiftyJSON +import DarwinCore +import SFSocket +import Crashlytics +import Fabric +import Charts +import XRuler +import Xcon + +class StatusConnectedCell:UITableViewCell { + @IBOutlet weak var configLabel: UILabel! + @IBOutlet weak var statusSwitch: UISwitch! + @IBOutlet weak var speedContainView:UIView! + @IBOutlet weak var downLabel: UILabel! + @IBOutlet weak var upLabel: UILabel! + + @IBOutlet weak var downSpeedLabel: UILabel! + @IBOutlet weak var upSpeedLabel: UILabel! + + + @IBOutlet weak var cellLabel: UILabel! + @IBOutlet weak var wifiLabel: UILabel! + + @IBOutlet weak var cellInfoLabel: UILabel! + @IBOutlet weak var wifiInfoLabel: UILabel! +} +class ProxyGroupCell:UITableViewCell { + @IBOutlet weak var configLabel: UILabel! + @IBOutlet weak var starView: UIImageView! + + +} +import Reachability +func version() ->Int { + return 10 +} +class TodayViewController: SFTableViewController, NCWidgetProviding { + + //@IBOutlet weak var tableView: UITableView! + var appearDate:Date = Date() + @IBOutlet var chartsView:ChartsView! + var config:String = "" + var proxyConfig:String = "" + var sysVersion = 10 //sysVersion() + var report:SFVPNStatistics = SFVPNStatistics.shared + var proxyGroup:ProxyGroupSettings! + var showServerHost = false + var lastTraffic:STTraffic = DataCounters("240.7.1.9") + var timer:Timer? + let dnsqueue:DispatchQueue = DispatchQueue(label: "com.abigt.dns") + var autoRedail = false + let reachability = Reachability()! + var charts:[Double] = [] + override init(style: UITableViewStyle) { + super.init(style: style) + prepareApp() + self.proxyGroup = ProxyGroupSettings.share + } + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + prepareApp() + self.proxyGroup = ProxyGroupSettings.share + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + prepareApp() + self.proxyGroup = ProxyGroupSettings.share + } + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if indexPath.row == 0 { + return 66.0 + }else { + return 44.0 + } + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + + if let ext = self.extensionContext { + if ext.widgetActiveDisplayMode == .expanded { + return displayCount() + }else { + let count = displayCount() + if count >= 2 { + return 2 + }else { + return 1 + } + } + } + + return 1 + + } + + func displayCount() -> Int{ + if proxyGroup.proxys.count < proxyGroup.widgetProxyCount { + return proxyGroup.proxys.count + 1 + }else { + return proxyGroup.widgetProxyCount + 1 + } + } + override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { + + if indexPath.row == 0 { + return nil + }else { + return indexPath + } + + // if indexPath.row == proxyGroup.proxys.count { + // return nil + // } + + } + func running() ->Bool { + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected { + return true + } + } + return false + } + func startStopToggled() { + + do { + let selectConf = ProxyGroupSettings.share.config + let result = try SFVPNManager.shared.startStopToggled(selectConf) + if !result { + Timer.scheduledTimer(timeInterval: 5.0, target: self + , selector: #selector(TodayViewController.registerStatus), userInfo: nil, repeats: false) +// SFVPNManager.shared.loadManager({[unowned self] (manager, error) in +// if let error = error { +// print(error.localizedDescription) +// }else { +// print("start/stop action") +// if self.autoRedail { +// self.startStopToggled() +// self.autoRedail = false +// } +// +// } +// }) + + } + + } catch let error{ + //SFVPNManager.shared.xpc() + print(error.localizedDescription) + } + + } + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + tableView.deselectRow(at: indexPath , animated: true) + let pIndex = indexPath.row - 1 + if pIndex == -1 { + return + } + if proxyGroup.selectIndex == pIndex { + showServerHost = !showServerHost + }else { + proxyGroup.selectIndex = pIndex + try! proxyGroup.save() + if running() { +// do { +// try SFVPNManager.shared.startStopToggled("") +// } catch let e { +// print(e.localizedDescription) +// } + + autoRedail = true + startStopToggled() + //changeProxy(index: pIndex) + } + } + + tableView.reloadData() + + } + func changeProxy(index:Int) { + let me = SFVPNXPSCommand.CHANGEPROXY.rawValue + "|\(index)" + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8) + { + do { + try session.sendProviderMessage(message) { [weak self] response in + guard let response = response else {return} + if let r = String.init(data: response, encoding: .utf8) , r == proxyChangedOK{ + + self!.alertMessageAction(r,complete: nil) + + } else { + self!.alertMessageAction("Failed to Change Proxy",complete: nil) + } + } + } catch let e as NSError{ + alertMessageAction("Failed to Change Proxy,reason \(e.description)",complete: nil) + } + + } + } + + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + // + var color = UIColor.darkText + if ProxyGroupSettings.share.wwdcStyle { + color = UIColor.white + } + + + // var count = 0 + // if proxyGroup.proxys.count < proxyGroup.widgetProxyCount { + // count = proxyGroup.proxys.count + // }else { + // count = proxyGroup.widgetProxyCount + // } + if indexPath.row == 0 { + let cell = tableView.dequeueReusableCell(withIdentifier: "main2") as! StatusConnectedCell + + var flag = false + if let m = SFVPNManager.shared.manager, m.isEnabled{ + if m.connection.status == .connected { + flag = true + } + } + // if sysVersion < 10 { + // if let _ = tunname(){ + // flag = true + // } + // } + cell.statusSwitch.isOn = flag + if flag { + print("connected ") + cell.downLabel.text = "\u{f35d}" + cell.downLabel.isHidden = false + cell.upLabel.isHidden = false + cell.downLabel.textColor = color//UIColor.whiteColor() + cell.upLabel.text = "\u{f366}" + cell.upLabel.textColor = color//UIColor.whiteColor() + let t = report.lastTraffice + cell.downSpeedLabel.text = t.toString(x: t.rx,label: "",speed: true) + cell.downSpeedLabel.textColor = color// UIColor.whiteColor() + cell.upSpeedLabel.text = t.toString(x: t.tx,label: "",speed: true) + cell.upSpeedLabel.textColor = color //UIColor.whiteColor() + cell.configLabel.textColor = color + cell.cellLabel.textColor = color + cell.cellInfoLabel.textColor = color + cell.wifiLabel.textColor = color + cell.wifiInfoLabel.textColor = color + + cell.cellLabel.isHidden = false + cell.cellLabel.text = "\u{f274}" + cell.cellInfoLabel.isHidden = false + cell.wifiLabel.isHidden = false + cell.wifiInfoLabel.isHidden = false + cell.wifiLabel.text = "\u{f25c}" + let x = report.cellTraffice.rx + report.cellTraffice.tx + let y = report.wifiTraffice.rx + report.wifiTraffice.tx + + cell.cellInfoLabel.text = report.cellTraffice.toString(x:x,label: "",speed: false) + cell.wifiInfoLabel.text = report.cellTraffice.toString(x:y,label: "",speed: false) + cell.speedContainView.isHidden = false + + cell.configLabel.isHidden = true + cell.downSpeedLabel.isHidden = false + cell.upSpeedLabel.isHidden = false + + + if reachability.isReachableViaWiFi { + cell.cellLabel.textColor = UIColor.gray + } + if reachability.isReachableViaWWAN { + cell.wifiLabel.textColor = UIColor.gray + } + }else { + print("not connected ") + cell.configLabel.isHidden = false + cell.speedContainView.isHidden = false + cell.statusSwitch.isHidden = false + cell.downLabel.isHidden = true + cell.upLabel.isHidden = true + cell.downSpeedLabel.isHidden = true + cell.upSpeedLabel.isHidden = true + + cell.cellLabel.isHidden = true + cell.cellInfoLabel.isHidden = true + cell.wifiLabel.isHidden = true + cell.wifiInfoLabel.isHidden = true + if ProxyGroupSettings.share.widgetProxyCount == 0 { + cell.configLabel.text = "Today Widget Disable" + + }else { + + let s = ProxyGroupSettings.share.config + + if !s.isEmpty { + + config = s + cell.configLabel.text = config //+ " Disconnect " //configLabel.text = config + }else { + cell.configLabel.text = "add config use A.BIG.T" + } + + } + cell.configLabel.textColor = color + } + + + return cell + }else { + + + let cell = tableView.dequeueReusableCell(withIdentifier: "proxy") as! ProxyGroupCell + let pIndex = indexPath.row - 1 + let proxy = proxyGroup.proxys[pIndex] + + var configString:String + var ts = "" + if !proxy.kcptun { + if proxy.tcpValue != 0 { + + if proxy.tcpValue > 0.0 { + ts = String(format: " %.0fms", proxy.tcpValue*1000) + //cell.subLabel.textColor = UIColor.cyanColor() + //print("111") + }else { + print("222") + ts = " Ping: Error" + //cell.subLabel.textColor = UIColor.redColor() + } + }else { + print("333") + } + }else { + ts = " kcptun" + } + + + if showServerHost { + configString = proxy.showString() + " " + proxy.serverAddress + ":" + proxy.serverPort + ts + }else { + if proxyGroup.showCountry { + configString = proxy.countryFlagFunc() + ts + }else { + configString = proxy.showString() + ts + } + + } + cell.configLabel.textColor = color + cell.configLabel.text = configString + + if proxyGroup.selectIndex == pIndex { + cell.starView.isHidden = false + }else { + cell.starView.isHidden = true + } + return cell + } + + } + + func showTraffice() ->Bool { + + if NSObject.version() >= 10 { + + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected || m.connection.status == .connecting{ + return true + } + }else { + return false + } + + }else { + if let m = SFVPNManager.shared.manager { + //profile + if m.connection.status == .connected || m.connection.status == .connecting{ + return true + }else { + return false + } + + }else { + return report.show + } + } + + return false + } + override func viewDidLoad() { + super.viewDidLoad() + Fabric.with([Crashlytics.self]) + Fabric.with([Answers.self]) + + try! reachability.startNotifier() + + + + if #available(iOSApplicationExtension 10.0, *) { + self.extensionContext!.widgetLargestAvailableDisplayMode = .expanded + } else { + updateSize() + } + if ProxyGroupSettings.share.widgetProxyCount == 0 { + removeTodayProfile() + + }else { + + profileStatus() + + } + + } + + + func profileStatus() { + NETunnelProviderManager.loadAllFromPreferences() { [weak self ](managers, error) -> Void in + if let managers = managers { + if managers.count > 0 { + + if let m = managers.first { + SFVPNManager.shared.manager = m + if m.connection.status == .connected { + //self!.statusCell!.statusSwitch.on = true + + + } + self!.registerStatus() + } + + + self!.tableView.reloadData() + } + + } + + } + + } + @IBAction func addProifile() { + //print("on") + if let m = SFVPNManager.shared.manager { + if m.connection.status == .connected { + //self.statusCell!.statusSwitch.on = true + } + self.registerStatus() + }else { + loadManager() + } + tableView.reloadData() + } + func reloadStatus(){ + //Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #, userInfo: <#T##Any?#>, repeats: <#T##Bool#>) + if NSObject.version() >= 10 { + timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(TodayViewController.trafficReport(_:)), userInfo: nil, repeats: true) + + }else { + + timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(TodayViewController.trafficReport(_:)), userInfo: nil, repeats: true) + } + } + func requestReportXPC() { + //print("000") + if let m = SFVPNManager.shared.manager , m.connection.status == .connected { + //print("\(m.protocolConfiguration)") + let date = NSDate() + + let me = SFVPNXPSCommand.FLOWS.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: .utf8) + + { + do { + try session.sendProviderMessage(message) { [weak self] response in + if response != nil { + self!.processData(data: response!) + } else { + //self!.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + //alertMessageAction("Failed to Get result ",complete: nil) + } + }else { + //alertMessageAction("Connection not Stated",complete: nil) + } + }else { + //alertMessageAction("message dont init",complete: nil) + tableView.reloadData() + } + + } + @objc func trafficReport(_ t:Timer) { + if let m = SFVPNManager.shared.manager, m.connection.status == .connected { + //requestReportXPC() + } + + guard let last = DataCounters("240.7.1.9") else {return} + report.cellTraffice.tx = last.wwanSent + report.cellTraffice.rx = last.wwanReceived + + report.wifiTraffice.tx = last.wiFiSent + report.wifiTraffice.rx = last.wiFiReceived + + + if reachability.isReachableViaWWAN { + report.lastTraffice.tx = last.wwanSent - lastTraffic.wwanSent + report.lastTraffice.rx = last.wwanReceived - lastTraffic.wwanReceived + }else { + report.lastTraffice.tx = last.wiFiSent - lastTraffic.wiFiSent + report.lastTraffice.rx = last.wiFiReceived - lastTraffic.wiFiReceived + } + + //NSLog("%ld,%ld", last.TunSent , lastTraffic.TunSent) + + + + + + charts.append(Double(report.lastTraffice.rx)) + print(charts) + if charts.count > 60 { + charts.remove(at: 0) + } + chartsView.update(charts) + + + lastTraffic = last + self.report.show = last.show + tableView.reloadData() + + } + + + + func updateSize(){ + proxyGroup = ProxyGroupSettings.share + try! proxyGroup.loadProxyFromFile() + var count = 1 + if proxyGroup.proxys.count < proxyGroup.widgetProxyCount { + count += proxyGroup.proxys.count + }else { + count += proxyGroup.widgetProxyCount + } + self.preferredContentSize = CGSize.init(width: 0, height: 44*CGFloat(count)) + } + @available(iOSApplicationExtension 10.0, *) + func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) { + proxyGroup = ProxyGroupSettings.share + try! proxyGroup.loadProxyFromFile() + var count = 1 + if proxyGroup.proxys.count < proxyGroup.widgetProxyCount { + count += proxyGroup.proxys.count + }else { + count += proxyGroup.widgetProxyCount + } + NSLog("max hegith %.02f", maxSize.height) + + + + switch activeDisplayMode { + case .expanded: + //self.preferredContentSize = CGSize.init(width:maxSize.width,height:260) + if proxyGroup.widgetFlow == false { + self.preferredContentSize = CGSize.init(width: 0, height: 44 * CGFloat(count) + 22 ) + }else { + self.preferredContentSize = CGSize.init(width: 0, height: 44 * CGFloat(count) + 22 + 150) + } + + case .compact: + //size = CGSize.init(width: 0, height: 44 * CGFloat(count)) + self.preferredContentSize = maxSize //CGSize.init(width: maxSize.width, height: 88.0) + + } + + self.tableView.reloadData() + } + override func viewWillAppear(_ animated: Bool) { + + super.viewWillAppear(animated) + + + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + appearDate = Date() + try! proxyGroup.loadProxyFromFile() + if proxyGroup.widgetFlow == false { + chartsView.isHidden = true + chartsView.frame.size.height = 0 + }else { + chartsView.isHidden = false + chartsView.frame.size.height = 150 + } + if proxyGroup.proxys.count > 0 { + //tcpScan() + } + reloadStatus() + + + + registerStatus() + tableView.reloadData() + } + override func viewDidDisappear(_ animated: Bool) { + + super.viewDidDisappear(animated) + if let t = timer { + t.invalidate() + } + let now = Date() + let ts = now.timeIntervalSince(appearDate) + Answers.logCustomEvent(withName: "Today", + customAttributes: [ + "Usage": ts, + + ]) + if let m = SFVPNManager.shared.manager { + NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: m.connection) + } + + } + + + func loadManager() { + //print("loadManager") + let vpnmanager = SFVPNManager.shared + if !vpnmanager.loading { + vpnmanager.loadManager() { + [weak self] (manager, error) -> Void in + if let _ = manager { + self!.tableView.reloadData() + self!.registerStatus() + vpnmanager.xpc() + } + } + }else { + print("vpnmanager loading") + } + + } + @objc func registerStatus(){ + if let m = SFVPNManager.shared.manager { + // Register to be notified of changes in the status. + NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: m.connection, queue: OperationQueue.main, using: { [weak self] notification in + + if let strong = self { + + if let o = notification.object { + if let c = o as? NEVPNConnection, c.status == .disconnected { + if strong.autoRedail { + strong.autoRedail = false + _ = try! SFVPNManager.shared.startStopToggled(ProxyGroupSettings.share.config) + } + + } + } + strong.tableView.reloadData() + } + + }) + }else { + + } + + } + + func removeTodayProfile(){ + NETunnelProviderManager.loadAllFromPreferences() { (managers, error) -> Void in + if let managers = managers { + if managers.count > 0 { + + var temp:NETunnelProviderManager? + let identify = "Surfing Today" + for mm in managers { + if mm.localizedDescription == identify { + temp = mm + } + } + //print(temp?.localizedDescription) + if let t = temp{ + t.removeFromPreferences(completionHandler: { (error) in + if let e = error{ + print(identify + " reomve error \(e.localizedDescription)") + }else { + print(identify + "removed ") + } + }) + } + + + + + } + + } + + } + + + } + + @IBAction func enable(_ sender: UISwitch) { + if NSObject.version() >= 10 { + + if let m = SFVPNManager.shared.manager { + let s = ProxyGroupSettings.share.config + if s.isEmpty{ + return + } + if m.isEnabled { + do { + _ = try SFVPNManager.shared.startStopToggled(s) + }catch let e as NSError { + print(e) + } + + }else { + //27440171 today widget error + let url = URL.init(string:"abigt://start" ) + self.extensionContext!.open(url!, completionHandler: { (s) in + if s { + print("good") + } + }) + //SFVPNManager.shared.enabledToggled(true) + } + + }else { + //statusCell!.configLabel.text = config + " please add profile" + //print("manager invalid") + loadManager() + sender.isOn = false + } + }else { + //9 只能用双profile + if ProxyGroupSettings.share.widgetProxyCount != 0 { + if let m = SFVPNManager.shared.manager { + let s = ProxyGroupSettings.share.config + if s.isEmpty{ + return + } + if m.isEnabled { + print("profile enabled ") + } + do { + _ = try SFVPNManager.shared.startStopToggled(s) + }catch let e as NSError { + print(e) + } + + }else { + //statusCell!.configLabel.text = config + " please add profile" + //print("manager invalid") + if sender.isOn { + loadManager() + sender.isOn = false + }else { + report.show = false + closeTun() + sender.isOn = false + } + + } + + }else { + + } + + } + + // tableView.reloadData() + } + func closeTun(){ + let queue = DispatchQueue(label:"com.abigt.socket")//, DISPATCH_QUEUE_CONCURRENT + + queue.async( execute: { + //let start = NSDate() + + + // Look up the host... + let socketfd: Int32 = socket(Int32(AF_INET), SOCK_STREAM, Int32(IPPROTO_TCP)) + let remoteHostName = "localhost" + //let port = Intp.serverPort + guard let remoteHost = gethostbyname2((remoteHostName as NSString).utf8String, AF_INET)else { + return + } + // Copy the info into the socket address structure... + + var remoteAddr = sockaddr_in() + remoteAddr.sin_family = sa_family_t(AF_INET) + bcopy(remoteHost.pointee.h_addr_list[0], &remoteAddr.sin_addr.s_addr, Int(remoteHost.pointee.h_length)) + remoteAddr.sin_port = UInt16(3128).bigEndian + + // Now, do the connection... + //https://swift.org/migration-guide/se-0107-migrate.html + let rc = withUnsafePointer(to: &remoteAddr) { + // Temporarily bind the memory at &addr to a single instance of type sockaddr. + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + connect(socketfd, $0, socklen_t(MemoryLayout.stride)) + } + } + + + if rc < 0 { + + }else { + + } + + let main = DispatchQueue.main + main.async(execute: { + [weak self] in + if let StrongSelft = self { + StrongSelft.tableView.reloadData() + //print("reload") + } + + }) + + }) + + + } + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + func requestReport() { + //print("000") + if let m = SFVPNManager.shared.manager {//where m.connection.status == .Connected + //print("\(m.protocolConfiguration)") + let date = NSDate() + let me = SFVPNXPSCommand.STATUS.rawValue + "|\(date)" + if let session = m.connection as? NETunnelProviderSession, + let message = me.data(using: String.Encoding.utf8), m.connection.status == .connected + { + do { + try session.sendProviderMessage(message) { [weak self] response in + if response != nil { + self!.processData(data: response! ) + } else { + //self!.alertMessageAction("Got a nil response from the provider",complete: nil) + } + } + } catch { + //alertMessageAction("Failed to Get result ",complete: nil) + } + }else { + //alertMessageAction("Connection not Stated",complete: nil) + //statusCell!.configLabel.text = config + " " + m.connection.status.description + } + }else { + //statusCell!.configLabel.text = config + //alertMessageAction("message dont init",complete: nil) + } + + } + func processData(data:Data) { + //results.removeAll() + //print("111") + //let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) + let obj = try! JSON.init(data: data) + if obj.error == nil { + //alertMessageAction("message dont init",complete: nil) + //report.map(j: obj) + report.netflow.mapObject(j: obj["netflow"]) + chartsView.updateFlow(report.netflow) + //statusCell!.configLabel.text = "\(report.lastTraffice.report()) mem:\(report.memoryString())" + //tableView.reloadSections(NSIndexSet.init(index: 2), withRowAnimation: .Automatic) + }else { + // if let m = SFVPNManager.shared.manager { + // statusCell!.configLabel.text = config + " " + m.connection.status.description + // statusCell!.statusSwitch.on = true + // }else { + // statusCell!.configLabel.text = "VPN Manager Error" + // statusCell!.statusSwitch.on = false + // } + // + } + tableView.reloadData() + } + func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets{ + return UIEdgeInsets.init(top: 5, left: 44, bottom: 0, right: 0) + } + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + self.tableView.contentSize = size + self.tableView.reloadData() + } + func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) { + // Perform any setup necessary in order to update the view. + + // If an error is encountered, use NCUpdateResult.Failed + // If there's no update required, use NCUpdateResult.NoData + // If there's an update, use NCUpdateResult.NewData + + completionHandler(NCUpdateResult.newData) + } + +} + +extension TodayViewController{ + func tcpScan(){ + let queue = DispatchQueue(label: "com.abigt.socket")//, DISPATCH_QUEUE_CONCURRENT) + for p in ProxyGroupSettings.share.proxys { + print(p.showString() + " now scan " ) + if p.kcptun { + continue + } + queue.async( execute: { + + let start = Date() + + + // Look up the host... + let socketfd: Int32 = socket(Int32(AF_INET), SOCK_STREAM, Int32(IPPROTO_TCP)) + let remoteHostName = p.serverAddress + //let port = Intp.serverPort + guard let remoteHost = gethostbyname2((remoteHostName as NSString).utf8String, AF_INET)else { + return + } + let d = NSDate() + p.dnsValue = d.timeIntervalSince(start) + var remoteAddr = sockaddr_in() + remoteAddr.sin_family = sa_family_t(AF_INET) + bcopy(remoteHost.pointee.h_addr_list[0], &remoteAddr.sin_addr.s_addr, Int(remoteHost.pointee.h_length)) + remoteAddr.sin_port = UInt16(p.serverPort)!.bigEndian + + // Now, do the connection... + //https://swift.org/migration-guide/se-0107-migrate.html + let rc = withUnsafePointer(to: &remoteAddr) { + // Temporarily bind the memory at &addr to a single instance of type sockaddr. + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { + connect(socketfd, $0, socklen_t(MemoryLayout.stride)) + } + } + + + if rc < 0 { + print("\(p.serverAddress):\(p.serverPort) socket connect failed") + //throw BlueSocketError(code: BlueSocket.SOCKET_ERR_CONNECT_FAILED, reason: self.lastError()) + p.tcpValue = -1 + }else { + let end = Date() + p.tcpValue = end.timeIntervalSince(start) + close(socketfd) + } + + + DispatchQueue.main.async( execute: { [weak self] in + if let StrongSelft = self { + StrongSelft.tableView.reloadData() + print("reload") + } + }) + }) + } + } +} diff --git a/SurfToday/image.xcassets/AppIcon-3.imageset/Contents.json b/SurfToday/image.xcassets/AppIcon-3.imageset/Contents.json new file mode 100644 index 0000000..f8f827e --- /dev/null +++ b/SurfToday/image.xcassets/AppIcon-3.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SurfToday/image.xcassets/Contents.json b/SurfToday/image.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/SurfToday/image.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SurfToday/image.xcassets/star.imageset/Contents.json b/SurfToday/image.xcassets/star.imageset/Contents.json new file mode 100644 index 0000000..14cf9e0 --- /dev/null +++ b/SurfToday/image.xcassets/star.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "star.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "star@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "star@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SurfToday/image.xcassets/star.imageset/star.png b/SurfToday/image.xcassets/star.imageset/star.png new file mode 100644 index 0000000..37a1157 Binary files /dev/null and b/SurfToday/image.xcassets/star.imageset/star.png differ diff --git a/SurfToday/image.xcassets/star.imageset/star@2x.png b/SurfToday/image.xcassets/star.imageset/star@2x.png new file mode 100644 index 0000000..fc68375 Binary files /dev/null and b/SurfToday/image.xcassets/star.imageset/star@2x.png differ diff --git a/SurfToday/image.xcassets/star.imageset/star@3x.png b/SurfToday/image.xcassets/star.imageset/star@3x.png new file mode 100644 index 0000000..f4afdf2 Binary files /dev/null and b/SurfToday/image.xcassets/star.imageset/star@3x.png differ diff --git a/SurfToday/today.entitlements b/SurfToday/today.entitlements new file mode 100644 index 0000000..5df8f2b --- /dev/null +++ b/SurfToday/today.entitlements @@ -0,0 +1,21 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + app-proxy-provider + + com.apple.developer.networking.vpn.api + + allow-vpn + + com.apple.security.application-groups + + group.com.abigt.Surf + + com.apple.developer.networking.HotspotHelper + + + diff --git a/SurfToday/zh-Hans.lproj/MainInterface.strings b/SurfToday/zh-Hans.lproj/MainInterface.strings new file mode 100644 index 0000000..73ce485 --- /dev/null +++ b/SurfToday/zh-Hans.lproj/MainInterface.strings @@ -0,0 +1,30 @@ + +/* Class = "UILabel"; text = "L"; ObjectID = "4a2-M0-VtP"; */ +"4a2-M0-VtP.text" = "L"; + +/* Class = "UILabel"; text = "L"; ObjectID = "Ad1-Bz-R7s"; */ +"Ad1-Bz-R7s.text" = "L"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "DMk-b2-mZ9"; */ +"DMk-b2-mZ9.text" = "Label"; + +/* Class = "UILabel"; text = "proxy"; ObjectID = "Sck-Xb-lRb"; */ +"Sck-Xb-lRb.text" = "proxy"; + +/* Class = "UILabel"; text = "L"; ObjectID = "Sdz-My-iT6"; */ +"Sdz-My-iT6.text" = "L"; + +/* Class = "UILabel"; text = "L"; ObjectID = "THa-vr-Pml"; */ +"THa-vr-Pml.text" = "L"; + +/* Class = "UILabel"; text = "No Config"; ObjectID = "VIW-wF-WxU"; */ +"VIW-wF-WxU.text" = "No Config"; + +/* Class = "UILabel"; text = "100.00KB/s"; ObjectID = "Whc-H8-1h5"; */ +"Whc-H8-1h5.text" = "100.00KB/s"; + +/* Class = "UILabel"; text = "100.00KB/s"; ObjectID = "oCP-iO-vns"; */ +"oCP-iO-vns.text" = "100.00KB/s"; + +/* Class = "UILabel"; text = "Label"; ObjectID = "yoN-WT-LAD"; */ +"yoN-WT-LAD.text" = "Label"; diff --git a/XDataService/Info.plist b/XDataService/Info.plist new file mode 100644 index 0000000..e13a17e --- /dev/null +++ b/XDataService/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2018年 A.BIG.T. All rights reserved. + NSPrincipalClass + + + diff --git a/XDataService/RequestBasic.xib b/XDataService/RequestBasic.xib new file mode 100644 index 0000000..0fd9299 --- /dev/null +++ b/XDataService/RequestBasic.xib @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/XDataService/RequestsBasic.swift b/XDataService/RequestsBasic.swift new file mode 100644 index 0000000..b2fb153 --- /dev/null +++ b/XDataService/RequestsBasic.swift @@ -0,0 +1,254 @@ +// +// RequestsBasic.swift +// XDataService +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +import Cocoa +import SwiftyJSON +import NetworkExtension +import SFSocket +import XProxy +open class RequestsBasic: NSViewController,NSTableViewDelegate,NSTableViewDataSource { + + public var results:[SFRequestInfo] = [] + public var dbURL:URL? + @IBOutlet public weak var tableView:NSTableView! + + + public override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { + print("load....") + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + @objc required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + print("load coder....") + } + + public func processData(data:Data) { + let oldresults = results + results.removeAll() + + let obj = try! JSON.init(data: data) + if obj.error == nil { + + let count = obj["count"] + + if count.intValue != 0 { + + let result = obj["data"] + if result.type == .array { + for item in result { + + let json = item.1 + let r = SFRequestInfo.init(rID: 0) + r.map(json) + let rr = oldresults.filter({ info -> Bool in + if info.reqID == r.reqID && info.subID == r.subID { + return true + } + return false + }) + + if rr.isEmpty { + results.append(r) + r.speedtraffice = r.traffice + }else { + let old = rr.first! + if r.traffice.rx > old.traffice.rx { + //sub id reset + r.speedtraffice.rx = r.traffice.rx - old.traffice.rx + } + + if r.traffice.tx > old.traffice.tx{ + //? + r.speedtraffice.tx = r.traffice.tx - old.traffice.tx + } + + + results.append(r) + } + + } + } + if results.count > 0 { + results.sort(by: { $0.reqID < $1.reqID }) + + } + + } + + + } + + tableView.reloadData() + + } + public func numberOfRows(in tableView: NSTableView) -> Int { + return results.count + } + public func tableView(_ tableView: NSTableView + , objectValueFor tableColumn: NSTableColumn? + , row: Int) -> Any? { + let result = results[row] + if (tableColumn?.identifier)!.rawValue == "Icon" { + switch result.rule.policy{ + case .Direct: + return NSImage(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + case .Proxy: + return NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + case .Reject: + return NSImage(named:NSImage.Name(rawValue: "NSStatusUnavailable")) + default: + break + } + } + return nil + } + public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + + let iden = tableColumn!.identifier.rawValue + let result = results[row] + + let cell:NSTableCellView = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as! NSTableCellView + if iden == "Index" { + cell.textField?.stringValue = "\(result.reqID) \(result.subID)" + + + }else if iden == "App" { + + cell.textField?.attributedStringValue = result.detailString() + }else if iden == "Url" { + if result.mode == .HTTP { + if let u = URL(string: result.url){ + if let h = u.host { + cell.textField?.stringValue = h + }else { + cell.textField?.stringValue = u.description + } + + }else { + if let req = result.reqHeader{ + cell.textField?.stringValue = req.Host + } + } + + }else { + cell.textField?.stringValue = result.url + } + + }else if iden == "Rule" { + + }else if iden == "Date" { + + cell.textField?.stringValue = result.dataDesc(result.sTime) + }else if iden == "Status" { + + let n = Date() + let a = result.activeTime + let idle = n.timeIntervalSince(a) + if idle > 1 { + cell.textField?.stringValue = "idle \(Int(idle))" + }else { + cell.textField?.stringValue = result.status.description + } + + }else if iden == "Policy" { + let rule = result.rule + cell.textField?.stringValue = rule.policy.description + " (" + rule.type.description + ":" + rule.name + ")" + //(\(rule.type.description):\(rule.name) ProxyName:\(rule.proxyName))" + //cell.textField?.stringValue = "Demo"//result.status.description + }else if iden == "Up" { + let tx = result.speedtraffice.tx + cell.textField?.stringValue = self.toString(x: tx,label:"",speed: true) + }else if iden == "Down" { + let rx = result.speedtraffice.rx + cell.textField?.stringValue = self.toString(x: rx,label:"",speed: true) + + }else if iden == "Method" { + if result.mode == .TCP{ + cell.textField?.stringValue = "TCP" + }else { + if let req = result.reqHeader { + if req.method == .CONNECT { + cell.textField?.stringValue = "HTTPS" + }else { + cell.textField?.stringValue = req.method.rawValue + } + + } + } + + }else if iden == "Icon" { + switch result.rule.policy{ + case .Direct: + cell.imageView?.objectValue = NSImage(named:NSImage.Name(rawValue: "NSStatusPartiallyAvailable")) + case .Proxy: + cell.imageView?.objectValue = NSImage(named:NSImage.Name(rawValue: "NSStatusAvailable")) + case .Reject: + cell.imageView?.objectValue = NSImage(named:NSImage.Name(rawValue: "NSStatusUnavailable")) + default: + break + } + }else if iden == "DNS" { + + if !result.rule.ipAddress.isEmpty { + cell.textField?.stringValue = result.rule.ipAddress + }else { + if !result.remoteIPaddress.isEmpty{ + let x = result.remoteIPaddress.components(separatedBy: " ") + if x.count > 1 { + cell.textField?.stringValue = x.last! + }else { + cell.textField?.stringValue = x.first! + } + + }else { + if !result.rule.name.isEmpty { + cell.textField?.stringValue = result.rule.name + }else { + let x = "NONE" + let s = NSMutableAttributedString(string:x ) + let r = NSMakeRange(0, 4); + s.addAttributes([NSAttributedStringKey.foregroundColor:NSColor.red,NSAttributedStringKey.backgroundColor:NSColor.white], range: r) + cell.textField?.attributedStringValue = s + } + + } + + } + + + } + if row % 2 == 0 { + cell.backgroundStyle = .dark + }else { + cell.backgroundStyle = .light + } + return cell + } + public func toString(x:UInt,label:String,speed:Bool) ->String { + + var s = "/s" + if !speed { + s = "" + } + + if x < 1024{ + return label + " \(x) B" + s + }else if x >= 1024 && x < 1024*1024 { + return label + String(format: "%0.2f KB", Float(x)/1024.0) + s + }else if x >= 1024*1024 && x < 1024*1024*1024 { + + return label + String(format: "%0.2f MB", Float(x)/1024/1024) + s + }else { + + return label + String(format: "%0.2f GB", Float(x)/1024/1024/1024) + s + } + + } +} diff --git a/XDataService/XDataService.h b/XDataService/XDataService.h new file mode 100644 index 0000000..f2721d9 --- /dev/null +++ b/XDataService/XDataService.h @@ -0,0 +1,19 @@ +// +// XDataService.h +// XDataService +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// + +#import + +//! Project version number for XDataService. +FOUNDATION_EXPORT double XDataServiceVersionNumber; + +//! Project version string for XDataService. +FOUNDATION_EXPORT const unsigned char XDataServiceVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/XDataService/xdatamac.xcconfig b/XDataService/xdatamac.xcconfig new file mode 100644 index 0000000..92fe888 --- /dev/null +++ b/XDataService/xdatamac.xcconfig @@ -0,0 +1,12 @@ +// +// mac.xcconfig +// Surf +// +// Created by abigt on 2018/1/17. +// Copyright © 2018年 A.BIG.T. All rights reserved. +// +HEADER_SEARCH_PATHS = $(inherited) // "$(SRCROOT)/MMDB" +OTHER_LDFLAGS = $(inherited) -framework Xcon +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/Carthage/Build/Mac/" +HEADER_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/share/include" "$(SRCROOT)/share/include/sodium" "$(SRCROOT)/Shared/header" "$(SRCROOT)/MMDB" "$(SRCROOT)/shared/lwip/badvpn" +USER_HEADER_SEARCH_PATHS = $(inherited) "$(SRCROOT)/Shared/header" "$(SRCROOT)/shared/lwip/src/include/"** "$(SRCROOT)/shared/lwip/custom" "$(SRCROOT)/Shared/proxy/ss" diff --git a/ios.sh b/ios.sh new file mode 100644 index 0000000..df22c4b --- /dev/null +++ b/ios.sh @@ -0,0 +1,4 @@ +rm -rf Crashlytics.framework +rm -rf Fabric.framework +ln -s iosLab/Crashlytics.framework Crashlytics.framework +ln -s iosLab/Fabric.framework Fabric.framework diff --git a/mac.sh b/mac.sh new file mode 100644 index 0000000..72dc8e4 --- /dev/null +++ b/mac.sh @@ -0,0 +1,4 @@ +rm Crashlytics.framework +rm Fabric.framework +ln -s maclab/Crashlytics.framework Crashlytics.framework +ln -s macloab/Fabric.framework Fabric.framework diff --git a/move.sh b/move.sh new file mode 100644 index 0000000..061dcb0 --- /dev/null +++ b/move.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# ln -s Crashlytics_ios.framework Crashlytics.framework +# ln -s Fabric_ios.framework Fabric.framework +#carthage update --platform iOS +cd Carthage/Build/iOS/ +list="Alamofire +SystemKitiOS +IoniconsSwift +Charts +SwiftyStoreKit +Reachability +MMDB +Charts +SwiftyStoreKit +GRDB +DarwinCore +ObjectMapper +IDZSwiftCommonCrypto +SFSocket +Sodium +CocoaAsyncSocket +AxLogger +kcp +snappy +SwiftyJSON +Crypto +CommonCrypto +XFoundation +XRuler +XProxy +Xsocket +Xcon +lwip" + +for line in $list +#cat ff.txt |while read line +do + echo $line +lipo -remove i386 $line.framework/$line -output $line.framework/$line +lipo -remove x86_64 $line.framework/$line -output $line.framework/$line +file $line.framework/$line +done