Changeset 5014

Show
Ignore:
Timestamp:
07/07/09 00:03:18 (4 years ago)
Author:
jow
Message:

luci-0.9: merge r5007-r5013

Location:
luci/branches/luci-0.9
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • luci/branches/luci-0.9/applications/luci-splash/luasrc/controller/splash/splash.lua

    r4752 r5014  
    2525    local mac = luci.sys.net.ip4mac(ip:match("^[\[::ffff:]*(%d+.%d+%.%d+%.%d+)\]*$")) 
    2626    if mac and luci.http.formvalue("accept") then 
    27         os.execute("luci-splash add "..mac.." >/dev/null 2>&1") 
     27        os.execute("luci-splash lease "..mac.." >/dev/null 2>&1") 
    2828        luci.http.redirect(luci.model.uci.cursor():get("freifunk", "community", "homepage")) 
    2929    else 
     
    3636    local macs = luci.http.formvaluetable("save") 
    3737 
    38     local function delete_mac(what, mac) 
    39         uci:delete_all("luci_splash", what, 
    40             function(s) 
    41                 return ( s.mac and s.mac:lower() == mac ) 
    42             end) 
    43     end 
    44  
    45     local function leases(mac) 
    46         local leases = { } 
    47  
    48         uci:foreach("luci_splash", "lease", function(s) 
    49             if s.start and s.mac and s.mac:lower() ~= mac then 
    50                 leases[#leases+1] = { 
    51                     start = s.start, 
    52                     mac   = s.mac 
    53                 } 
    54             end 
    55         end) 
    56  
    57         uci:revert("luci_splash") 
    58  
    59         return leases 
    60     end 
    61  
    62     local function commit(leases, no_commit) 
    63         if not no_commit then 
    64             uci:save("luci_splash") 
    65             uci:commit("luci_splash") 
    66         end 
    67  
    68         for _, l in ipairs(leases) do 
    69             uci:section("luci_splash", "lease", nil, l) 
    70         end 
    71  
    72         uci:save("luci_splash") 
    73         os.execute("/etc/init.d/luci_splash restart") 
    74     end 
     38    local changes = {  
     39        whitelist = { }, 
     40        blacklist = { }, 
     41        lease     = { }, 
     42        remove    = { } 
     43    } 
    7544 
    7645    for key, _ in pairs(macs) do 
    7746        local policy = luci.http.formvalue("policy.%s" % key) 
    7847        local mac    = luci.http.protocol.urldecode(key) 
    79         local lslist = leases(policy ~= "kick" and mac) 
    80  
    81         delete_mac("blacklist", mac) 
    82         delete_mac("whitelist", mac) 
    8348 
    8449        if policy == "whitelist" or policy == "blacklist" then 
    85             uci:section("luci_splash", policy, nil, { mac = mac }) 
    86         elseif policy == "normal" then           
    87             lslist[#lslist+1] = { mac = mac, start = os.time() } 
    88         elseif policy == "kick" then 
    89             for _, l in ipairs(lslist) do 
    90                 if l.mac:lower() == mac then l.kicked="1" end 
    91             end 
     50            changes[policy][#changes[policy]+1] = mac 
     51        elseif policy == "normal" then 
     52            changes["lease"][#changes["lease"]+1] = mac 
     53        elseif policy == "kicked" then 
     54            changes["remove"][#changes["remove"]+1] = mac 
    9255        end 
     56    end 
    9357 
    94         commit(lslist) 
     58    if #changes.whitelist > 0 then 
     59        os.execute("luci-splash whitelist %s >/dev/null" 
     60            % table.concat(changes.whitelist)) 
     61    end 
     62 
     63    if #changes.blacklist > 0 then 
     64        os.execute("luci-splash blacklist %s >/dev/null" 
     65            % table.concat(changes.blacklist)) 
     66    end 
     67 
     68    if #changes.lease > 0 then 
     69        os.execute("luci-splash lease %s >/dev/null" 
     70            % table.concat(changes.lease)) 
     71    end 
     72 
     73    if #changes.remove > 0 then 
     74        os.execute("luci-splash remove %s >/dev/null" 
     75            % table.concat(changes.remove)) 
    9576    end 
    9677 
  • luci/branches/luci-0.9/applications/luci-splash/luasrc/view/admin_status/splash.htm

    r4855 r5014  
    3636                limit   = ( tonumber(s.start) + leasetime ), 
    3737                mac     = s.mac:upper(), 
     38                ipaddr  = s.ipaddr, 
    3839                policy  = "normal", 
    3940                packets = 0, 
    4041                bytes   = 0, 
    41                 kicked  = s.kicked and true or false 
    4242            } 
    4343        end 
     
    5959end 
    6060 
    61 for _, r in ipairs(ipt:find({table="filter", chain="luci_splash_filter", options={"MAC"}})) do 
    62     local c = clients[r.options[2]:lower()] 
    63     if c and c.packets == 0 then 
    64         c.bytes   = tonumber(r.bytes) 
    65         c.packets = tonumber(r.packets) 
     61for mac, client in pairs(clients) do 
     62    client.bytes_in    = 0 
     63    client.bytes_out   = 0 
     64    client.packets_in  = 0 
     65    client.packets_out = 0 
     66 
     67    if client.ipaddr then 
     68        local rin  = ipt:find({table="mangle", chain="luci_splash_mark_in", destination=client.ipaddr}) 
     69        local rout = ipt:find({table="mangle", chain="luci_splash_mark_out", options={"MAC", client.mac:upper()}}) 
     70 
     71        if rin and #rin > 0 then 
     72            client.bytes_in   = rin[1].bytes 
     73            client.packets_in = rin[1].packets 
     74        end 
     75 
     76        if rout and #rout > 0 then 
     77            client.bytes_out   = rout[1].bytes 
     78            client.packets_out = rout[1].packets 
     79        end 
    6680    end 
    6781end 
     
    124138                    <th class="cbi-section-table-cell"><%:ff_splash_mac MAC Address%></th> 
    125139                    <th class="cbi-section-table-cell"><%:ff_splash_timeleft Time remaining%></th> 
    126                     <th class="cbi-section-table-cell"><%:ff_splash_traffic Outgoing traffic%></th> 
     140                    <th class="cbi-section-table-cell"><%:ff_splash_traffic Traffic in/out%></th> 
    127141                    <th class="cbi-section-table-cell"><%:ff_splash_policy Policy%></th> 
    128142                </tr> 
     
    150164                                (c.policy ~= "normal") and "-" or "<em>" .. translate("ff_splash_expired", "expired") .. "</em>" 
    151165                        %></td> 
    152                         <td class="cbi-section-table-cell"><%=wat.byte_format(c.bytes)%></td> 
     166                        <td class="cbi-section-table-cell"><%=wat.byte_format(c.bytes_in)%> / <%=wat.byte_format(c.bytes_out)%></td> 
    153167                        <td class="cbi-section-table-cell"> 
    154168                            <% if is_admin then %> 
     
    158172                                <option value="blacklist"<%=c.policy=="blacklist" and ' selected="selected"'%>><%:ff_splash_blacklisted blacklisted%></option> 
    159173                                <% if c.policy == "normal" then -%> 
    160                                 <option value="kick"<%=c.kicked and ' selected="selected"'%>><%:ff_splash_tempblock temporarily blocked%> (<%=wat.date_format(c.limit-os.time())%>)</option> 
     174                                    <option value="kicked"><%:ff_splash_tempblock temporarily blocked%></option> 
    161175                                <%- end %> 
    162176                            </select> 
  • luci/branches/luci-0.9/applications/luci-splash/root/etc/init.d/luci_splash

    r4960 r5014  
    11#!/bin/sh /etc/rc.common 
     2 
    23START=70 
    34EXTRA_COMMANDS=clear_leases 
    4 SPLASH_INTERFACES="" 
    55LIMIT_DOWN=0 
    66LIMIT_DOWN_BURST=0 
    77LIMIT_UP=0 
    88 
     9IPT_REPLAY=/var/run/luci_splash.iptlog 
     10LOCK=/var/run/luci_splash.lock 
     11 
     12include /lib/network 
     13scan_interfaces 
     14config_load luci_splash 
     15 
    916silent() { 
    1017    "$@" 2>/dev/null 
     18} 
     19 
     20ipt_log() { 
     21    iptables -I "$@" 
     22    echo iptables -D "$@" >> $IPT_REPLAY 
    1123} 
    1224 
     
    3850    eval "$(ipcalc.sh $ipaddr $netmask)" 
    3951 
    40     iptables -t nat -A prerouting_${zone} -j luci_splash_prerouting 
    41     iptables -t nat -A luci_splash_prerouting -j luci_splash_portal 
    42  
    43     iptables -t filter -I luci_splash_filter -s ! "$NETWORK/$PREFIX" -j RETURN 
    44     iptables -t nat    -I luci_splash_leases -s ! "$NETWORK/$PREFIX" -j RETURN 
    45  
    46     iptables -t filter -I luci_splash_filter -s "$NETWORK/$PREFIX" -d "$ipaddr/${netmask:-32}" -j RETURN 
    47     iptables -t nat    -I luci_splash_leases -s "$NETWORK/$PREFIX" -d "$ipaddr/${netmask:-32}" -j RETURN 
    48  
     52    ### Add interface specific chain entry rules 
     53    ipt_log "zone_${zone}_prerouting" -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_prerouting -t nat 
     54    ipt_log "zone_${zone}_forward"    -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_forwarding -t filter 
     55 
     56    ### Allow traffic to the same subnet 
     57    iptables -t nat    -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN 
     58    iptables -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN 
     59 
     60    ### Allow traffic to the mesh subnet 
    4961    [ "$parentproto" = "static" -a -n "$parentipaddr" ] && { 
    50         iptables -t filter -I luci_splash_filter -s "$NETWORK/$PREFIX" -d "$parentipaddr/${parentnetmask:-32}" -j RETURN 
    51         iptables -t nat    -I luci_splash_leases -s "$NETWORK/$PREFIX" -d "$parentipaddr/${parentnetmask:-32}" -j RETURN 
    52     } 
    53  
    54     iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -p udp --dport 53 -j RETURN 
    55     iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -p tcp --dport 22 -j RETURN    # XXX: ssh really needed? 
    56     iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -p tcp --dport 80 -j RETURN 
    57     iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -j REJECT --reject-with icmp-admin-prohibited 
     62        iptables -t nat    -I luci_splash_prerouting -d "$parentipaddr/${parentnetmask:-32}" -j RETURN 
     63        iptables -t filter -I luci_splash_forwarding -d "$parentipaddr/${parentnetmask:-32}" -j RETURN 
     64    } 
    5865 
    5966    qos_iface_add "$ifname" 
    60  
    61     append SPLASH_INTERFACES "$ifname" 
    6267} 
    6368 
     
    6671    [ -n "$zone" ] || return 0 
    6772 
    68     while iptables -t nat -D prerouting_${zone} -j luci_splash_prerouting 2>&-; do :; done 
    69  
    7073    config_get net "$1" network 
    7174    [ -n "$net" ] || return 0 
     
    7477    [ -n "$ifname" ] || return 0 
    7578 
     79    # Clear interface specific rules 
     80    [ -s $IPT_REPLAY ] && { 
     81        grep -- "-i ${ifname%:*}" $IPT_REPLAY | while read ln; do silent $ln; done 
     82        sed -ie "/-i ${ifname%:*}/d" $IPT_REPLAY 
     83    } 
     84 
    7685    qos_iface_del "$ifname" 
    7786} 
    7887 
    79 blacklist_add() { 
    80     local cfg="$1" 
    81      
    82     config_get mac "$cfg" mac 
    83     [ -n "$mac" ] && { 
    84         iptables -t filter -I luci_splash_filter -m mac --mac-source "$mac" -j DROP 
    85         iptables -t nat    -I luci_splash_leases -m mac --mac-source "$mac" -j DROP 
    86     } 
    87 } 
    88  
    89 whitelist_add() { 
    90     local cfg="$1" 
    91      
    92     config_get mac "$cfg" mac 
    93     [ -n "$mac" ] && { 
    94         iptables -t filter -I luci_splash_filter -m mac --mac-source "$mac" -j RETURN 
    95         iptables -t nat    -I luci_splash_leases -m mac --mac-source "$mac" -j RETURN 
    96     } 
    97 } 
    98  
    99 lease_add() { 
    100     local cfg="$1" 
    101      
    102     config_get mac "$cfg" mac 
    103     config_get ban "$cfg" kicked 
    104  
    105     ban=${ban:+DROP} 
    106  
    107     [ -n "$mac" ] && { 
    108         local oIFS="$IFS"; IFS=":" 
    109         set -- $mac 
    110         IFS="$oIFS"; unset oIFS 
    111      
    112         local mac_pre="$1$2" 
    113         local mac_post="$3$4$5$6" 
    114         local handle="$6" 
    115  
    116         iptables -t filter -I luci_splash_filter -m mac --mac-source "$mac" -j RETURN 
    117         iptables -t nat    -I luci_splash_leases -m mac --mac-source "$mac" -j "${ban:-RETURN}" 
    118  
    119         [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && { 
    120             iptables -t mangle -I luci_splash_mark -m mac --mac-source "$mac" -j MARK --set-mark 79 
    121  
    122             for i in $SPLASH_INTERFACES; do 
    123                 tc filter add dev $i parent 77:0 protocol ip prio 2 handle ::$handle u32 \ 
    124                     match u16 0x0800 0xFFFF at -2 match u32 0x$mac_post 0xFFFFFFFF at -12 \ 
    125                     match u16 0x$mac_pre 0xFFFF at -14 flowid 77:10 
    126             done 
    127         } 
    128     } 
     88mac_add() { 
     89    config_get mac "$1" mac 
     90    append MACS "$mac" 
    12991} 
    13092 
     
    13698     
    13799    [ -n "$ipaddr" ] && { 
    138         iptables -t filter -I luci_splash_filter -d "$ipaddr/${netmask:-32}" -j RETURN 
    139         iptables -t nat    -I luci_splash_portal -d "$ipaddr/${netmask:-32}" -j RETURN 
     100        iptables -t nat    -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN 
     101        iptables -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN 
    140102    } 
    141103} 
     
    146108    # 77 -> download root qdisc 
    147109    # 78 -> upload root qdisc 
    148     # 79 -> fwmark 
     110    # 79 -> fwmark: client->inet 
     111    # 80 -> fwmark: inet->client 
    149112 
    150113    silent tc qdisc del dev "$iface" root handle 77: 
     
    158121        # set download limit and burst 
    159122        tc class add dev "$iface" parent 77:1 classid 77:10 htb \ 
    160             rate ${LIMIT_DOWN}kb ceil ${LIMIT_DOWN_BURST}kb prio 2 
     123            rate ${LIMIT_DOWN}kbit ceil ${LIMIT_DOWN_BURST}kbit prio 2 
    161124 
    162125        tc qdisc add dev "$iface" parent 77:10 handle 78: sfq perturb 10 
     
    165128        silent tc qdisc add dev "$iface" ingress 
    166129 
     130        # set client download speed 
     131        tc filter add dev "$iface" parent 77: protocol ip prio 2 \ 
     132            handle 80 fw flowid 77:10 
     133 
    167134        # set client upload speed 
    168135        tc filter add dev "$iface" parent ffff: protocol ip prio 1 \ 
    169             handle 79 fw police rate ${LIMIT_UP}kb mtu 6k burst 6k drop 
     136            handle 79 fw police rate ${LIMIT_UP}kbit mtu 6k burst 6k drop 
    170137    fi   
    171138} 
     
    181148boot() { 
    182149    ### Setup splash-relay 
    183     uci get lucid.splashr || { 
     150    uci get lucid.splashr 2>/dev/null || { 
    184151uci batch <<EOF 
    185152    set lucid.splashr=daemon 
     
    203170 
    204171start() { 
    205     ### Read chains from config 
    206     include /lib/network 
    207     scan_interfaces 
    208     config_load luci_splash 
    209      
     172    lock -w $LOCK && lock $LOCK 
     173 
    210174    ### Find QoS limits 
    211175    config_get LIMIT_UP general limit_up 
     
    213177    config_get LIMIT_DOWN_BURST general limit_down_burst 
    214178 
    215     LIMIT_UP="${LIMIT_UP:-0}" 
    216     LIMIT_DOWN="${LIMIT_DOWN:-0}" 
    217     LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:-$(($LIMIT_DOWN * 2))}" 
     179    LIMIT_UP="$((8*${LIMIT_UP:-0}))" 
     180    LIMIT_DOWN="$((8*${LIMIT_DOWN:-0}))" 
     181    LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:+$((8*$LIMIT_DOWN_BURST))}" 
     182    LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:-$(($LIMIT_DOWN / 5 * 6))}" 
    218183 
    219184    ### Load required modules 
     
    222187        silent insmod cls_u32 
    223188        silent insmod sch_htb 
     189        silent insmod sch_sfq 
    224190        silent insmod sch_ingress 
    225191    } 
    226192 
    227193    ### Create subchains 
     194    iptables -t nat    -N luci_splash_prerouting 
     195    iptables -t nat    -N luci_splash_leases 
     196    iptables -t filter -N luci_splash_forwarding 
    228197    iptables -t filter -N luci_splash_filter 
    229     iptables -t nat    -N luci_splash_portal 
    230     iptables -t nat    -N luci_splash_leases 
    231     iptables -t nat    -N luci_splash_prerouting 
    232  
    233     [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && \ 
    234         iptables -t mangle -N luci_splash_mark 
     198 
     199    ### Clear iptables replay log 
     200    [ -s $IPT_REPLAY ] && . $IPT_REPLAY 
     201    echo -n > $IPT_REPLAY 
    235202 
    236203    ### Build the main and portal rule 
    237204    config_foreach iface_add iface 
    238205    config_foreach subnet_add subnet 
    239     config_foreach blacklist_add blacklist 
    240     config_foreach whitelist_add whitelist 
    241     config_foreach lease_add lease 
    242      
    243     ### Build the portal rule 
    244     iptables -t filter -I INPUT      -j luci_splash_filter 
    245     iptables -t filter -I FORWARD    -j luci_splash_filter 
    246  
    247     [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && \ 
    248         iptables -t mangle -I PREROUTING -j luci_splash_mark 
    249  
    250     ### Allow icmp, dns and traceroute 
    251     iptables -t nat -A luci_splash_portal -p udp --dport 33434:33523 -j RETURN 
    252     iptables -t nat -A luci_splash_portal -p icmp -j RETURN 
    253     iptables -t nat -A luci_splash_portal -p udp --dport 53 -j RETURN 
    254  
    255     ### Redirect the rest into the lease chain 
    256     iptables -t nat -A luci_splash_portal -j luci_splash_leases 
    257      
    258     ### Build the leases rule 
     206 
     207    ### Add interface independant prerouting rules 
     208    iptables -t nat -A luci_splash_prerouting -j luci_splash_leases 
     209    iptables -t nat -A luci_splash_leases -p udp --dport 53 -j REDIRECT --to-ports 53 
    259210    iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082 
    260      
     211 
     212    ### Add interface independant forwarding rules 
     213    iptables -t filter -A luci_splash_forwarding -j luci_splash_filter 
     214    iptables -t filter -A luci_splash_filter -p tcp -j REJECT --reject-with tcp-reset 
     215    iptables -t filter -A luci_splash_filter -j REJECT --reject-with icmp-net-prohibited 
     216 
     217    ### Add QoS chain 
     218    [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && { 
     219        iptables -t mangle -N luci_splash_mark_out 
     220        iptables -t mangle -N luci_splash_mark_in 
     221        iptables -t mangle -I PREROUTING  -j luci_splash_mark_out 
     222        iptables -t mangle -I POSTROUTING -j luci_splash_mark_in 
     223    } 
     224 
     225    ### Find active mac addresses 
     226    MACS="" 
     227    config_foreach mac_add lease 
     228    config_foreach mac_add blacklist 
     229    config_foreach mac_add whitelist 
     230 
    261231    ### Add crontab entry 
    262232    test -f /etc/crontabs/root || touch /etc/crontabs/root 
     
    264234        echo '*/5 * * * *   /usr/sbin/luci-splash sync' >> /etc/crontabs/root 
    265235    } 
     236 
     237    lock -u $LOCK 
     238 
     239    ### Populate iptables 
     240    [ -n "$MACS" ] && luci-splash add-rules $MACS 
    266241} 
    267242 
    268243stop() { 
     244    lock -w $LOCK && lock $LOCK 
     245 
    269246    ### Clear interface rules 
    270     include /lib/network 
    271     scan_interfaces 
    272     config_load luci_splash 
    273247    config_foreach iface_del iface 
    274248 
    275     silent iptables -t filter -D INPUT      -j luci_splash_filter 
    276     silent iptables -t filter -D FORWARD    -j luci_splash_filter 
    277     silent iptables -t mangle -D PREROUTING -j luci_splash_mark 
     249    silent iptables -t mangle -D PREROUTING  -j luci_splash_mark_out 
     250    silent iptables -t mangle -D POSTROUTING -j luci_splash_mark_in 
    278251         
    279252    ### Clear subchains 
     253    silent iptables -t nat    -F luci_splash_prerouting 
    280254    silent iptables -t nat    -F luci_splash_leases 
    281     silent iptables -t nat    -F luci_splash_portal 
    282     silent iptables -t nat    -F luci_splash_prerouting 
     255    silent iptables -t filter -F luci_splash_forwarding 
    283256    silent iptables -t filter -F luci_splash_filter 
    284     silent iptables -t mangle -F luci_splash_mark 
     257    silent iptables -t mangle -F luci_splash_mark_out 
     258    silent iptables -t mangle -F luci_splash_mark_in 
    285259     
    286260    ### Delete subchains 
     261    silent iptables -t nat    -X luci_splash_prerouting 
    287262    silent iptables -t nat    -X luci_splash_leases 
    288     silent iptables -t nat    -X luci_splash_portal 
    289     silent iptables -t nat    -X luci_splash_prerouting 
     263    silent iptables -t filter -X luci_splash_forwarding 
    290264    silent iptables -t filter -X luci_splash_filter 
    291     silent iptables -t mangle -X luci_splash_mark 
     265    silent iptables -t mangle -X luci_splash_mark_out 
     266    silent iptables -t mangle -X luci_splash_mark_in 
    292267     
    293268    sed -ie '/\/usr\/sbin\/luci-splash sync/d' /var/spool/cron/crontabs/root 
    294 } 
    295  
    296      
     269 
     270    lock -u $LOCK 
     271} 
     272 
    297273clear_leases() { 
    298     stop 
    299     while uci -P /var/state del luci_splash.@lease[0] 2>&-;do :; done 
    300     start 
    301 } 
    302  
     274    ### Find active mac addresses 
     275    MACS="" 
     276    config_foreach mac_add lease 
     277 
     278    ### Clear leases 
     279    [ -n "$MACS" ] && luci-splash remove $MACS 
     280} 
     281 
  • luci/branches/luci-0.9/applications/luci-splash/root/usr/sbin/luci-splash

    r4855 r5014  
    33require("luci.util") 
    44require("luci.model.uci") 
     5require("luci.sys") 
    56require("luci.sys.iptparser") 
    67 
     
    89local uci = luci.model.uci.cursor_state() 
    910local ipt = luci.sys.iptparser.IptParser() 
    10  
    11 local splash_interfaces = { } 
     11local net = luci.sys.net 
     12 
    1213local limit_up = 0 
    1314local limit_down = 0 
    1415 
     16function lock() 
     17    os.execute("lock -w /var/run/luci_splash.lock && lock /var/run/luci_splash.lock") 
     18end 
     19 
     20function unlock() 
     21    os.execute("lock -u /var/run/luci_splash.lock") 
     22end 
     23 
    1524function main(argv) 
    16     local cmd = argv[1] 
    17     local arg = argv[2] 
     25    local cmd = table.remove(argv, 1) 
     26    local arg = argv[1] 
    1827 
    1928    limit_up = tonumber(uci:get("luci_splash", "general", "limit_up")) or 0 
    2029    limit_down = tonumber(uci:get("luci_splash", "general", "limit_down")) or 0 
    21      
    22     uci:foreach("luci_splash", "iface", function(s) 
    23         if s.network then 
    24             splash_interfaces[#splash_interfaces+1] = uci:get("network", s.network, "ifname") 
    25         end 
    26     end) 
    27  
    28     if cmd == "status" and arg then 
    29         if islisted("whitelist", arg) then 
    30             print("whitelisted") 
    31         elseif islisted("blacklist", arg) then 
    32             print("blacklisted") 
    33         else         
    34             local lease = haslease(arg) 
    35             if lease and lease.kicked then 
    36                 print("kicked") 
    37             elseif lease then 
    38                 print("lease") 
     30 
     31    if ( cmd == "lease" or cmd == "add-rules" or cmd == "remove" or 
     32         cmd == "whitelist" or cmd == "blacklist" ) and #argv > 0 
     33    then 
     34        lock() 
     35 
     36        local arp_cache      = net.arptable() 
     37        local leased_macs    = get_known_macs("lease") 
     38        local blacklist_macs = get_known_macs("blacklist") 
     39        local whitelist_macs = get_known_macs("whitelist") 
     40 
     41        for i, adr in ipairs(argv) do 
     42            local mac = nil 
     43            if adr:find(":") then 
     44                mac = adr:lower() 
    3945            else 
    40                 print("unknown") 
     46                for _, e in ipairs(arp_cache) do 
     47                    if e["IP address"] == adr then 
     48                        mac = e["HW address"] 
     49                        break 
     50                    end 
     51                end 
    4152            end 
    42         end 
    43         os.exit(0) 
    44     elseif cmd == "add" and arg then 
    45         if not haslease(arg) then 
    46             add_lease(arg) 
    47         else 
    48             print("already leased!") 
    49             os.exit(2) 
    50         end 
    51         os.exit(0) 
    52     elseif cmd == "remove" and arg then 
    53         remove_lease(arg) 
    54         os.exit(0)       
     53 
     54            if mac and cmd == "add-rules" then 
     55                if leased_macs[mac] then 
     56                    add_lease(mac, arp_cache, true) 
     57                elseif blacklist_macs[mac] then 
     58                    add_blacklist_rule(mac) 
     59                elseif whitelist_macs[mac] then 
     60                    add_whitelist_rule(mac) 
     61                end 
     62            elseif mac and ( cmd == "whitelist" or cmd == "blacklist" or cmd == "lease" ) then 
     63                if cmd ~= "lease" and leased_macs[mac] then 
     64                    print("Removing %s from leases" % mac) 
     65                    remove_lease(mac) 
     66                    leased_macs[mac] = nil 
     67                end 
     68 
     69                if cmd ~= "whitelist" and whitelist_macs[mac] then 
     70                    print("Removing %s from whitelist" % mac) 
     71                    remove_whitelist(mac) 
     72                    whitelist_macs[mac] = nil                    
     73                end 
     74 
     75                if cmd ~= "blacklist" and blacklist_macs[mac] then 
     76                    print("Removing %s from blacklist" % mac) 
     77                    remove_blacklist(mac) 
     78                    blacklist_macs[mac] = nil 
     79                end 
     80 
     81                if cmd == "lease" and not leased_macs[mac] then 
     82                    print("Adding %s to leases" % mac) 
     83                    add_lease(mac) 
     84                    leased_macs[mac] = true 
     85                elseif cmd == "whitelist" and not whitelist_macs[mac] then 
     86                    print("Adding %s to whitelist" % mac) 
     87                    add_whitelist(mac) 
     88                    whitelist_macs[mac] = true 
     89                elseif cmd == "blacklist" and not blacklist_macs[mac] then 
     90                    print("Adding %s to blacklist" % mac) 
     91                    add_blacklist(mac) 
     92                    blacklist_macs[mac] = true 
     93                else 
     94                    print("The mac %s is already %sed" %{ mac, cmd }) 
     95                end 
     96            elseif mac and cmd == "remove" then 
     97                if leased_macs[mac] then 
     98                    print("Removing %s from leases" % mac) 
     99                    remove_lease(mac) 
     100                    leased_macs[mac] = nil 
     101                elseif whitelist_macs[mac] then 
     102                    print("Removing %s from whitelist" % mac) 
     103                    remove_whitelist(mac) 
     104                    whitelist_macs[mac] = nil                    
     105                elseif blacklist_macs[mac] then 
     106                    print("Removing %s from blacklist" % mac) 
     107                    remove_blacklist(mac) 
     108                    blacklist_macs[mac] = nil 
     109                else 
     110                    print("The mac %s is not known" % mac) 
     111                end 
     112            else 
     113                print("Can not find mac for ip %s" % argv[i]) 
     114            end 
     115        end 
     116 
     117        unlock() 
     118        os.exit(0)   
    55119    elseif cmd == "sync" then 
    56120        sync() 
    57121        os.exit(0) 
     122    elseif cmd == "list" then 
     123        list() 
     124        os.exit(0) 
    58125    else 
    59         print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]") 
     126        print("Usage:") 
     127        print("\n  luci-splash list\n    List connected, black- and whitelisted clients") 
     128        print("\n  luci-splash sync\n    Synchronize firewall rules and clear expired leases") 
     129        print("\n  luci-splash lease <MAC-or-IP>\n    Create a lease for the given address") 
     130        print("\n  luci-splash blacklist <MAC-or-IP>\n    Add given address to blacklist") 
     131        print("\n  luci-splash whitelist <MAC-or-IP>\n    Add given address to whitelist") 
     132        print("\n  luci-splash remove <MAC-or-IP>\n    Remove given address from the lease-, black- or whitelist") 
     133        print("") 
     134 
    60135        os.exit(1)   
    61136    end 
    62137end 
    63138 
     139-- Get a list of known mac addresses 
     140function get_known_macs(list) 
     141    local leased_macs = { } 
     142 
     143    if not list or list == "lease" then 
     144        uci:foreach("luci_splash", "lease", 
     145            function(s) leased_macs[s.mac:lower()] = true end) 
     146    end 
     147 
     148    if not list or list == "whitelist" then 
     149        uci:foreach("luci_splash", "whitelist", 
     150            function(s) leased_macs[s.mac:lower()] = true end) 
     151    end 
     152 
     153    if not list or list == "blacklist" then 
     154        uci:foreach("luci_splash", "blacklist", 
     155            function(s) leased_macs[s.mac:lower()] = true end) 
     156    end 
     157 
     158    return leased_macs 
     159end 
     160 
     161 
     162-- Get a list of known ip addresses 
     163function get_known_ips(macs, arp) 
     164    local leased_ips = { } 
     165    if not macs then macs = get_known_macs() end 
     166    for _, e in ipairs(arp or net.arptable()) do 
     167        if macs[e["HW address"]] then leased_ips[e["IP address"]] = true end 
     168    end 
     169    return leased_ips 
     170end 
     171 
     172 
     173-- Helper to delete iptables rules 
     174function ipt_delete_all(args, comp, off) 
     175    off = off or { } 
     176    for i, r in ipairs(ipt:find(args)) do 
     177        if comp == nil or comp(r) then 
     178            off[r.table] = off[r.table] or { } 
     179            off[r.table][r.chain] = off[r.table][r.chain] or 0 
     180 
     181            os.execute("iptables -t %q -D %q %d 2>/dev/null" 
     182                %{ r.table, r.chain, r.index - off[r.table][r.chain] }) 
     183 
     184            off[r.table][r.chain] = off[r.table][r.chain] + 1 
     185        end 
     186    end 
     187end 
     188 
     189 
    64190-- Add a lease to state and invoke add_rule 
    65 function add_lease(mac) 
    66     uci:section("luci_splash", "lease", nil, { 
    67         mac = mac, 
    68         start = os.time() 
    69     }) 
    70     add_rule(mac) 
    71      
    72     uci:save("luci_splash") 
     191function add_lease(mac, arp, no_uci) 
     192    mac = mac:lower() 
     193 
     194    -- Get current ip address 
     195    local ipaddr 
     196    for _, entry in ipairs(arp or net.arptable()) do 
     197        if entry["HW address"] == mac then 
     198            ipaddr = entry["IP address"] 
     199            break 
     200        end 
     201    end 
     202 
     203    -- Add lease if there is an ip addr 
     204    if ipaddr then 
     205        if not no_uci then 
     206            uci:section("luci_splash", "lease", nil, { 
     207                mac    = mac, 
     208                ipaddr = ipaddr, 
     209                start  = os.time() 
     210            }) 
     211            uci:save("luci_splash") 
     212        end 
     213        add_lease_rule(mac, ipaddr) 
     214    else 
     215        print("Found no active IP for %s, lease not added" % mac) 
     216    end 
    73217end 
    74218 
     
    77221function remove_lease(mac) 
    78222    mac = mac:lower() 
    79     remove_rule(mac) 
    80223 
    81224    uci:delete_all("luci_splash", "lease", 
    82         function(s) return ( s.mac:lower() == mac ) end) 
     225        function(s) 
     226            if s.mac:lower() == mac then 
     227                remove_lease_rule(mac, s.ipaddr) 
     228                return true 
     229            end 
     230            return false 
     231        end) 
    83232         
    84233    uci:save("luci_splash") 
     
    86235 
    87236 
     237-- Add a whitelist entry 
     238function add_whitelist(mac) 
     239    uci:section("luci_splash", "whitelist", nil, { mac = mac }) 
     240    uci:save("luci_splash") 
     241    uci:commit("luci_splash") 
     242    add_whitelist_rule(mac) 
     243end 
     244 
     245 
     246-- Add a blacklist entry 
     247function add_blacklist(mac) 
     248    uci:section("luci_splash", "blacklist", nil, { mac = mac }) 
     249    uci:save("luci_splash") 
     250    uci:commit("luci_splash") 
     251    add_blacklist_rule(mac) 
     252end 
     253 
     254 
     255-- Remove a whitelist entry 
     256function remove_whitelist(mac) 
     257    mac = mac:lower() 
     258    uci:delete_all("luci_splash", "whitelist", 
     259        function(s) return not s.mac or s.mac:lower() == mac end) 
     260    uci:save("luci_splash") 
     261    uci:commit("luci_splash") 
     262    remove_lease_rule(mac) 
     263end 
     264 
     265 
     266-- Remove a blacklist entry 
     267function remove_blacklist(mac) 
     268    mac = mac:lower() 
     269    uci:delete_all("luci_splash", "blacklist", 
     270        function(s) return not s.mac or s.mac:lower() == mac end) 
     271    uci:save("luci_splash") 
     272    uci:commit("luci_splash") 
     273    remove_lease_rule(mac) 
     274end 
     275 
     276 
    88277-- Add an iptables rule 
    89 function add_rule(mac) 
    90     local a, b, c, d, e, f = mac:match("(%w+):(%w+):(%w+):(%w+):(%w+):(%w+)") 
    91     local mac_pre  = "%s%s" %{ a, b } 
    92     local mac_post = "%s%s%s%s" %{ c, d, e, f } 
    93     local handle   = f 
    94  
     278function add_lease_rule(mac, ipaddr) 
    95279    if limit_up > 0 and limit_down > 0 then 
    96         os.execute("iptables -t mangle -I luci_splash_mark -m mac --mac-source %q -j MARK --set-mark 79" % mac) 
    97  
    98         for _, i in ipairs(splash_interfaces) do 
    99             os.execute("tc filter add dev %q parent 77:0 protocol ip prio 2 " % i ..  
    100                 "handle ::%q u32 " % handle .. 
    101                 "match u16 0x0800 0xFFFF at -2 match u32 0x%q 0xFFFFFFFF at -12 " % mac_post .. 
    102                 "match u16 0x%q 0xFFFF at -14 flowid 77:10" % mac_pre) 
    103         end 
     280        os.execute("iptables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j MARK --set-mark 79" % mac) 
     281        os.execute("iptables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 80" % ipaddr) 
    104282    end 
    105283 
    106284    os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac) 
    107     return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac) 
    108 end 
    109  
    110  
    111 -- Remove an iptables rule 
    112 function remove_rule(mac) 
    113     local handle = mac:match("%w+:%w+:%w+:%w+:%w+:(%w+)") 
    114  
    115     local function ipt_delete_foreach(args) 
    116         for _, r in ipairs(ipt:find(args)) do 
    117             os.execute("iptables -t %q -D %q -m mac --mac-source %q %s 2>/dev/null" 
    118                 %{ r.table, r.chain, mac, 
    119                     r.target == "MARK" and "-j MARK --set-mark 79" or 
    120                         r.target and "-j %q" % r.target or "" }) 
    121         end 
    122     end 
    123  
    124     ipt_delete_foreach({table="filter", chain="luci_splash_filter", options={"MAC", mac:upper()}}) 
    125     ipt_delete_foreach({table="mangle", chain="luci_splash_mark", options={"MAC", mac:upper()}}) 
    126     ipt_delete_foreach({table="nat", chain="luci_splash_leases", options={"MAC", mac:upper()}}) 
    127  
    128     for _, i in ipairs(splash_interfaces) do 
    129         os.execute("tc filter del dev %q parent 77:0 protocol ip prio 2 " % i ..  
    130             "handle 800::%q u32 2>/dev/null" % handle) 
    131     end 
    132  
     285    os.execute("iptables -t nat    -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac) 
     286end 
     287 
     288 
     289-- Remove lease, black- or whitelist rules 
     290function remove_lease_rule(mac, ipaddr) 
    133291    ipt:resync() 
    134 end 
    135  
    136  
    137 -- Check whether a MAC-Address is listed in the lease state list 
    138 function haslease(mac) 
    139     mac = mac:lower() 
    140     local lease = nil 
    141  
    142     uci:foreach("luci_splash", "lease", 
    143         function (section) 
    144             if section.mac:lower() == mac then 
    145                 lease = section 
    146             end 
    147         end) 
    148  
    149     return lease 
    150 end 
    151  
    152  
    153 -- Check whether a MAC-Address is in given list 
    154 function islisted(what, mac) 
    155     mac = mac:lower() 
    156  
    157     uci:foreach("luci_splash", what, 
    158         function (section) 
    159             if section.mac:lower() == mac then 
    160                 stat = true 
    161                 return 
    162             end 
    163         end) 
    164  
    165     return false 
    166 end 
    167  
    168  
    169 -- Returns a list of MAC-Addresses for which a rule is existing 
    170 function listrules() 
    171     local macs = { } 
    172     for i, r in ipairs(ipt:find({table="nat", chain="luci_splash_leases", options={"MAC"}})) do 
    173         macs[r.options[2]:lower()] = true 
    174     end 
    175     return luci.util.keys(macs) 
     292 
     293    if ipaddr then 
     294        ipt_delete_all({table="mangle", chain="luci_splash_mark_in",  destination=ipaddr}) 
     295        ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", mac:upper()}}) 
     296    end 
     297 
     298    ipt_delete_all({table="filter", chain="luci_splash_filter",   options={"MAC", mac:upper()}}) 
     299    ipt_delete_all({table="nat",    chain="luci_splash_leases",   options={"MAC", mac:upper()}}) 
     300end 
     301 
     302 
     303-- Add whitelist rules 
     304function add_whitelist_rule(mac) 
     305    os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac) 
     306    os.execute("iptables -t nat    -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac) 
     307end 
     308 
     309 
     310-- Add blacklist rules 
     311function add_blacklist_rule(mac) 
     312    os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac) 
     313    os.execute("iptables -t nat    -I luci_splash_leases -m mac --mac-source %q -j DROP" % mac) 
    176314end 
    177315 
     
    179317-- Synchronise leases, remove abandoned rules 
    180318function sync() 
    181     local written = {} 
     319    lock() 
     320 
    182321    local time = os.time() 
    183      
     322 
    184323    -- Current leases in state files 
    185324    local leases = uci:get_all("luci_splash") 
     
    192331    uci:revert("luci_splash") 
    193332     
    194      
    195333    -- For all leases 
    196334    for k, v in pairs(leases) do 
     
    198336            if os.difftime(time, tonumber(v.start)) > leasetime then 
    199337                -- Remove expired 
    200                 remove_rule(v.mac) 
     338                remove_lease_rule(v.mac, v.ipaddr) 
    201339            else 
    202340                -- Rewrite state 
    203341                uci:section("luci_splash", "lease", nil, {       
    204342                    mac    = v.mac, 
    205                     start  = v.start, 
    206                     kicked = v.kicked 
     343                    ipaddr = v.ipaddr, 
     344                    start  = v.start 
    207345                }) 
    208                 written[v.mac:lower()] = 1 
    209346            end 
    210         elseif v[".type"] == "whitelist" or v[".type"] == "blacklist" then 
    211             written[v.mac:lower()] = 1 
    212         end 
    213     end 
    214      
    215      
    216     -- Delete rules without state 
    217     for i, r in ipairs(listrules()) do 
    218         if #r > 0 and not written[r:lower()] then 
    219             remove_rule(r) 
    220         end 
    221     end 
    222      
    223     uci:save("luci_splash") 
     347        end 
     348    end 
     349 
     350    uci:save("luci_splash") 
     351 
     352    -- Get current IPs and MAC addresses 
     353    local macs = get_known_macs() 
     354    local ips  = get_known_ips(macs) 
     355 
     356    ipt:resync() 
     357 
     358    ipt_delete_all({table="filter", chain="luci_splash_filter", options={"MAC"}}, 
     359        function(r) return not macs[r.options[2]:lower()] end) 
     360 
     361    ipt_delete_all({table="nat", chain="luci_splash_leases", options={"MAC"}}, 
     362        function(r) return not macs[r.options[2]:lower()] end) 
     363 
     364    ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", "MARK", "set"}}, 
     365        function(r) return not macs[r.options[2]:lower()] end) 
     366 
     367    ipt_delete_all({table="mangle", chain="luci_splash_mark_in", options={"MARK", "set"}}, 
     368        function(r) return not ips[r.destination] end) 
     369 
     370    unlock() 
     371end 
     372 
     373-- Show client info 
     374function list() 
     375    -- Get current arp cache 
     376    local arpcache = { } 
     377    for _, entry in ipairs(net.arptable()) do 
     378        arpcache[entry["HW address"]] = { entry["Device"], entry["IP address"] } 
     379    end 
     380 
     381    -- Find traffic usage 
     382    local function traffic(lease) 
     383        local traffic_in  = 0 
     384        local traffic_out = 0 
     385 
     386        local rin  = ipt:find({table="mangle", chain="luci_splash_mark_in", destination=lease.ipaddr}) 
     387        local rout = ipt:find({table="mangle", chain="luci_splash_mark_out", options={"MAC", lease.mac:upper()}}) 
     388 
     389        if rin  and #rin  > 0 then traffic_in  = math.floor( rin[1].bytes / 1024) end 
     390        if rout and #rout > 0 then traffic_out = math.floor(rout[1].bytes / 1024) end 
     391 
     392        return traffic_in, traffic_out 
     393    end 
     394 
     395    -- Print listings 
     396    local leases = uci:get_all("luci_splash") 
     397 
     398    print(string.format( 
     399        "%-17s  %-15s  %-9s  %-4s  %-7s  %20s", 
     400        "MAC", "IP", "State", "Dur.", "Intf.", "Traffic down/up" 
     401    )) 
     402 
     403    -- Leases 
     404    for _, s in pairs(leases) do 
     405        if s[".type"] == "lease" and s.mac then 
     406            local ti, to = traffic(s) 
     407            local mac = s.mac:lower() 
     408            local arp = arpcache[mac] 
     409            print(string.format( 
     410                "%-17s  %-15s  %-9s  %3dm  %-7s  %7dKB  %7dKB", 
     411                mac, s.ipaddr, "leased", 
     412                math.floor(( os.time() - tonumber(s.start) ) / 60), 
     413                arp and arp[1] or "?", ti, to 
     414            )) 
     415        end 
     416    end 
     417 
     418    -- Whitelist, Blacklist 
     419    for _, s in luci.util.spairs(leases, 
     420        function(a,b) return leases[a][".type"] > leases[b][".type"] end 
     421    ) do 
     422        if (s[".type"] == "whitelist" or s[".type"] == "blacklist") and s.mac then 
     423            local mac = s.mac:lower() 
     424            local arp = arpcache[mac] 
     425            print(string.format( 
     426                "%-17s  %-15s  %-9s  %4s  %-7s  %9s  %9s", 
     427                mac, arp and arp[2] or "?", s[".type"], "- ", 
     428                arp and arp[1] or "?", "-", "-" 
     429            )) 
     430        end 
     431    end 
    224432end 
    225433 
  • luci/branches/luci-0.9/libs/lucid/luasrc/lucid.lua

    r4681 r5014  
    107107function run() 
    108108    local pollint = tonumber((cursor:get(UCINAME, "main", "pollinterval"))) 
     109    local threadlimit = tonumber(cursor:get(UCINAME, "main", "threadlimit")) 
    109110 
    110111    while true do 
    111         local stat, code = nixio.poll(pollt, pollint) 
    112          
    113         if stat and stat > 0 then 
    114             for _, polle in ipairs(pollt) do 
    115                 if polle.revents ~= 0 and polle.handler then 
    116                     polle.handler(polle) 
     112        if not threadlimit or tcount < threadlimit then 
     113            local stat, code = nixio.poll(pollt, pollint) 
     114         
     115            if stat and stat > 0 then 
     116                for _, polle in ipairs(pollt) do 
     117                    if polle.revents ~= 0 and polle.handler then 
     118                        polle.handler(polle) 
     119                    end 
    117120                end 
     121            elseif stat == 0 then 
     122                ifaddrs = nixio.getifaddrs() 
     123                collectgarbage("collect") 
    118124            end 
    119         elseif stat == 0 then 
    120             ifaddrs = nixio.getifaddrs() 
    121             collectgarbage("collect") 
    122125        end 
    123126         
  • luci/branches/luci-0.9/libs/lucid/root/etc/config/lucid

    r4823 r5014  
    11config lucid main 
    22    option pollinterval 15000 
    3     option threadlimit 25 
     3    option threadlimit 10 
    44    option daemonize 1 
    55    option debug 0 
  • luci/branches/luci-0.9/po/de/freifunk.po

    r4951 r5014  
    44"Report-Msgid-Bugs-To: \n" 
    55"POT-Creation-Date: 2009-06-30 06:43+0200\n" 
    6 "PO-Revision-Date: 2009-06-30 06:47+0200\n" 
     6"PO-Revision-Date: 2009-07-07 00:31+0200\n" 
    77"Last-Translator: Jo-Philipp Wich <xm@subsignal.org>\n" 
    88"Language-Team: LANGUAGE <LL@li.org>\n" 
     
    126126#. Client-Splash 
    127127msgid "ff_splash" 
    128 msgstr "Client-Splash" 
     128msgstr "Verkehr (down/up)" 
    129129 
    130130#. Active Clients 
  • luci/branches/luci-0.9/po/en/freifunk.po

    r4951 r5014  
    44"Report-Msgid-Bugs-To: \n" 
    55"POT-Creation-Date: 2009-06-30 06:42+0200\n" 
    6 "PO-Revision-Date: 2009-06-30 06:43+0200\n" 
     6"PO-Revision-Date: 2009-07-06 23:21+0200\n" 
    77"Last-Translator: Jo-Philipp Wich <xm@subsignal.org>\n" 
    88"Language-Team: LANGUAGE <LL@li.org>\n" 
     
    148148#. Outgoing traffic 
    149149msgid "ff_splash_traffic" 
    150 msgstr "Outgoing traffic" 
     150msgstr "Traffic (down/up)" 
    151151 
    152152#. Policy 
  • luci/branches/luci-0.9/po/templates/freifunk.pot

    r4951 r5014  
    133133msgstr "" 
    134134 
    135 #. Outgoing traffic 
     135#. Traffic (in/out) 
    136136msgid "ff_splash_traffic" 
    137137msgstr ""