Content-Security-Policy: default-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 8831
Content-Disposition: inline; filename="main.cpp"
Last-Modified: Thu, 19 Jun 2025 16:49:57 GMT
Expires: Sun, 17 Jun 2035 16:49:57 GMT
ETag: "577e84c481f6a6891405f42111690c7847a7842b"

// dear imgui: standalone example application for SDL2 + OpenGL
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.)

#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <SDL.h>

// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually. 
// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad.
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
#include <GL/gl3w.h>    // Initialize with gl3wInit()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
#include <GL/glew.h>    // Initialize with glewInit()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
#include <glad/glad.h>  // Initialize with gladLoadGL()
#else
#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM
#endif

int main(int, char**)
{
    // Setup SDL
    if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
    {
        printf("Error: %s\n", SDL_GetError());
        return -1;
    }

    // Decide GL+GLSL versions
#if __APPLE__
    // GL 3.2 Core + GLSL 150
    const char* glsl_version = "#version 150";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#else
    // GL 3.0 + GLSL 130
    const char* glsl_version = "#version 130";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif

    // Create window with graphics context
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
    SDL_DisplayMode current;
    SDL_GetCurrentDisplayMode(0, &current);
    SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
    SDL_GLContext gl_context = SDL_GL_CreateContext(window);
    SDL_GL_SetSwapInterval(1); // Enable vsync

    // Initialize OpenGL loader
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
    bool err = gl3wInit() != 0;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
    bool err = glewInit() != GLEW_OK;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
    bool err = gladLoadGL() == 0;
#endif
    if (err)
    {
        fprintf(stderr, "Failed to initialize OpenGL loader!\n");
        return 1;
    }

    // Setup Dear ImGui binding
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls

    ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
    ImGui_ImplOpenGL3_Init(glsl_version);

    // Setup style
    ImGui::StyleColorsDark();
    //ImGui::StyleColorsClassic();

    // Load Fonts
    // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. 
    // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. 
    // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
    // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
    // - Read 'misc/fonts/README.txt' for more instructions and details.
    // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
    //io.Fonts->AddFontDefault();
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
    //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
    //IM_ASSERT(font != NULL);

    bool show_demo_window = true;
    bool show_another_window = false;
    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

    // Main loop
    bool done = false;
    while (!done)
    {
        // Poll and handle events (inputs, window resize, etc.)
        // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
        // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
        // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
        // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            ImGui_ImplSDL2_ProcessEvent(&event);
            if (event.type == SDL_QUIT)
                done = true;
            if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
                done = true;
        }

        // Start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplSDL2_NewFrame(window);
        ImGui::NewFrame();

        // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
        if (show_demo_window)
            ImGui::ShowDemoWindow(&show_demo_window);

        // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
        {
            static float f = 0.0f;
            static int counter = 0;

            ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.

            ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)
            ImGui::Checkbox("Demo Window", &show_demo_window);      // Edit bools storing our window open/close state
            ImGui::Checkbox("Another Window", &show_another_window);

            ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f    
            ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color

            if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated)
                counter++;
            ImGui::SameLine();
            ImGui::Text("counter = %d", counter);

            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
            ImGui::End();
        }

        // 3. Show another simple window.
        if (show_another_window)
        {
            ImGui::Begin("Another Window", &show_another_window);   // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
            ImGui::Text("Hello from another window!");
            if (ImGui::Button("Close Me"))
                show_another_window = false;
            ImGui::End();
        }

        // Rendering
        ImGui::Render();
        SDL_GL_MakeCurrent(window, gl_context);
        glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        SDL_GL_SwapWindow(window);
    }

    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

    SDL_GL_DeleteContext(gl_context);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
<a id='n170' href='#n170'>170</a>
<a id='n171' href='#n171'>171</a>
<a id='n172' href='#n172'>172</a>
<a id='n173' href='#n173'>173</a>
<a id='n174' href='#n174'>174</a>
<a id='n175' href='#n175'>175</a>
<a id='n176' href='#n176'>176</a>
<a id='n177' href='#n177'>177</a>
<a id='n178' href='#n178'>178</a>
<a id='n179' href='#n179'>179</a>
<a id='n180' href='#n180'>180</a>
<a id='n181' href='#n181'>181</a>
<a id='n182' href='#n182'>182</a>
<a id='n183' href='#n183'>183</a>
<a id='n184' href='#n184'>184</a>
<a id='n185' href='#n185'>185</a>
<a id='n186' href='#n186'>186</a>
<a id='n187' href='#n187'>187</a>
<a id='n188' href='#n188'>188</a>
<a id='n189' href='#n189'>189</a>
<a id='n190' href='#n190'>190</a>
<a id='n191' href='#n191'>191</a>
<a id='n192' href='#n192'>192</a>
<a id='n193' href='#n193'>193</a>
<a id='n194' href='#n194'>194</a>
<a id='n195' href='#n195'>195</a>
<a id='n196' href='#n196'>196</a>
<a id='n197' href='#n197'>197</a>
<a id='n198' href='#n198'>198</a>
<a id='n199' href='#n199'>199</a>
<a id='n200' href='#n200'>200</a>
<a id='n201' href='#n201'>201</a>
<a id='n202' href='#n202'>202</a>
<a id='n203' href='#n203'>203</a>
<a id='n204' href='#n204'>204</a>
<a id='n205' href='#n205'>205</a>
<a id='n206' href='#n206'>206</a>
<a id='n207' href='#n207'>207</a>
<a id='n208' href='#n208'>208</a>
<a id='n209' href='#n209'>209</a>
<a id='n210' href='#n210'>210</a>
<a id='n211' href='#n211'>211</a>
<a id='n212' href='#n212'>212</a>
<a id='n213' href='#n213'>213</a>
<a id='n214' href='#n214'>214</a>
<a id='n215' href='#n215'>215</a>
<a id='n216' href='#n216'>216</a>
<a id='n217' href='#n217'>217</a>
<a id='n218' href='#n218'>218</a>
<a id='n219' href='#n219'>219</a>
<a id='n220' href='#n220'>220</a>
<a id='n221' href='#n221'>221</a>
<a id='n222' href='#n222'>222</a>
<a id='n223' href='#n223'>223</a>
<a id='n224' href='#n224'>224</a>
<a id='n225' href='#n225'>225</a>
<a id='n226' href='#n226'>226</a>
<a id='n227' href='#n227'>227</a>
<a id='n228' href='#n228'>228</a>
<a id='n229' href='#n229'>229</a>
<a id='n230' href='#n230'>230</a>
<a id='n231' href='#n231'>231</a>
<a id='n232' href='#n232'>232</a>
<a id='n233' href='#n233'>233</a>
<a id='n234' href='#n234'>234</a>
<a id='n235' href='#n235'>235</a>
<a id='n236' href='#n236'>236</a>
<a id='n237' href='#n237'>237</a>
<a id='n238' href='#n238'>238</a>
<a id='n239' href='#n239'>239</a>
<a id='n240' href='#n240'>240</a>
<a id='n241' href='#n241'>241</a>
<a id='n242' href='#n242'>242</a>
<a id='n243' href='#n243'>243</a>
<a id='n244' href='#n244'>244</a>
<a id='n245' href='#n245'>245</a>
<a id='n246' href='#n246'>246</a>
<a id='n247' href='#n247'>247</a>
<a id='n248' href='#n248'>248</a>
<a id='n249' href='#n249'>249</a>
<a id='n250' href='#n250'>250</a>
<a id='n251' href='#n251'>251</a>
<a id='n252' href='#n252'>252</a>
<a id='n253' href='#n253'>253</a>
<a id='n254' href='#n254'>254</a>
<a id='n255' href='#n255'>255</a>
<a id='n256' href='#n256'>256</a>
<a id='n257' href='#n257'>257</a>
<a id='n258' href='#n258'>258</a>
<a id='n259' href='#n259'>259</a>
<a id='n260' href='#n260'>260</a>
<a id='n261' href='#n261'>261</a>
<a id='n262' href='#n262'>262</a>
<a id='n263' href='#n263'>263</a>
<a id='n264' href='#n264'>264</a>
<a id='n265' href='#n265'>265</a>
<a id='n266' href='#n266'>266</a>
<a id='n267' href='#n267'>267</a>
<a id='n268' href='#n268'>268</a>
<a id='n269' href='#n269'>269</a>
<a id='n270' href='#n270'>270</a>
<a id='n271' href='#n271'>271</a>
<a id='n272' href='#n272'>272</a>
<a id='n273' href='#n273'>273</a>
<a id='n274' href='#n274'>274</a>
<a id='n275' href='#n275'>275</a>
<a id='n276' href='#n276'>276</a>
<a id='n277' href='#n277'>277</a>
<a id='n278' href='#n278'>278</a>
<a id='n279' href='#n279'>279</a>
<a id='n280' href='#n280'>280</a>
<a id='n281' href='#n281'>281</a>
<a id='n282' href='#n282'>282</a>
<a id='n283' href='#n283'>283</a>
<a id='n284' href='#n284'>284</a>
<a id='n285' href='#n285'>285</a>
<a id='n286' href='#n286'>286</a>
<a id='n287' href='#n287'>287</a>
<a id='n288' href='#n288'>288</a>
<a id='n289' href='#n289'>289</a>
<a id='n290' href='#n290'>290</a>
<a id='n291' href='#n291'>291</a>
<a id='n292' href='#n292'>292</a>
<a id='n293' href='#n293'>293</a>
<a id='n294' href='#n294'>294</a>
<a id='n295' href='#n295'>295</a>
<a id='n296' href='#n296'>296</a>
<a id='n297' href='#n297'>297</a>
<a id='n298' href='#n298'>298</a>
<a id='n299' href='#n299'>299</a>
<a id='n300' href='#n300'>300</a>
<a id='n301' href='#n301'>301</a>
<a id='n302' href='#n302'>302</a>
<a id='n303' href='#n303'>303</a>
<a id='n304' href='#n304'>304</a>
<a id='n305' href='#n305'>305</a>
<a id='n306' href='#n306'>306</a>
<a id='n307' href='#n307'>307</a>
<a id='n308' href='#n308'>308</a>
<a id='n309' href='#n309'>309</a>
<a id='n310' href='#n310'>310</a>
<a id='n311' href='#n311'>311</a>
<a id='n312' href='#n312'>312</a>
<a id='n313' href='#n313'>313</a>
<a id='n314' href='#n314'>314</a>
<a id='n315' href='#n315'>315</a>
<a id='n316' href='#n316'>316</a>
<a id='n317' href='#n317'>317</a>
<a id='n318' href='#n318'>318</a>
<a id='n319' href='#n319'>319</a>
<a id='n320' href='#n320'>320</a>
<a id='n321' href='#n321'>321</a>
<a id='n322' href='#n322'>322</a>
<a id='n323' href='#n323'>323</a>
<a id='n324' href='#n324'>324</a>
<a id='n325' href='#n325'>325</a>
<a id='n326' href='#n326'>326</a>
<a id='n327' href='#n327'>327</a>
<a id='n328' href='#n328'>328</a>
<a id='n329' href='#n329'>329</a>
<a id='n330' href='#n330'>330</a>
<a id='n331' href='#n331'>331</a>
<a id='n332' href='#n332'>332</a>
<a id='n333' href='#n333'>333</a>
<a id='n334' href='#n334'>334</a>
<a id='n335' href='#n335'>335</a>
<a id='n336' href='#n336'>336</a>
<a id='n337' href='#n337'>337</a>
<a id='n338' href='#n338'>338</a>
<a id='n339' href='#n339'>339</a>
<a id='n340' href='#n340'>340</a>
<a id='n341' href='#n341'>341</a>
<a id='n342' href='#n342'>342</a>
<a id='n343' href='#n343'>343</a>
<a id='n344' href='#n344'>344</a>
<a id='n345' href='#n345'>345</a>
<a id='n346' href='#n346'>346</a>
<a id='n347' href='#n347'>347</a>
<a id='n348' href='#n348'>348</a>
<a id='n349' href='#n349'>349</a>
<a id='n350' href='#n350'>350</a>
<a id='n351' href='#n351'>351</a>
<a id='n352' href='#n352'>352</a>
<a id='n353' href='#n353'>353</a>
<a id='n354' href='#n354'>354</a>
<a id='n355' href='#n355'>355</a>
<a id='n356' href='#n356'>356</a>
<a id='n357' href='#n357'>357</a>
<a id='n358' href='#n358'>358</a>
<a id='n359' href='#n359'>359</a>
<a id='n360' href='#n360'>360</a>
<a id='n361' href='#n361'>361</a>
<a id='n362' href='#n362'>362</a>
<a id='n363' href='#n363'>363</a>
<a id='n364' href='#n364'>364</a>
<a id='n365' href='#n365'>365</a>
<a id='n366' href='#n366'>366</a>
<a id='n367' href='#n367'>367</a>
<a id='n368' href='#n368'>368</a>
<a id='n369' href='#n369'>369</a>
<a id='n370' href='#n370'>370</a>
<a id='n371' href='#n371'>371</a>
<a id='n372' href='#n372'>372</a>
<a id='n373' href='#n373'>373</a>
<a id='n374' href='#n374'>374</a>
<a id='n375' href='#n375'>375</a>
<a id='n376' href='#n376'>376</a>
<a id='n377' href='#n377'>377</a>
<a id='n378' href='#n378'>378</a>
<a id='n379' href='#n379'>379</a>
<a id='n380' href='#n380'>380</a>
<a id='n381' href='#n381'>381</a>
<a id='n382' href='#n382'>382</a>
<a id='n383' href='#n383'>383</a>
<a id='n384' href='#n384'>384</a>
<a id='n385' href='#n385'>385</a>
<a id='n386' href='#n386'>386</a>
<a id='n387' href='#n387'>387</a>
<a id='n388' href='#n388'>388</a>
<a id='n389' href='#n389'>389</a>
<a id='n390' href='#n390'>390</a>
<a id='n391' href='#n391'>391</a>
<a id='n392' href='#n392'>392</a>
<a id='n393' href='#n393'>393</a>
<a id='n394' href='#n394'>394</a>
<a id='n395' href='#n395'>395</a>
<a id='n396' href='#n396'>396</a>
<a id='n397' href='#n397'>397</a>
<a id='n398' href='#n398'>398</a>
<a id='n399' href='#n399'>399</a>
<a id='n400' href='#n400'>400</a>
<a id='n401' href='#n401'>401</a>
<a id='n402' href='#n402'>402</a>
<a id='n403' href='#n403'>403</a>
<a id='n404' href='#n404'>404</a>
<a id='n405' href='#n405'>405</a>
<a id='n406' href='#n406'>406</a>
<a id='n407' href='#n407'>407</a>
<a id='n408' href='#n408'>408</a>
<a id='n409' href='#n409'>409</a>
<a id='n410' href='#n410'>410</a>
<a id='n411' href='#n411'>411</a>
<a id='n412' href='#n412'>412</a>
<a id='n413' href='#n413'>413</a>
<a id='n414' href='#n414'>414</a>
<a id='n415' href='#n415'>415</a>
<a id='n416' href='#n416'>416</a>
<a id='n417' href='#n417'>417</a>
<a id='n418' href='#n418'>418</a>
<a id='n419' href='#n419'>419</a>
<a id='n420' href='#n420'>420</a>
<a id='n421' href='#n421'>421</a>
<a id='n422' href='#n422'>422</a>
<a id='n423' href='#n423'>423</a>
<a id='n424' href='#n424'>424</a>
<a id='n425' href='#n425'>425</a>
<a id='n426' href='#n426'>426</a>
<a id='n427' href='#n427'>427</a>
<a id='n428' href='#n428'>428</a>
<a id='n429' href='#n429'>429</a>
<a id='n430' href='#n430'>430</a>
<a id='n431' href='#n431'>431</a>
<a id='n432' href='#n432'>432</a>
<a id='n433' href='#n433'>433</a>
<a id='n434' href='#n434'>434</a>
<a id='n435' href='#n435'>435</a>
<a id='n436' href='#n436'>436</a>
<a id='n437' href='#n437'>437</a>
<a id='n438' href='#n438'>438</a>
<a id='n439' href='#n439'>439</a>
<a id='n440' href='#n440'>440</a>
<a id='n441' href='#n441'>441</a>
<a id='n442' href='#n442'>442</a>
<a id='n443' href='#n443'>443</a>
<a id='n444' href='#n444'>444</a>
<a id='n445' href='#n445'>445</a>
<a id='n446' href='#n446'>446</a>
<a id='n447' href='#n447'>447</a>
<a id='n448' href='#n448'>448</a>
<a id='n449' href='#n449'>449</a>
<a id='n450' href='#n450'>450</a>
<a id='n451' href='#n451'>451</a>
<a id='n452' href='#n452'>452</a>
<a id='n453' href='#n453'>453</a>
<a id='n454' href='#n454'>454</a>
</pre></td>
<td class='lines'><pre><code><style>pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="ch">#!/bin/sh</span>
<span class="o">[</span> -e /etc/functions.sh <span class="o">]</span> <span class="o">&amp;&amp;</span> . /etc/functions.sh <span class="o">||</span> . ./functions.sh
<span class="o">[</span> -x /sbin/modprobe <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">insmod</span><span class="o">=</span><span class="s2">&quot;modprobe&quot;</span> <span class="o">||</span> <span class="nv">insmod</span><span class="o">=</span><span class="s2">&quot;insmod&quot;</span>

add_insmod<span class="o">()</span> <span class="o">{</span>
	<span class="nb">eval</span> <span class="s2">&quot;export isset=\${insmod_</span><span class="nv">$1</span><span class="s2">}&quot;</span>
	<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$isset</span><span class="s2">&quot;</span> in
		<span class="m">1</span><span class="o">)</span> <span class="p">;;</span>
		*<span class="o">)</span> append INSMOD <span class="s2">&quot;</span><span class="nv">$insmod</span><span class="s2"> </span><span class="nv">$*</span><span class="s2"> &gt;&amp;- 2&gt;&amp;-&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span><span class="p">;</span> <span class="nb">export</span> insmod_<span class="nv">$1</span><span class="o">=</span><span class="m">1</span><span class="p">;;</span>
	<span class="k">esac</span>
<span class="o">}</span>

<span class="o">[</span> -e /etc/config/network <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="o">{</span>
	<span class="c1"># only try to parse network config on openwrt</span>

	find_ifname<span class="o">()</span> <span class="o">{(</span>
		reset_cb
		include /lib/network
		scan_interfaces
		config_get <span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span> ifname
	<span class="o">)}</span>
<span class="o">}</span> <span class="o">||</span> <span class="o">{</span>
	find_ifname<span class="o">()</span> <span class="o">{</span>
		<span class="nb">echo</span> <span class="s2">&quot;Interface not found.&quot;</span>
		<span class="nb">exit</span> <span class="m">1</span>
	<span class="o">}</span>
<span class="o">}</span>

parse_matching_rule<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">var</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">section</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">options</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$3</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">prefix</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$4</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">suffix</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$5</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">proto</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$6</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">mport</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
	<span class="nb">local</span> <span class="nv">ports</span><span class="o">=</span><span class="s2">&quot;&quot;</span>

	append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$prefix</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
	<span class="k">for</span> option in <span class="nv">$options</span><span class="p">;</span> <span class="k">do</span>
		<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$option</span><span class="s2">&quot;</span> in
			proto<span class="o">)</span> config_get value <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> proto<span class="p">;</span> <span class="nv">proto</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">proto</span><span class="k">:-</span><span class="nv">$value</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">;;</span>
		<span class="k">esac</span>
	<span class="k">done</span>
	config_get <span class="nb">type</span> <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> TYPE
	<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$type</span><span class="s2">&quot;</span> in
		classify<span class="o">)</span> <span class="nb">unset</span> pkt<span class="p">;</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m mark --mark 0&quot;</span><span class="p">;;</span>
		default<span class="o">)</span> <span class="nv">pkt</span><span class="o">=</span><span class="m">1</span><span class="p">;</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m mark --mark 0&quot;</span><span class="p">;;</span>
		reclassify<span class="o">)</span> <span class="nv">pkt</span><span class="o">=</span><span class="m">1</span><span class="p">;;</span>
	<span class="k">esac</span>
	append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="si">${</span><span class="nv">proto</span><span class="p">:+-p </span><span class="nv">$proto</span><span class="si">}</span><span class="s2">&quot;</span>
	<span class="k">for</span> option in <span class="nv">$options</span><span class="p">;</span> <span class="k">do</span>
		config_get value <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$option</span><span class="s2">&quot;</span>
		
		<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$pkt</span><span class="s2">:</span><span class="nv">$option</span><span class="s2">&quot;</span> in
			*:srchost<span class="o">)</span>
				append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-s </span><span class="nv">$value</span><span class="s2">&quot;</span>
			<span class="p">;;</span>
			*:dsthost<span class="o">)</span>
				append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-d </span><span class="nv">$value</span><span class="s2">&quot;</span>
			<span class="p">;;</span>
			*:layer7<span class="o">)</span>
				add_insmod ipt_layer7
				add_insmod xt_layer7
				append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m layer7 --l7proto </span><span class="nv">$value</span><span class="si">${</span><span class="nv">pkt</span><span class="p">:+ --l7pkt</span><span class="si">}</span><span class="s2">&quot;</span>
			<span class="p">;;</span>
			*:ports<span class="p">|</span>*:srcports<span class="p">|</span>*:dstports<span class="o">)</span>
				<span class="nv">value</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="p">|</span> sed -e <span class="s1">&#39;s,-,:,g&#39;</span><span class="k">)</span><span class="s2">&quot;</span>
				<span class="nv">lproto</span><span class="o">=</span><span class="si">${</span><span class="nv">lproto</span><span class="k">:-</span><span class="nv">tcp</span><span class="si">}</span>
				<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$proto</span><span class="s2">&quot;</span> in
					<span class="s2">&quot;&quot;</span><span class="p">|</span>tcp<span class="p">|</span>udp<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m </span><span class="si">${</span><span class="nv">proto</span><span class="k">:-</span><span class="nv">tcp</span><span class="p"> -p tcp</span><span class="si">}</span><span class="s2"> -m multiport&quot;</span><span class="p">;;</span>
					*<span class="o">)</span> <span class="nb">unset</span> <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span><span class="p">;</span> <span class="k">return</span> <span class="m">0</span><span class="p">;;</span>
				<span class="k">esac</span>
				<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$option</span><span class="s2">&quot;</span> in
					ports<span class="o">)</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> srcports <span class="s2">&quot;&quot;</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> dstports <span class="s2">&quot;&quot;</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> portrange <span class="s2">&quot;&quot;</span>
						append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;--ports </span><span class="nv">$value</span><span class="s2">&quot;</span>
					<span class="p">;;</span>
					srcports<span class="o">)</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> ports <span class="s2">&quot;&quot;</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> dstports <span class="s2">&quot;&quot;</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> portrange <span class="s2">&quot;&quot;</span>
						append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;--sports </span><span class="nv">$value</span><span class="s2">&quot;</span>
					<span class="p">;;</span>
					dstports<span class="o">)</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> ports <span class="s2">&quot;&quot;</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> srcports <span class="s2">&quot;&quot;</span>
						config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> portrange <span class="s2">&quot;&quot;</span>
						append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;--dports </span><span class="nv">$value</span><span class="s2">&quot;</span>
					<span class="p">;;</span>
				<span class="k">esac</span>
				<span class="nv">ports</span><span class="o">=</span><span class="m">1</span>
			<span class="p">;;</span>
			*:portrange<span class="o">)</span>
				config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> ports <span class="s2">&quot;&quot;</span>
				config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> srcports <span class="s2">&quot;&quot;</span>
				config_set <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> dstports <span class="s2">&quot;&quot;</span>
				<span class="nv">value</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="p">|</span> sed -e <span class="s1">&#39;s,-,:,g&#39;</span><span class="k">)</span><span class="s2">&quot;</span>
				<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$proto</span><span class="s2">&quot;</span> in
					<span class="s2">&quot;&quot;</span><span class="p">|</span>tcp<span class="p">|</span>udp<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m </span><span class="si">${</span><span class="nv">proto</span><span class="k">:-</span><span class="nv">tcp</span><span class="p"> -p tcp</span><span class="si">}</span><span class="s2"> --sport </span><span class="nv">$value</span><span class="s2"> --dport </span><span class="nv">$value</span><span class="s2">&quot;</span><span class="p">;;</span>
					*<span class="o">)</span> <span class="nb">unset</span> <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span><span class="p">;</span> <span class="k">return</span> <span class="m">0</span><span class="p">;;</span>
				<span class="k">esac</span>
				<span class="nv">ports</span><span class="o">=</span><span class="m">1</span>
			<span class="p">;;</span>
			*:connbytes<span class="o">)</span>
				<span class="nv">value</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="p">|</span> sed -e <span class="s1">&#39;s,-,:,g&#39;</span><span class="k">)</span><span class="s2">&quot;</span>
				add_insmod ipt_connbytes
				append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m connbytes --connbytes </span><span class="nv">$value</span><span class="s2"> --connbytes-dir both --connbytes-mode bytes&quot;</span>
			<span class="p">;;</span>
			*:tos<span class="o">)</span>
                                add_insmod ipt_tos
                                <span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> in
                                        !*<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m tos ! --tos </span><span class="nv">$value</span><span class="s2">&quot;</span><span class="p">;;</span>
                                        *<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m tos --tos </span><span class="nv">$value</span><span class="s2">&quot;</span>
                                <span class="k">esac</span>
                        <span class="p">;;</span>
			*:dscp<span class="o">)</span>
                                add_insmod ipt_dscp
				<span class="nv">dscp_option</span><span class="o">=</span><span class="s2">&quot;--dscp&quot;</span>
                                <span class="o">[</span> -z <span class="s2">&quot;</span><span class="si">${</span><span class="nv">value</span><span class="p">%%[EBCA]*</span><span class="si">}</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">dscp_option</span><span class="o">=</span><span class="s2">&quot;--dscp-class&quot;</span>
				<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> in
                                       	!*<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m dscp ! </span><span class="nv">$dscp_option</span><span class="s2"> </span><span class="nv">$value</span><span class="s2">&quot;</span><span class="p">;;</span>
                                       	*<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m dscp </span><span class="nv">$dscp_option</span><span class="s2"> </span><span class="nv">$value</span><span class="s2">&quot;</span>
                                <span class="k">esac</span>
                        <span class="p">;;</span>
			*:direction<span class="o">)</span>
				<span class="nv">value</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="p">|</span> sed -e <span class="s1">&#39;s,-,:,g&#39;</span><span class="k">)</span><span class="s2">&quot;</span>
				<span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="o">=</span> <span class="s2">&quot;out&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
					append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-o </span><span class="nv">$device</span><span class="s2">&quot;</span>
				<span class="k">elif</span> <span class="o">[</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="o">=</span> <span class="s2">&quot;in&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
					append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-i </span><span class="nv">$device</span><span class="s2">&quot;</span>
				<span class="k">fi</span>
			<span class="p">;;</span>
			<span class="m">1</span>:pktsize<span class="o">)</span>
				<span class="nv">value</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> <span class="p">|</span> sed -e <span class="s1">&#39;s,-,:,g&#39;</span><span class="k">)</span><span class="s2">&quot;</span>
				add_insmod ipt_length
				append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m length --length </span><span class="nv">$value</span><span class="s2">&quot;</span>
			<span class="p">;;</span>
			<span class="m">1</span>:limit<span class="o">)</span>
				add_insmod ipt_limit
				append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m limit --limit </span><span class="nv">$value</span><span class="s2">&quot;</span>
			<span class="p">;;</span>
			<span class="m">1</span>:tcpflags<span class="o">)</span>
				<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$proto</span><span class="s2">&quot;</span> in
					tcp<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m tcp --tcp-flags ALL </span><span class="nv">$value</span><span class="s2">&quot;</span><span class="p">;;</span>
					*<span class="o">)</span> <span class="nb">unset</span> <span class="nv">$var</span><span class="p">;</span> <span class="k">return</span> <span class="m">0</span><span class="p">;;</span>
				<span class="k">esac</span>
			<span class="p">;;</span>
			<span class="m">1</span>:mark<span class="o">)</span>
				config_get class <span class="s2">&quot;</span><span class="si">${</span><span class="nv">value</span><span class="p">##!</span><span class="si">}</span><span class="s2">&quot;</span> classnr
				<span class="o">[</span> -z <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="k">continue</span><span class="p">;</span>
				<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$value</span><span class="s2">&quot;</span> in
					!*<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m mark ! --mark </span><span class="nv">$class</span><span class="s2">&quot;</span><span class="p">;;</span>
					*<span class="o">)</span> append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;-m mark --mark </span><span class="nv">$class</span><span class="s2">&quot;</span><span class="p">;;</span>
				<span class="k">esac</span>
			<span class="p">;;</span>
			<span class="m">1</span>:TOS<span class="o">)</span>
				add_insmod ipt_TOS
				config_get TOS <span class="s2">&quot;</span><span class="nv">$rule</span><span class="s2">&quot;</span> <span class="s1">&#39;TOS&#39;</span>
				<span class="nv">suffix</span><span class="o">=</span><span class="s2">&quot;-j TOS --set-tos &quot;</span><span class="si">${</span><span class="nv">TOS</span><span class="k">:-</span><span class="s2">&quot;Normal-Service&quot;</span><span class="si">}</span>
			<span class="p">;;</span>
			<span class="m">1</span>:DSCP<span class="o">)</span>
				add_insmod ipt_DSCP
				config_get DSCP <span class="s2">&quot;</span><span class="nv">$rule</span><span class="s2">&quot;</span> <span class="s1">&#39;DSCP&#39;</span>
				<span class="o">[</span> -z <span class="s2">&quot;</span><span class="si">${</span><span class="nv">DSCP</span><span class="p">%%[EBCA]*</span><span class="si">}</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">set_value</span><span class="o">=</span><span class="s2">&quot;--set-dscp-class </span><span class="nv">$DSCP</span><span class="s2">&quot;</span> <span class="se">\</span>
				<span class="o">||</span> <span class="nv">set_value</span><span class="o">=</span><span class="s2">&quot;--set-dscp </span><span class="nv">$DSCP</span><span class="s2">&quot;</span>
				<span class="nv">suffix</span><span class="o">=</span><span class="s2">&quot;-j DSCP </span><span class="nv">$set_value</span><span class="s2">&quot;</span>
			<span class="p">;;</span>
		<span class="k">esac</span>
	<span class="k">done</span>
	append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$suffix</span><span class="s2">&quot;</span>
	<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$ports</span><span class="s2">:</span><span class="nv">$proto</span><span class="s2">&quot;</span> in
		<span class="m">1</span>:<span class="o">)</span>	parse_matching_rule <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$section</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$options</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$prefix</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$suffix</span><span class="s2">&quot;</span> <span class="s2">&quot;udp&quot;</span><span class="p">;;</span>
	<span class="k">esac</span>
<span class="o">}</span>

config_cb<span class="o">()</span> <span class="o">{</span>
	option_cb<span class="o">()</span> <span class="o">{</span>
		<span class="k">return</span> <span class="m">0</span>
	<span class="o">}</span>

	<span class="c1"># Section start</span>
	<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span> in
		interface<span class="o">)</span>
			config_set <span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span> <span class="s2">&quot;classgroup&quot;</span> <span class="s2">&quot;Default&quot;</span>
			config_set <span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span> <span class="s2">&quot;upload&quot;</span> <span class="s2">&quot;128&quot;</span>
		<span class="p">;;</span>
		classify<span class="p">|</span>default<span class="p">|</span>reclassify<span class="o">)</span>
			option_cb<span class="o">()</span> <span class="o">{</span>
				append options <span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
			<span class="o">}</span>
		<span class="p">;;</span>
	<span class="k">esac</span>

    <span class="c1"># Section end</span>
	config_get TYPE <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> TYPE
	<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$TYPE</span><span class="s2">&quot;</span> in
		interface<span class="o">)</span>
			config_get_bool enabled <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> enabled <span class="m">1</span>
			<span class="o">[</span> <span class="m">1</span> -eq <span class="s2">&quot;</span><span class="nv">$enabled</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="k">return</span> <span class="m">0</span>
			config_get classgroup <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> classgroup
			config_set <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> imqdev <span class="s2">&quot;</span><span class="nv">$C</span><span class="s2">&quot;</span>
			<span class="nv">C</span><span class="o">=</span><span class="k">$((</span><span class="nv">$C</span><span class="o">+</span><span class="m">1</span><span class="k">))</span>
			append INTERFACES <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span>
			config_set <span class="s2">&quot;</span><span class="nv">$classgroup</span><span class="s2">&quot;</span> enabled <span class="m">1</span>
			config_get device <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> device
			<span class="o">[</span> -z <span class="s2">&quot;</span><span class="nv">$device</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="o">{</span>
				<span class="nv">device</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$(</span>find_ifname <span class="si">${</span><span class="nv">CONFIG_SECTION</span><span class="si">}</span><span class="k">)</span><span class="s2">&quot;</span>
				config_set <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> device <span class="s2">&quot;</span><span class="si">${</span><span class="nv">device</span><span class="k">:-</span><span class="nv">eth0</span><span class="si">}</span><span class="s2">&quot;</span>
			<span class="o">}</span>
		<span class="p">;;</span>
		classgroup<span class="o">)</span> append CG <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span><span class="p">;;</span>
		classify<span class="p">|</span>default<span class="p">|</span>reclassify<span class="o">)</span>
			<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$TYPE</span><span class="s2">&quot;</span> in
				classify<span class="o">)</span> <span class="nv">var</span><span class="o">=</span><span class="s2">&quot;ctrules&quot;</span><span class="p">;;</span>
				*<span class="o">)</span> <span class="nv">var</span><span class="o">=</span><span class="s2">&quot;rules&quot;</span><span class="p">;;</span>
			<span class="k">esac</span>
			config_get target <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> target
			config_set <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span> options <span class="s2">&quot;</span><span class="nv">$options</span><span class="s2">&quot;</span>
			append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$CONFIG_SECTION</span><span class="s2">&quot;</span>
			<span class="nb">unset</span> options
		<span class="p">;;</span>
	<span class="k">esac</span>
<span class="o">}</span>


enum_classes<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">c</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
	config_get classes <span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span> classes
	config_get default <span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span> default
	<span class="k">for</span> class in <span class="nv">$classes</span><span class="p">;</span> <span class="k">do</span>
		<span class="nv">c</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$((</span><span class="nv">$c</span> <span class="o">+</span> <span class="m">1</span><span class="k">))</span><span class="s2">&quot;</span>
		config_set <span class="s2">&quot;</span><span class="si">${</span><span class="nv">class</span><span class="si">}</span><span class="s2">&quot;</span> classnr <span class="nv">$c</span>
		<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> in
			<span class="nv">$default</span><span class="o">)</span> <span class="nv">class_default</span><span class="o">=</span><span class="nv">$c</span><span class="p">;;</span>
		<span class="k">esac</span>
	<span class="k">done</span>
	<span class="nv">class_default</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">class_default</span><span class="k">:-</span><span class="nv">$c</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="o">}</span>

cls_var<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">varname</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">class</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">name</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$3</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">type</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$4</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">default</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$5</span><span class="s2">&quot;</span>
	<span class="nb">local</span> tmp tmp1 tmp2
	config_get tmp1 <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$name</span><span class="s2">&quot;</span>
	config_get tmp2 <span class="s2">&quot;</span><span class="si">${</span><span class="nv">class</span><span class="si">}</span><span class="s2">_</span><span class="si">${</span><span class="nv">type</span><span class="si">}</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$name</span><span class="s2">&quot;</span>
	<span class="nv">tmp</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">tmp2</span><span class="k">:-</span><span class="nv">$tmp1</span><span class="si">}</span><span class="s2">&quot;</span>
	<span class="nv">tmp</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">tmp</span><span class="k">:-</span><span class="nv">$tmp2</span><span class="si">}</span><span class="s2">&quot;</span>
	<span class="nb">export</span> <span class="si">${</span><span class="nv">varname</span><span class="si">}</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">tmp</span><span class="k">:-</span><span class="nv">$default</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="o">}</span>

tcrules<span class="o">()</span> <span class="o">{</span>
	<span class="nv">dir</span><span class="o">=</span>/usr/lib/qos
	<span class="o">[</span> -e <span class="nv">$dir</span>/tcrules.awk <span class="o">]</span> <span class="o">||</span> <span class="nv">dir</span><span class="o">=</span>.
	<span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$cstr</span><span class="s2">&quot;</span> <span class="p">|</span> awk <span class="se">\</span>
		-v <span class="nv">device</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$dev</span><span class="s2">&quot;</span> <span class="se">\</span>
		-v <span class="nv">linespeed</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$rate</span><span class="s2">&quot;</span> <span class="se">\</span>
		-f <span class="nv">$dir</span>/tcrules.awk
<span class="o">}</span>

start_interface<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">iface</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">num_imq</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span>
	config_get device <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> device
	config_get_bool enabled <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> enabled <span class="m">1</span>
	<span class="o">[</span> -z <span class="s2">&quot;</span><span class="nv">$device</span><span class="s2">&quot;</span> -o <span class="m">1</span> -ne <span class="s2">&quot;</span><span class="nv">$enabled</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="o">{</span>
		<span class="k">return</span> <span class="m">1</span> 
	<span class="o">}</span>
	config_get upload <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> upload
	config_get halfduplex <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> halfduplex
	config_get download <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> download
	config_get classgroup <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> classgroup
	config_get_bool overhead <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> overhead <span class="m">0</span>
	
	<span class="nv">download</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">download</span><span class="k">:-</span><span class="si">${</span><span class="nv">halfduplex</span><span class="p">:+</span><span class="nv">$upload</span><span class="si">}}</span><span class="s2">&quot;</span>
	enum_classes <span class="s2">&quot;</span><span class="nv">$classgroup</span><span class="s2">&quot;</span>
	<span class="k">for</span> dir in up<span class="si">${</span><span class="nv">halfduplex</span><span class="si">}</span> <span class="si">${</span><span class="nv">download</span><span class="p">:+down</span><span class="si">}</span><span class="p">;</span> <span class="k">do</span>
		<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$dir</span><span class="s2">&quot;</span> in
			up<span class="o">)</span>
				<span class="o">[</span> <span class="s2">&quot;</span><span class="nv">$overhead</span><span class="s2">&quot;</span> <span class="o">=</span> <span class="m">1</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">upload</span><span class="o">=</span><span class="k">$((</span><span class="nv">$upload</span> <span class="o">*</span> <span class="m">98</span> <span class="o">/</span> <span class="m">100</span> <span class="o">-</span> <span class="o">(</span><span class="m">15</span> <span class="o">*</span> <span class="m">128</span> <span class="o">/</span> <span class="nv">$upload</span><span class="k">))</span><span class="o">)</span>
				<span class="nv">dev</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$device</span><span class="s2">&quot;</span>
				<span class="nv">rate</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$upload</span><span class="s2">&quot;</span>
				<span class="nv">dl_mode</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
				<span class="nv">prefix</span><span class="o">=</span><span class="s2">&quot;cls&quot;</span>
			<span class="p">;;</span>
			down<span class="o">)</span>
				add_insmod imq <span class="nv">numdevs</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$num_imq</span><span class="s2">&quot;</span>
				config_get imqdev <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> imqdev
				<span class="o">[</span> <span class="s2">&quot;</span><span class="nv">$overhead</span><span class="s2">&quot;</span> <span class="o">=</span> <span class="m">1</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">download</span><span class="o">=</span><span class="k">$((</span><span class="nv">$download</span> <span class="o">*</span> <span class="m">98</span> <span class="o">/</span> <span class="m">100</span> <span class="o">-</span> <span class="o">(</span><span class="m">80</span> <span class="o">*</span> <span class="m">1024</span> <span class="o">/</span> <span class="nv">$download</span><span class="k">))</span><span class="o">)</span>
				<span class="nv">dev</span><span class="o">=</span><span class="s2">&quot;imq</span><span class="nv">$imqdev</span><span class="s2">&quot;</span>
				<span class="nv">rate</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$download</span><span class="s2">&quot;</span>
				<span class="nv">dl_mode</span><span class="o">=</span><span class="m">1</span>
				<span class="nv">prefix</span><span class="o">=</span><span class="s2">&quot;d_cls&quot;</span>
			<span class="p">;;</span>
			*<span class="o">)</span> <span class="k">continue</span><span class="p">;;</span>
		<span class="k">esac</span>
		<span class="nv">cstr</span><span class="o">=</span>
		<span class="k">for</span> class in <span class="nv">$classes</span><span class="p">;</span> <span class="k">do</span>
			cls_var pktsize <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> packetsize <span class="nv">$dir</span> <span class="m">1500</span>
			cls_var pktdelay <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> packetdelay <span class="nv">$dir</span> <span class="m">0</span>
			cls_var maxrate <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> limitrate <span class="nv">$dir</span> <span class="m">100</span>
			cls_var prio <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> priority <span class="nv">$dir</span> <span class="m">1</span>
			cls_var avgrate <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> avgrate <span class="nv">$dir</span> <span class="m">0</span>
			config_get classnr <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> classnr
			append cstr <span class="s2">&quot;</span><span class="nv">$classnr</span><span class="s2">:</span><span class="nv">$prio</span><span class="s2">:</span><span class="nv">$avgrate</span><span class="s2">:</span><span class="nv">$pktsize</span><span class="s2">:</span><span class="nv">$pktdelay</span><span class="s2">:</span><span class="nv">$maxrate</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
		<span class="k">done</span>
		append <span class="si">${</span><span class="nv">prefix</span><span class="si">}</span>q <span class="s2">&quot;</span><span class="k">$(</span>tcrules<span class="k">)</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
		<span class="nb">export</span> dev_<span class="si">${</span><span class="nv">dir</span><span class="si">}</span><span class="o">=</span><span class="s2">&quot;ifconfig </span><span class="nv">$dev</span><span class="s2"> up txqueuelen 5 &gt;&amp;- 2&gt;&amp;-</span>
<span class="s2">tc qdisc del dev </span><span class="nv">$dev</span><span class="s2"> root &gt;&amp;- 2&gt;&amp;-</span>
<span class="s2">tc qdisc add dev </span><span class="nv">$dev</span><span class="s2"> root handle 1: hfsc default </span><span class="si">${</span><span class="nv">class_default</span><span class="si">}</span><span class="s2">0</span>
<span class="s2">tc class add dev </span><span class="nv">$dev</span><span class="s2"> parent 1: classid 1:1 hfsc sc rate </span><span class="si">${</span><span class="nv">rate</span><span class="si">}</span><span class="s2">kbit ul rate </span><span class="si">${</span><span class="nv">rate</span><span class="si">}</span><span class="s2">kbit&quot;</span>
	<span class="k">done</span>
	add_insmod cls_fw
	add_insmod sch_hfsc
	add_insmod sch_sfq
	add_insmod sch_red

	cat <span class="s">&lt;&lt;EOF</span>
<span class="s">${INSMOD:+$INSMOD$N}${dev_up:+$dev_up</span>
<span class="s">$clsq</span>
<span class="s">}${imqdev:+$dev_down</span>
<span class="s">$d_clsq</span>
<span class="s">$d_clsl</span>
<span class="s">$d_clsf</span>
<span class="s">}</span>
<span class="s">EOF</span>
	<span class="nb">unset</span> INSMOD clsq clsf clsl d_clsq d_clsl d_clsf dev_up dev_down
<span class="o">}</span>

start_interfaces<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">C</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
	<span class="k">for</span> iface in <span class="nv">$INTERFACES</span><span class="p">;</span> <span class="k">do</span>
		start_interface <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$C</span><span class="s2">&quot;</span>
	<span class="k">done</span>
<span class="o">}</span>

add_rules<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">var</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">rules</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span>
	<span class="nb">local</span> <span class="nv">prefix</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$3</span><span class="s2">&quot;</span>
	
	<span class="k">for</span> rule in <span class="nv">$rules</span><span class="p">;</span> <span class="k">do</span>
		<span class="nb">unset</span> iptrule
		config_get target <span class="s2">&quot;</span><span class="nv">$rule</span><span class="s2">&quot;</span> target
		config_get target <span class="s2">&quot;</span><span class="nv">$target</span><span class="s2">&quot;</span> classnr
		config_get options <span class="s2">&quot;</span><span class="nv">$rule</span><span class="s2">&quot;</span> options

		<span class="c1">## If we want to override the TOS field, let&#39;s clear the DSCP field first.</span>
		<span class="o">[</span> ! -z <span class="s2">&quot;</span><span class="k">$(</span><span class="nb">echo</span> <span class="nv">$options</span> <span class="p">|</span> grep <span class="s1">&#39;TOS&#39;</span><span class="k">)</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="o">{</span>
			<span class="nv">s_options</span><span class="o">=</span><span class="si">${</span><span class="nv">options</span><span class="p">%%TOS</span><span class="si">}</span>
			add_insmod ipt_DSCP
			parse_matching_rule iptrule <span class="s2">&quot;</span><span class="nv">$rule</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$s_options</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$prefix</span><span class="s2">&quot;</span> <span class="s2">&quot;-j DSCP --set-dscp 0&quot;</span>
			append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$iptrule</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
			<span class="nb">unset</span> iptrule
		<span class="o">}</span>

		parse_matching_rule iptrule <span class="s2">&quot;</span><span class="nv">$rule</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$options</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$prefix</span><span class="s2">&quot;</span> <span class="s2">&quot;-j MARK --set-mark </span><span class="nv">$target</span><span class="s2">&quot;</span>
		append <span class="s2">&quot;</span><span class="nv">$var</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$iptrule</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
	<span class="k">done</span>
<span class="o">}</span>

start_cg<span class="o">()</span> <span class="o">{</span>
	<span class="nb">local</span> <span class="nv">cg</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
	<span class="nb">local</span> iptrules
	<span class="nb">local</span> pktrules
	<span class="nb">local</span> sizerules
	<span class="nb">local</span> download
	enum_classes <span class="s2">&quot;</span><span class="nv">$cg</span><span class="s2">&quot;</span>
	add_rules iptrules <span class="s2">&quot;</span><span class="nv">$ctrules</span><span class="s2">&quot;</span> <span class="s2">&quot;iptables -t mangle -A </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2">_ct&quot;</span>
	config_get classes <span class="s2">&quot;</span><span class="nv">$cg</span><span class="s2">&quot;</span> classes
	<span class="k">for</span> class in <span class="nv">$classes</span><span class="p">;</span> <span class="k">do</span>
		config_get mark <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> classnr
		config_get maxsize <span class="s2">&quot;</span><span class="nv">$class</span><span class="s2">&quot;</span> maxsize
		<span class="o">[</span> -z <span class="s2">&quot;</span><span class="nv">$maxsize</span><span class="s2">&quot;</span> -o -z <span class="s2">&quot;</span><span class="nv">$mark</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="o">{</span>
			add_insmod ipt_length
			append pktrules <span class="s2">&quot;iptables -t mangle -A </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2"> -m mark --mark </span><span class="nv">$mark</span><span class="s2"> -m length --length </span><span class="nv">$maxsize</span><span class="s2">: -j MARK --set-mark 0&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
		<span class="o">}</span>
	<span class="k">done</span>
	add_rules pktrules <span class="s2">&quot;</span><span class="nv">$rules</span><span class="s2">&quot;</span> <span class="s2">&quot;iptables -t mangle -A </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2">&quot;</span>
	<span class="k">for</span> iface in <span class="nv">$INTERFACES</span><span class="p">;</span> <span class="k">do</span>
		config_get classgroup <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> classgroup
		config_get device <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> device
		config_get imqdev <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> imqdev
		config_get dl <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> download
		config_get halfduplex <span class="s2">&quot;</span><span class="nv">$iface</span><span class="s2">&quot;</span> halfduplex
		add_insmod ipt_IMQ
		append up <span class="s2">&quot;iptables -t mangle -A OUTPUT -o </span><span class="nv">$device</span><span class="s2"> -j </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
		append up <span class="s2">&quot;iptables -t mangle -A FORWARD -o </span><span class="nv">$device</span><span class="s2"> -j </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
		<span class="o">[</span> -z <span class="s2">&quot;</span><span class="nv">$dl</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="o">{</span>
			<span class="o">[</span> -z <span class="s2">&quot;</span><span class="nv">$halfduplex</span><span class="s2">&quot;</span> <span class="o">]</span> <span class="o">||</span> <span class="o">{</span>
				append down <span class="s2">&quot;iptables -t mangle -A POSTROUTING -o </span><span class="nv">$device</span><span class="s2"> -j IMQ --todev </span><span class="nv">$imqdev</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
			<span class="o">}</span>
			append down <span class="s2">&quot;iptables -t mangle -A PREROUTING -i </span><span class="nv">$device</span><span class="s2"> -j </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
			append down <span class="s2">&quot;iptables -t mangle -A POSTROUTING -o </span><span class="nv">$device</span><span class="s2"> -j </span><span class="si">${</span><span class="nv">cg</span><span class="si">}</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
			append down <span class="s2">&quot;iptables -t mangle -A PREROUTING -i </span><span class="nv">$device</span><span class="s2"> -j IMQ --todev </span><span class="nv">$imqdev</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$N</span><span class="s2">&quot;</span>
		<span class="o">}</span>
	<span class="k">done</span>
	cat <span class="s">&lt;&lt;EOF</span>
<span class="s">$INSMOD</span>
<span class="s">iptables -t mangle -N ${cg} &gt;&amp;- 2&gt;&amp;-</span>
<span class="s">iptables -t mangle -N ${cg}_ct &gt;&amp;- 2&gt;&amp;-</span>
<span class="s">${iptrules:+${iptrules}${N}iptables -t mangle -A ${cg}_ct -j CONNMARK --save-mark}</span>
<span class="s">iptables -t mangle -A ${cg} -j CONNMARK --restore-mark</span>
<span class="s">iptables -t mangle -A ${cg} -m mark --mark 0 -j ${cg}_ct</span>
<span class="s">$pktrules</span>
<span class="s">$up$N${down:+${down}$N}</span>
<span class="s">EOF</span>
	<span class="nb">unset</span> INSMOD
<span class="o">}</span>

start_firewall<span class="o">()</span> <span class="o">{</span>
	add_insmod ipt_multiport
	add_insmod ipt_CONNMARK
	cat <span class="s">&lt;&lt;EOF</span>
<span class="s">iptables -t mangle -F</span>
<span class="s">iptables -t mangle -X</span>
<span class="s">EOF</span>
	<span class="k">for</span> group in <span class="nv">$CG</span><span class="p">;</span> <span class="k">do</span>
		start_cg <span class="nv">$group</span>
	<span class="k">done</span>
<span class="o">}</span>

<span class="nv">C</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="nv">INTERFACES</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
<span class="o">[</span> -e ./qos.conf <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="o">{</span>
	. ./qos.conf
	config_cb
<span class="o">}</span> <span class="o">||</span> config_load qos

<span class="nv">C</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="k">for</span> iface in <span class="nv">$INTERFACES</span><span class="p">;</span> <span class="k">do</span>
	<span class="nb">export</span> <span class="nv">C</span><span class="o">=</span><span class="s2">&quot;</span><span class="k">$((</span><span class="nv">$C</span> <span class="o">+</span> <span class="m">1</span><span class="k">))</span><span class="s2">&quot;</span>
<span class="k">done</span>

<span class="k">case</span> <span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span> in
	all<span class="o">)</span>
		start_interfaces <span class="s2">&quot;</span><span class="nv">$C</span><span class="s2">&quot;</span>
		start_firewall
	<span class="p">;;</span>
	interface<span class="o">)</span>
		start_interface <span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span> <span class="s2">&quot;</span><span class="nv">$C</span><span class="s2">&quot;</span>
	<span class="p">;;</span>
	interfaces<span class="o">)</span>
		start_interfaces
	<span class="p">;;</span>
	firewall<span class="o">)</span>
		start_firewall
	<span class="p">;;</span>
<span class="k">esac</span>
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2025-06-19 16:49:58 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
