OK, turing.

<- leave blank

Wed Jan 17 14:02:01 EST 2018

#16 "?63(o+?50;+'51;'# #@"/*"r"{\D-v e-'[fa5.q]PkPPX)\( 9 '#CO"14"^ 92*/
#/*0|7//```"` [>.>.])[-'][( 7 >77*,68*,@'_ 7 )(22)S/ \ 5 \7aa*+42@n; 7
999993 1 7 3 1 8 1 1 55 EEEEEδΘΔΔΔΘΔΘλiiipsddpsdoh k zzzzkf kf k zzzzzd kf k
zzzzza kf bfz(coding=utf8
1P''53'S^'????!?!??!??!!!!???!?!??!!?!?!!!!!?!!!!?????!????????????????????!
#>c#z#111#y#y#y#_#1111x -x xxxxxxxxxxxxxxxxxxxxxxxxx/112\
# 36!@ ` e ++++++::@ /"78"oo@ h#115 o# dO x-----
#comment -[af] tAtAtA
TbTbTbRtRtRt-VkVkVkRcRcRcBkBkBkMbMbMbPSPSPSpspspsQhQhQhQrQrQrHnHnHnbqbqbqLzLzLzTcTcTcxxxxx8=,
#~==++++++ ++++++++++++++++++++++ +++++++++++++++++++++.._+++++++.
#`<`=============================================================== p
#<<<#>>]+-}}[.^+;;+;;+;;+<>;;+;;+;;+;;;;;;+;;+;;.._]}--<^>++[+++++[>+++++++<-]>._++++._+++._^<]+-+<[<<._>>x>-]^>[
#{
#cs}
#2""/*\*
#=x<R+++++[D>+++++++9999 9 9
L+++<-][PLACET,2<-#2FAC,2SUB#1<-#52FAC,2SUB#2<-#32FACREADOUT,2PLEASEGIVEUPFACs]_>@@+.---@._+>][
#x%+>+=ttt_Z_*.9 999 99 9999 9 _ _ _
#D>xU/-<+++L_9
#R+.----._>]| 9 9999
#[#[(+?+?0l0v01k1kMoOMoOMoOMoOMOOx0l0ix0jor0h0h1d111
0eU0y0yx0moO1d0y0e0e00m1d0i0fx0g0n0n11yxMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOmOotMOo0moo0n0tx0t0moO0fx4O6O@
0t0gOOM0g0f0h0j0j0i000x1k1x0vx0v0l111111^_0 )000011100\\
[ "`e```.1'.0'.6''i]56pq{}26q[puts 59][exit]" ,'_\['];#/s\\/;print"24";
exit}}__DATA__/
###x<$+@+-@@@@=>+<@@@=>+<?#d>;?\:-._++._++++._#/<?\>3-++._6+---2._#</++++++++++++++++++++++++++++++++++++++++++++++++._++._++++++.>!\
'(wWWWwWWWWwvwWWwWWWwvwWWWwWWWW\WWWWwWWWWwWWWWW/WW\wWWWWWWWWwwwwvwWW/WwWWWWwvwWWwWWWwvwWWwWWWwvwWWwWWWwx
(([5]{})))\';';print(( eval("1\x2f 2")and(9)or 13<< (65 )>>65or
68)-(0and eval("\"ppp\".bytes.class==Array and(4)or(95==\"ar_\"[2]and 5-96
or-93)"))^1<<(65)>>62) or"'x"or'
{}{}{}{}{}{}{}({}<(((((()()())){}{}) ){}{})>)(({})5){}x{(
<(<()>)({})({}<{}>({}){})>){({}[()])}}({}){}({}()<()()()>)wWW
ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho ho
ho ho ho dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO
dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO dO MU s
'#}#(prin
45)(bye)46(8+9+9+9+9+=!)((("3'3)))"'a'[[@*3*74[?]*.*]*.*(<\>]xxxxxxxxxxxxxxxxxxx)'#
\\
__DATA__=1#"'x"
#.;R"12"'
###;console.log 39;
# \\
""""# \
' ( <>< ( x)> ){ ({}[( )] )}{\'; a=$(printf \\x00 ) ;b=${#a};#\\
" }"'; (( ( (';case "{"$ar[1]"}"${b} in *1)echo 54;;*4)echo
$((19629227668178112600/ 118248359446856100));; *1*)echo 50;;*)echo
58;;esac;exit;#( (((') )))#\
=begin
#p +555!/2+55x%6E2x!<******>**********************828+*+@[*99[?]*]*****|!
;set print "-";print 89;exit#ss e$P+ + + + + *D* + + +1+ +1E!s
p now 70 dollar off!
p has been selling out worldwide!
[mxf]-main=-[165]-###jxf
#
seeeemPaeueewuuweeeeeeeeeeCisajjappppppxf⠆⠄⡒⡆⡘😆😨😒😨💬95💬👥➡😻😹😸🙀🙀😹😼😿🙀🙀😼😼😸🙀🙀🙀🙀
👋🔢🌚🌝🌝🌚🌚🌚🌚🌚▲▲▲²²²²▲¡▼¡▲▲¡→
밠밠따빠빠맣박다맣받다맣희맣희うんたんたんたんたんうんうんうんうんうんたんうんうんうんたんうんたんたんうんたんたんうんたんたんうんたんたんうんたんたんたんたんたんうんうんうんうんたんたんうんたんたんたんうんうんうんたんうんうんたんうんうんたんうんうんたんうんたんうんうんうんたんたんうんたんたんうんたんたんうんたんたんうんたんたんたんうんうん
😊♈💖
😇♈♈
😊♉♈
😇♈♈
😇♈♉
😇♈💜
😊♉♈
😊📢♈
😈♈💜
😊📢♈
😇♉💞
😊📢♉⠀⢃⠛⠋
#-49,A,-1 #
#-5,A,-1 #
#6,A,-1 #
1 ! !
2 ! !
1 !!
1 x*
53 ++-------+
1 x*|$0011 \|
51 +|/1000 /|
1 x*|\ 0011\|
34 +|/01 00/|
15 +|\ 0011\| ? ?@ _ !
1 *|@ 0110/| ?@ ?
1 | +| + *
1 !+-------+--- ? ! ?
1 ! ? @ ?
< < << < <
< B= ===== =>8 =
, 8= > B = =
= == = = > 8 =
D B+ += D x xxx x
` ` + = > 8 = >
 x ~ B = = = = > ~
 B + = D+ ~ 8 = >x
x x x x x xx x
x x x+ xx x + + + + +
x x xx xx +++ +
x+ +x +x x + + + +
 8=+, _ + + + +
   + + + + +
 + + + + + + + +
   + + + +
   + + + + + +
   + + +
   + + + + +
   + + + +
	  + + +
# + + +
#+ + ++ + + +
# + + +
+#
  * +
  *+*

   *************************************************+
# + +
# + +
   + + *
	 *****+
# + +
# + +
  * *
   +*****
# +
   ( printout t 164 )
(exit )
#cepp
MsgBox(0,"",169 )
#cs
Yo::=~147
::=
You can see an x here.<<<<

>{-<<
>SET x TO 120.  [0]{472454523665721469465830106052219449897}
>X x.  PPQ-}
>x--/2
> =157;y=146--/2
>main=print y{-ss

\begin{code}
{-x





-}
open import IO;main = run (putStr"159" ) --s
\end{code}
pppppppppppp
Take Northern Line to Tooting Bec
Take Northern Line to Charing Cross
Take Northern Line to Charing Cross
Take Northern Line to Bank
Take District Line to Hammersmith
Take District Line to Upminster
Take District Line to Hammersmith
Take District Line to Upminster
Take District Line to Embankment
Take Bakerloo Line to Embankment
7 UP
Take Northern Line to Mornington Crescent
7 RIGHT
7 RIGHT
7 TEACH
6 BOND
6 BOND
6 BOND
5 RIGHT
5 LEFT
5 RIGHT
7 BOND
7 TEACH
5 TEACH
6 YELL
5 TEACH
6 YELL
6 YELL
set ! 57,,...,,.,,..,,,,,,..,,,.$^
set ! 51.  #"6027"1,_ye do{--}gibe16"124"+*sizeString tnd xfmain=9717 96lo
More 91 of this red down one blue up red down one blue up red up one red right two
blue up ssswwwWWWwWWWWWwWWWWWWWwWWWWWWWWW baa
baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bleeeeeeeeeeeeet
bleeeeeeeeeeeeet bleeeeeeeeeet baaaa bleet bleeeeeeeeeet bleeet bleeeeeeeeeet
How much is it*/
#if 0
.int 2298589328,898451655,12,178790,1018168591,84934449,12597
#endif//*
#1""//*
#include<stdio.h>
#define x(d) #d
#define u8 "38\0 "//"
char*x="24 10 31 1"
"a c #FFC0FF""B c #0000C0""d c #58007B""e c #0C8302"
"h c #E60001""i c #CAFFFF""j c #280000""k c #CA0000""l c #CA007F""n c #330001 ""q
c #E60000"
"o c #FF8000""t c #FF00BC""u c #008080"
"A c #0040C0""E c #808000""F c #00C040""G c #008000 ""R c #800000"
"H c #0000AA""I c #00AA00""J c #55FFFF""K c #AAAAAA"
"r c red""g c green""b c blue""c c cyan""m c magenta""y c #FFFF00""x c black""_ c
#FFFFFF"
"HHHahtdegggggggyrggggggc"
"IHHaixuEFbGGbggbryAEGRgc"
"JJHajyurbgbgggggggb____o"
"IJHakmyyyyyyyyyyyyyyyyye"
"I__almyyyyyyyyyyyyyyyyye"
"K__anmyyyyyyyyyyyyyy_y_e"
"HH_aqggyyyyyyyyg____m_Je"
"JH_axxxxxxxxxxxxxxxxxxxx"
"K__aaaam___bbbbbBm_bbBab"
"K__________bbbbb___bbxbb";//"
int f(char*a,char*b ){ puts(a?"124":sizeof(0,u8)-5?u8"67":*u8""?"37": x( 0'0
"'\"")[9]?"75":'??-'&1?  "79":"77" );}main(){f(x,x=0);}//<*/
#1""/*/

>data B=B Integer--WWWWWWWWWWWWWW<<W<p
>instance Eq B where{-[ppWWWWWWWWWWWWay Uce stagehere]-}(B a )== (B b)=a==b
>instance Num B where{ fromInteger=B;negate ( B a )=B$a+1}
>main=print$last$169+1:[128|B 2==head [(-1 )::B]]--}


#1""/*/
#if 0
#endif//* --...  ...--
/*/
p=sizeof(" (\"); print'(''72'')';end!" );main(){ puts('??-'&1?"101":"92");return
0;}
#if 0
#endif//* rk:start | print: "69" rk:end
@,-1,:*b5<>
print 61
#}
disp 49
#{
}{}<> K yya+- & g+$
$'main'3x A=AgRA; AC
#-3o4o#$$$
#<T>"3"O._</+++++++>/+++<-\>+++.---.\_<!+++++++++++++++++++++++++++++++++++++++++++++++++._++.-.>@
#<<<#>>> /
reg end="";print(85);reg
s#++++++++++++++++++++++++++++++++++++++++++++++++++++++++.-.
=end
;"""#"#xxxxclou"78"<\++++>/<~#class P{function:Main (a:String[]
)~Nil{83->Print(); }}
#endcOmment
#nocOmment outtext("155" )
#ce pS9^7^8^MUOUOF @0:8:8 \ @,,1'1'<> @125iRE
# |o51~nJ;#:p'34'3 \=#print( size([[1] [3]][1,:] )[1]==2?158+4:17 )#>say
27#p>>>say 170-3#]#print(47)#]#echo 21#v>++++
#8M`| <esc>dggi2<esc>// $}<}}<}>}
[<<}<<<<<}<<}<<<<}<<<}}}<}}<}}<}}<
}}<}}<}}}<}}<<<<<<<<<<<}}}<}}<}}<}}<}}<}}<}}}<<<<<<<<<<}+++++++++++++++++++++++++++++++++++++++++++++++++._++.._#]~-<~-<~-<<<~-<COprint("65")#`=>ass^_^_#
#9 "25" +/ppppppp ggeeee*n*n*n*es^*s*s*ee*n*n*n*e*sss*e*n*n*n*ee<*s 5>1
*e*///\)Q222999686#


Wed Jan 17 12:17:57 EST 2018
use std

impl disposable int =
	__dispose__ = {n
		std.put("Disposing of {}\n", n)
	}
;;

impl disposable (-> void) =
	__dispose__ = {f; f()}
;;

const f = {b
	var x = 1
	auto x++
	if b
		-> void
	;;
	auto x++
}

const g = {n
	auto (40 + 2)
	while n > 0
		auto n--
		if n <= 0
			-> void
		;;
		auto n--
	;;
}

const main = {
	auto {
		std.put("Tchuss!\n");
	}
	f(true)
	std.put("-- \n")
	f(false)
	std.put("-- \n")
	g(2)
	std.put("-- \n")
	g(3)
}


Wed Jan 17 12:15:18 EST 2018
Disposing of 1
--
Disposing of 2
Disposing of 1
--
Disposing of 1
Disposing of 2
Disposing of 42
--
Disposing of 2
Disposing of 3
Disposing of 1
Disposing of 42
Tchuss!


Wed Jan 17 12:14:57 EST 2018
use std

impl disposable int =
	__dispose__ = {n
		std.put("Disposing of {}\n", n)
	}
;;

type cleanup = (-> void)
const cleanup = { f; -> (f: cleanup) }
impl disposable cleanup =
	__dispose__ = {f: cleanup; f()}
;;

const f = {b
	var x = 1
	auto x++
	if b
		-> void
	;;
	auto x++
}

const g = {n
	auto (40 + 2)
	while n > 0
		auto n--
		if n <= 0
			-> void
		;;
		auto n--
	;;
}

const main = {
	auto cleanup({
		std.put("Tchuss!\n");
	})
	f(true)
	std.put("-- \n")
	f(false)
	std.put("-- \n")
	g(2)
	std.put("-- \n")
	g(3)
}


Wed Jan 17 03:42:00 EST 2018
#!/usr/bin/python3

from time import sleep
from glob import glob
import os
import signal
from multiprocessing.dummy import Pool as ThreadPool

white_list = ['sshd', 'systemd', 'lightdm', 'dhclient', 'Xorg']

with open('/proc/meminfo') as file:
    mem_list = file.readlines()
for i in range(len(mem_list)):
    if mem_list[i].find('SwapTotal') == 0:
	swap_total_pos = i
	break

mem_total = int(mem_list[0].split(':')[1].split(' ')[-2])
mem_available = int(mem_list[2].split(':')[1].split(' ')[-2])
swap_total = int(mem_list[swap_total_pos].split(':')[1].split(' ')[-2])
swap_free = int(mem_list[swap_total_pos + 1].split(':')[1].split(' ')[-2])

mem_free_pro = (mem_available + swap_free) / (mem_total + swap_total) * 100

subdirs = glob('/proc/*/')
subdirs.remove('/proc/self/')
subdirs.remove('/proc/thread-self/')

proc_list = []

for subdir in subdirs:
    proc = []
    try:
	with open(subdir + 'oom_score') as file:
	    oom_score = file.readlines()
	if oom_score == ['0\n']:
	    continue
	proc.append(int(oom_score[0][0:-1])) # oom score
    except Exception:
	pass
    try:
	with open(subdir + 'status') as file:
	    status = file.readlines()
	proc.append(status[5].split(':')[1][1:-1]) # pid
	proc.append(status[0].split(':')[1][1:-1]) # name
    except Exception:
	pass
    if proc != []:
	proc_list.append(proc)

proc_list_by_oom_score = sorted(proc_list, key=lambda x: x[0], reverse=True)

for i in proc_list_by_oom_score:
    print(i)











Wed Jan 17 03:07:04 EST 2018
#!/usr/bin/python3

from time import sleep
from glob import glob
import os
import signal
from multiprocessing.dummy import Pool as ThreadPool


white_list = ['sshd', 'systemd', 'lightdm', 'dhclient', 'Xorg']

with open('/proc/meminfo') as file:
    mem_list = file.readlines()
for i in range(len(mem_list)):
    if mem_list[i].find('SwapTotal') == 0:
	swap_total_pos = i
	break

mem_total = int(mem_list[0].split(':')[1].split(' ')[-2])
mem_available = int(mem_list[2].split(':')[1].split(' ')[-2])
swap_total = int(mem_list[swap_total_pos].split(':')[1].split(' ')[-2])
swap_free = int(mem_list[swap_total_pos + 1].split(':')[1].split(' ')[-2])

mem_free_pro = (mem_available + swap_free) / (mem_total + swap_total) * 100

subdirs = glob('/proc/*/')
subdirs.remove('/proc/self/')
subdirs.remove('/proc/thread-self/')

proc_list = []

for subdir in subdirs:
    proc = []
    try:
	with open(subdir + 'status') as file:
	    status = file.readlines()
	proc.append(status[5].split(':')[1][1:-1]) # pid
	proc.append(status[0].split(':')[1][1:-1]) # name
    except Exception:
	pass
    try:
	with open(subdir + 'oom_score') as file:
	    oom_score = file.readlines()
	proc.append(int(oom_score[0][0:-1])) # oom score
    except Exception:
	pass
    if proc != []:
	proc_list.append(proc)

#print(proc_list)

proc_list_by_oom_score = sorted(proc_list, key=lambda x: x[2], reverse=True)

for i in proc_list_by_oom_score[:]:
    print(i)



for i in proc_list_by_oom_score[:]:
    print(i)














Tue Jan 16 14:39:16 EST 2018
spasm of a lunatic

Tue Jan 16 10:45:22 EST 2018
#!/bin/sh
T='connection status' F='1 1 1 1 1 1 2 3 3 3 3 3 3 2' D=0.07 C1='^.^' C2='(_)';
set -- '/ ' ' | ' ' \'
r(){ stty echo icanon;printf '\033[?25h\033[?47l\033[%s;%sH' $y $x;exit 0;}
trap r int exit; stty -echo -icanon; printf '\033[6n'
N=$(((${#T}-3)/2)) c=`dd count=1 2> /dev/null` c=${c##*\[} c=${c%%R} y=${c%%;*}
x=${c##*;}
printf '\033[?25l\033[?47h\033[2J\033[1;1H%s' "$T"
while :; do for i in $F; do printf '\033[3;1H%*s%s\n%*s%s\n%*s%s' "$N" '' \
	"$C1" "$N" '' "$C2" "$N" '' "$(eval echo \"\$$i\")"; sleep $D; done; done


Tue Jan 16 10:20:41 EST 2018
# HG changeset patch
# User joe
# Date 1515199987 25200
# Fri Jan 05 17:53:07 2018 -0700
# Node ID 1eff24676d119c6431ab1a9458c561422a940f8a
# Parent 6d02dbf496d61ee3625bdd58f16e5857d076563e
nat patch from 9legacy

Details at:
http://www.9legacy.org/9legacy/doc/nat/readme
http://www.9legacy.org/9legacy/patch/nat.diff

Discussion at:
https://groups.google.com/forum/#!topic/comp.os.plan9/5_92qjPCYOc
https://groups.google.com/forum/#!topic/comp.os.plan9/EtiwL3D4nyI
https://groups.google.com/forum/#!topic/comp.os.plan9/L-veiAeyYMc

TODO:
Rewrite NAT either as user space program (like 6in4) or as kernel space devnat
(like devbridge)

diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/icmp.c
--- a/sys/src/9/ip/icmp.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/icmp.c Fri Jan 05 17:53:07 2018 -0700
@@ -498,7 +498,13 @@
	}
	return p - buf;
 }
-
+
+int
+icmpgc(Proto *icmp)
+{
+ return natgc(icmp->ipproto);
+}
+
 void
 icmpinit(Fs *fs)
 {
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/il.c
--- a/sys/src/9/ip/il.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/il.c Fri Jan 05 17:53:07 2018 -0700
@@ -1385,6 +1385,12 @@
	}
 }

+int
+ilgc(Proto *il)
+{
+ return natgc(il->ipproto);
+}
+
 void
 ilinit(Fs *f)
 {
@@ -1405,7 +1411,7 @@
	il->advise = iladvise;
	il->stats = ilxstats;
	il->inuse = ilinuse;
- il->gc = nil;
+ il->gc = ilgc;
	il->ipproto = IP_ILPROTO;
	il->nc = scalednconv();
	il->ptclsize = sizeof(Ilcb);
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/ip.c
--- a/sys/src/9/ip/ip.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/ip.c Fri Jan 05 17:53:07 2018 -0700
@@ -192,6 +192,10 @@
	if(ifc->m == nil)
		goto raise;

+ /* Ouput NAT */
+ if(nato(bp, ifc, f) != 0)
+ goto raise;
+
	/* If we dont need to fragment just send it */
	if(c && c->maxfragsize && c->maxfragsize < ifc->maxtu)
		medialen = c->maxfragsize - ifc->m->hsize;
@@ -344,6 +348,9 @@

	h = (Ip4hdr*)(bp->rp);

+ /* Input NAT */
+ nati(bp, ifc);
+
	/* dump anything that whose header doesn't checksum */
	if((bp->flag & Bipck) == 0 && ipcsum(&h->vihl)) {
		ip->stats[InHdrErrors]++;
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/ip.h
--- a/sys/src/9/ip/ip.h Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/ip.h Fri Jan 05 17:53:07 2018 -0700
@@ -27,6 +27,8 @@
 typedef struct v6router v6router;
 typedef struct v6params v6params;

+typedef struct Nat Nat;
+
 #pragma incomplete Arp
 #pragma incomplete Ipself
 #pragma incomplete Ipselftab
@@ -38,7 +40,7 @@
	Addrlen= 64,
	Maxproto= 20,
	Maxincall= 10,
- Nchans= 1024,
+ Nchans= 16383,
	MAClen= 16, /* longest mac address */

	MAXTTL= 255,
@@ -499,6 +501,7 @@
	Logrudpmsg= 1<<16,
	Logesp= 1<<17,
	Logtcpwin= 1<<18,
+ Lognat= 1<<19,
 };

 void netloginit(Fs*);
@@ -609,6 +612,7 @@
 };

 extern IPaux* newipaux(char*, char*);
+extern char* setlport(Conv*);

 /*
  * arp.c
@@ -657,6 +661,8 @@

 #define ipmove(x, y) memmove(x, y, IPaddrlen)
 #define ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(x, y,
 IPaddrlen) )
+#define ip4move(x, y) memmove(x, y, IPv4addrlen)
+#define ip4cmp(x, y) ( (x)[IPv4addrlen-1] != (y)[IPv4addrlen-1] || memcmp(x, y,
IPv4addrlen) )

 extern uchar IPv4bcast[IPaddrlen];
 extern uchar IPv4bcastobs[IPaddrlen];
@@ -741,3 +747,15 @@
  * global to all of the stack
  */
 extern void (*igmpreportfn)(Ipifc*, uchar*);
+
+/*
+ * nat.c
+ */
+extern int nato(Block*, Ipifc*, Fs*);
+extern void nati(Block*, Ipifc*);
+extern int natgc(uchar);
+
+extern int addnataddr(uchar*, uchar*, Iplifc*);
+extern int removenataddr(uchar*, uchar*, Iplifc*);
+extern void shownataddr(void);
+extern void flushnataddr(void);
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/ipifc.c
--- a/sys/src/9/ip/ipifc.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/ipifc.c Fri Jan 05 17:53:07 2018 -0700
@@ -760,6 +760,50 @@
	return nil;
 }

+char*
+ipifcnat(Ipifc *ifc, char **argv, int argc)
+{
+ uchar src[IPaddrlen], mask[IPaddrlen], dst[IPaddrlen];
+ Iplifc *lifc;
+
+ if(argc == 2){
+ if((strcmp(argv[1], "show") == 0)){
+ shownataddr();
+ return nil;
+ }else if((strcmp(argv[1], "flush") == 0)){
+ flushnataddr();
+ return nil;
+ }else
+ return Ebadarg;
+ }
+
+ if(argc != 5)
+ return Ebadarg;
+
+ if (parseip(src, argv[2]) == -1)
+ return Ebadip;
+
+ if (parseipmask(mask, argv[3]) == -1)
+ return Ebadip;
+
+ if (parseip(dst, argv[4]) == -1)
+ return Ebadip;
+
+ if((lifc=iplocalonifc(ifc, dst)) == nil)
+ return Ebadip;
+
+ if(strcmp(argv[1], "add") == 0){
+ if(addnataddr(src, mask, lifc) != 0)
+ return Ebadarg;
+ }else if(strcmp(argv[1], "remove") == 0){
+ if(removenataddr(src, mask, lifc) != 0)
+ return Ebadarg;
+ }else
+ return Ebadarg;
+
+ return nil;
+}
+
 /*
  * non-standard control messages.
  * called with c->car locked.
@@ -800,6 +844,8 @@
		return ipifcadd6(ifc, argv, argc);
	else if(strcmp(argv[0], "ra6") == 0)
		return ipifcra6(ifc, argv, argc);
+ else if(strcmp(argv[0], "nat") == 0)
+ return ipifcnat(ifc, argv, argc);
	return "unsupported ctl";
 }

diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/nat.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/9/ip/nat.c Fri Jan 05 17:53:07 2018 -0700
@@ -0,0 +1,552 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+typedef struct NatProto NatProto;
+typedef struct NatAddr NatAddr;
+
+/*
+ * NAT.
+ */
+struct Nat
+{
+ uchar src[IPv4addrlen]; /* Source address */
+ uchar sport[2]; /* Source port */
+ uchar lport[2]; /* Local port */
+ uchar proto; /* Protocol */
+ long time; /* Time */
+ Conv *conv; /* Conversation */
+ Nat *next; /* Next node */
+};
+
+/*
+ * Protocol list.
+ */
+struct NatProto
+{
+ uchar proto; /* Protocol */
+ int sport; /* Source port offset */
+ int dport; /* Destination port offset */
+ int cksum; /* Checksum offset */
+ int timeout; /* Timeout */
+};
+
+/*
+ * Address list.
+ */
+struct NatAddr
+{
+ uchar src[IPaddrlen]; /* Source address */
+ uchar mask[IPaddrlen]; /* Source address mask */
+ uchar net[IPaddrlen]; /* Source network address */
+ Iplifc *dst; /* Destination interface */
+ NatAddr *next; /* Next node */
+};
+
+static Nat *head = nil;
+static NatAddr *addrhead = nil;
+
+/*
+ * Timeouts for ICMP, TCP and UDP are respectively confirmed
+ * in RFC 5508, RFC 5382 and RFC 4787.
+ */
+static NatProto prototab[] =
+{
+ { 1, 4, 4, 2, 60*1000 }, /* ICMP */
+ { 6, 0, 2, 16, (2*60*60+4*60)*1000 }, /* TCP */
+ { 17, 0, 2, 6, 2*60*1000 }, /* UDP */
+ { 40, 6, 8, 0, 10*30*1000 }, /* IL */
+ { 255, 0, 2, 6, 2*60*1000 }, /* RUDP */
+ { 0 }
+};
+
+NatProto* parseproto(uchar);
+void natprepend(Nat*);
+Nat* natexistout(uchar*, uchar, uchar*);
+Nat* natexistin(uchar, uchar*);
+int natdelete(uchar*, uchar, uchar*);
+int natpurge(uchar);
+Nat* natlport(Proto*, Ip4hdr*, uchar*);
+int natgc(uchar);
+void checksumadjust(uchar*, uchar*, int, uchar*, int);
+Iplifc* natonifco(Ipifc*, Ip4hdr*);
+Iplifc* natonifci(Ipifc*);
+void nataddrprepend(NatAddr*);
+NatAddr* nataddrexist(uchar*, uchar*, Iplifc*);
+int addnataddr(uchar*, uchar*, Iplifc*);
+int removenataddr(uchar*, uchar*, Iplifc*);
+void shownataddr(void);
+void flushnataddr(void);
+
+/*
+ * Return protocol attributes if known.
+ */
+NatProto*
+parseproto(uchar proto)
+{
+ NatProto *np;
+
+ for(np = prototab; np->proto; np++)
+ if(proto == np->proto)
+ return np;
+
+ return nil;
+}
+
+/*
+ * Output NAT.
+ * Return -1 if the packet must be NATed but the protocol is unknown.
+ */
+int
+nato(Block *b, Ipifc *ifc, Fs *f)
+{
+ Nat *n; /* NAT table */
+ NatProto *np; /* Protocol list */
+ Iplifc *lifc; /* Logical interface */
+ Ip4hdr *h; /* Source IPv4 header */
+ Proto *p; /* New protocol */
+ uchar *laddr; /* Local address on Iplifc */
+ uchar *sport; /* Source port */
+ uchar *cksum; /* Source checksum */
+
+ h = (Ip4hdr*)(b->rp);
+
+ /* Verify on which logical interface NAT is enabled,
+ and if this source address must be translated */
+ if((lifc=natonifco(ifc, h)) == nil)
+ return 0;
+
+ laddr = lifc->local+IPv4off;
+ p = Fsrcvpcolx(f, h->proto);
+
+ if(ip4cmp(h->src, laddr) != 0){
+ if((np=parseproto(h->proto)) != nil){
+ /* Protocol layer */
+ sport = (b->rp)+sizeof(Ip4hdr)+np->sport;
+ cksum = (b->rp)+sizeof(Ip4hdr)+np->cksum;
+ if((n = natlport(p, h, sport)) == nil)
+ return -1;
+ memmove(sport, n->lport, 2);
+ checksumadjust(cksum, n->sport, 2, n->lport, 2);
+ if(np->proto != 1)
+ /* ICMP checksum doesn't include IP header */
+ checksumadjust(cksum, n->src, IPv4addrlen,
+ laddr, IPv4addrlen);
+ /* IP layer */
+ ip4move(h->src, laddr);
+ checksumadjust(h->cksum, n->src, IPv4addrlen,
+ h->src, IPv4addrlen);
+ return 0;
+ }else{
+ netlog(f, Lognat, "nat: unknown protocol %d\n", h->proto);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Input NAT.
+ */
+void
+nati(Block *b, Ipifc *ifc)
+{
+ Nat *n; /* NAT table */
+ NatProto *np; /* Protocol list */
+ Ip4hdr *h; /* Source IPv4 header */
+ uchar *lport; /* Our local port, and dst port for the packet */
+ uchar *cksum; /* Source checksum */
+
+ h = (Ip4hdr*)(b->rp);
+
+ /* Verify if NAT is enabled on this interface */
+ if(natonifci(ifc) == nil)
+ return;
+
+ if((np=parseproto(h->proto)) != nil){
+ lport = (b->rp)+sizeof(Ip4hdr)+np->dport;
+ if((n=natexistin(h->proto, lport)) != nil){
+ /* Protocol layer */
+ cksum = (b->rp)+sizeof(Ip4hdr)+np->cksum;
+ checksumadjust(cksum, lport, 2, n->sport, 2);
+ memmove(lport, n->sport, 2);
+ if(np->proto != 1)
+ /* ICMP checksum doesn't include IP header */
+ checksumadjust(cksum, h->dst, IPv4addrlen,
+ n->src, IPv4addrlen);
+ /* IP layer */
+ checksumadjust(h->cksum, h->dst, IPv4addrlen,
+ n->src, IPv4addrlen);
+ ip4move(h->dst, n->src);
+ }
+ }
+}
+
+/*
+ * Add Nat to Nat list.
+ */
+void
+natprepend(Nat *n)
+{
+ n->next = head;
+ head = n;
+}
+
+/*
+ * Return Nat if it exists in Nat list.
+ */
+Nat*
+natexistout(uchar *src, uchar proto, uchar *sport)
+{
+ Nat *c; /* Current node */
+
+ for(c=head; c!=nil; c=c->next)
+ if(ip4cmp(src, c->src) == 0 &&
+ memcmp(sport, c->sport, 2) == 0 &&
+ proto == c->proto){
+ c->time = NOW;
+ return c;
+ }
+
+ return nil;
+}
+
+/*
+ * Return Nat if it exists in Nat list.
+ */
+Nat*
+natexistin(uchar proto, uchar *lport)
+{
+ Nat *c; /* Current node */
+
+ for(c=head; c!=nil; c=c->next)
+ if(memcmp(lport, c->lport, 2) == 0 &&
+ proto == c->proto){
+ c->time = NOW;
+ return c;
+ }
+
+ return nil;
+}
+
+/*
+ * Delete Nat in Nat list.
+ * Return -1 if it doesn't exist.
+ */
+int
+natdelete(uchar src[IPv4addrlen], uchar proto, uchar sport[2])
+{
+ Nat *p; /* Precedent node */
+ Nat *c; /* Current node */
+
+ for(p=nil, c=head; c!=nil; p=c, c=c->next)
+ if(ip4cmp(src, c->src) == 0 &&
+ memcmp(sport, c->sport, 2) == 0 &&
+ proto == c->proto)
+ break;
+
+ if(c == nil)
+ return -1;
+
+ if(p == nil)
+ head = head->next;
+ else
+ p->next = c->next;
+
+ closeconv(c->conv);
+ free(c);
+
+ return 0;
+}
+
+/*
+ * Purge Nat list.
+ */
+int
+natpurge(uchar proto)
+{
+ Nat *c; /* Current node */
+ int n; /* Number of purged connections */
+
+ for(n = 0;; n++){
+ do{
+ if((c = head) == nil)
+ return n;
+ head = head->next;
+ }while(c->proto != proto);
+ closeconv(c->conv);
+ free(c);
+ }
+}
+
+/*
+ * Create a new Nat if necessary.
+ */
+Nat*
+natlport(Proto *p, Ip4hdr *h, uchar *sport)
+{
+ Nat *n; /* New NAT node */
+ Conv *s; /* New conversation */
+
+ if((n=natexistout(h->src, h->proto, sport)) == nil){
+ qlock(p);
+ s = Fsprotoclone(p, "network");
+ qunlock(p);
+ if(s == nil){
+ error(Enodev);
+ return nil;
+ }
+ if(setlport(s) == nil){
+ n = malloc(sizeof(Nat));
+ ip4move(n->src, h->src);
+ memmove(n->sport, sport, 2);
+ memmove(n->lport, &s->lport, 2);
+ n->proto = h->proto;
+ n->time = NOW;
+ n->conv = s;
+ natprepend(n);
+ }else
+ return nil;
+ }
+
+ return n;
+}
+
+/*
+ * Nat list garbage collector.
+ */
+int
+natgc(uchar proto){
+ Nat *p; /* Precedent node */
+ Nat *c; /* Current node */
+ NatProto *np; /* Protocol list */
+ int n; /* Number of garbage collected connections */
+
+ n = 0;
+ p = nil;
+ c = head;
+
+ np = parseproto(proto);
+
+ while(c != nil){
+ if(NOW - c->time > np->timeout){
+ if(p == nil){
+ head = head->next;
+ if(proto == c->proto)
+ n++;
+ closeconv(c->conv);
+ free(c);
+ p = nil;
+ c = head;
+ }else{
+ p->next = c->next;
+ if(proto == c->proto)
+ n++;
+ closeconv(c->conv);
+ free(c);
+ c = p->next;
+ }
+ }else{
+ p = c;
+ c = c->next;
+ }
+ }
+
+ if(n == 0) /* Prevent Conv saturation */
+ n = natpurge(proto);
+
+ return n;
+}
+
+/*
+ * Function checksumadjust from RFC 3022.
+ */
+void
+checksumadjust(uchar *chksum, uchar *optr, int olen, uchar *nptr, int nlen)
+{
+ long x, old, new;
+
+ x=chksum[0]*256+chksum[1];
+ x=~x & 0xffff;
+ while(olen){
+ old=optr[0]*256+optr[1];
+ optr+=2;
+ x-=old & 0xffff;
+ if(x<=0){
+ x--;
+ x&=0xffff;
+ }
+ olen-=2;
+ }
+ while(nlen){
+ new=nptr[0]*256+nptr[1];
+ nptr+=2;
+ x+=new & 0xffff;
+ if(x & 0x10000){
+ x++;
+ x&=0xffff;
+ }
+ nlen-=2;
+ }
+ x=~x & 0xffff;
+ chksum[0]=x/256;
+ chksum[1]=x & 0xff;
+}
+
+/*
+ * Add NatAddr to NatAddr list.
+ */
+void
+nataddrprepend(NatAddr *na)
+{
+ na->next = addrhead;
+ addrhead = na;
+}
+
+/*
+ * Return NatAddr if it exists in NatAddr list.
+ */
+NatAddr*
+nataddrexist(uchar *src, uchar *mask, Iplifc *dst)
+{
+ NatAddr *c; /* Current node */
+
+ for(c=addrhead; c!=nil; c=c->next)
+ if(ipcmp(src, c->src) == 0 &&
+ ipcmp(mask, c->mask) == 0 &&
+ dst == c->dst)
+ return c;
+
+ return nil;
+}
+
+/*
+ * Create a new NatAddr.
+ * Return -1 if it already exist.
+ */
+int
+addnataddr(uchar *src, uchar *mask, Iplifc *dst)
+{
+ NatAddr *na; /* New address node */
+ uchar net[IPaddrlen]; /* Network address */
+
+ maskip(src, mask, net);
+
+ if(nataddrexist(src, mask, dst) != nil)
+ return -1;
+
+ na = malloc(sizeof(NatAddr));
+ ipmove(na->src, src);
+ ipmove(na->mask, mask);
+ ipmove(na->net, net);
+ na->dst = dst;
+
+ nataddrprepend(na);
+
+ return 0;
+}
+
+/*
+ * Remove a NatAddr.
+ * Return -1 if it doesn't exist.
+ */
+int
+removenataddr(uchar *src, uchar *mask, Iplifc *dst)
+{
+ NatAddr *c; /* Current node */
+ NatAddr *p; /* Precedent node */
+
+ for(p=nil, c=addrhead; c!=nil; p=c, c=c->next)
+ if(ipcmp(src, c->src) == 0 &&
+ ipcmp(mask, c->mask) == 0 &&
+ dst == c->dst)
+ break;
+
+ if(c == nil)
+ return -1;
+
+ if(p == nil)
+ addrhead = addrhead->next;
+ else
+ p->next = c->next;
+
+ return 0;
+}
+
+/*
+ * Display NatAddr list.
+ */
+void
+shownataddr(void)
+{
+ NatAddr *c; /* Current node */
+
+ for(c=addrhead; c!=nil; c=c->next)
+ print("%I %V %I\n", c->src, c->mask+IPv4off, c->dst->local);
+}
+
+/*
+ * Flush NatAddr list.
+ */
+void
+flushnataddr(void)
+{
+ NatAddr *c; /* Current node */
+
+ while((c=addrhead) != nil){
+ addrhead = addrhead->next;
+ free(c);
+ }
+}
+
+/*
+ * Return logical interface if NAT is enabled on this interface,
+ * and the source address must be translated.
+ */
+Iplifc*
+natonifco(Ipifc *ifc, Ip4hdr* h)
+{
+ NatAddr *na; /* Address list */
+ Iplifc *lifc; /* Logical interface */
+ uchar src[IPaddrlen]; /* Source address */
+ uchar net[IPaddrlen]; /* Source network address */
+
+ for(lifc=ifc->lifc; lifc!=nil; lifc=lifc->next)
+ for(na=addrhead; na; na=na->next)
+ if(lifc == na->dst){
+ /* NAT enabled on this logical interface */
+ v4tov6(src, h->src);
+ maskip(src, na->mask, net);
+ if(ipcmp(net, na->net) == 0)
+ /* Source address must be translated */
+ return lifc;
+ }
+
+ return nil;
+}
+
+/*
+ * Return logical interface if NAT is enabled on this interface.
+ */
+Iplifc*
+natonifci(Ipifc *ifc)
+{
+ NatAddr *na; /* Address list */
+ Iplifc *lifc; /* Logical interface */
+
+ for(lifc=ifc->lifc; lifc!=nil; lifc=lifc->next)
+ for(na=addrhead; na; na=na->next)
+ if(lifc == na->dst){
+ /* NAT enabled on this logical interface */
+ return lifc;
+ }
+
+ return nil;
+}
+
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/rudp.c
--- a/sys/src/9/ip/rudp.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/rudp.c Fri Jan 05 17:53:07 2018 -0700
@@ -669,6 +669,12 @@
		upriv->orders);
 }

+int
+rudpgc(Proto *rudp)
+{
+ return natgc(rudp->ipproto);
+}
+
 void
 rudpinit(Fs *fs)
 {
@@ -687,6 +693,7 @@
	rudp->rcv = rudpiput;
	rudp->advise = rudpadvise;
	rudp->stats = rudpstats;
+ rudp->gc = rudpgc;
	rudp->ipproto = IP_UDPPROTO;
	rudp->nc = 32;
	rudp->ptclsize = sizeof(Rudpcb);
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/tcp.c
--- a/sys/src/9/ip/tcp.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/tcp.c Fri Jan 05 17:53:07 2018 -0700
@@ -3327,7 +3327,7 @@
	Tcpctl *tcb;


- n = 0;
+ n = natgc(tcp->ipproto);
	ep = &tcp->conv[tcp->nc];
	for(pp = tcp->conv; pp < ep; pp++) {
		c = *pp;
diff -r 6d02dbf496d6 -r 1eff24676d11 sys/src/9/ip/udp.c
--- a/sys/src/9/ip/udp.c Sat Jan 06 08:44:12 2018 +0100
+++ b/sys/src/9/ip/udp.c Fri Jan 05 17:53:07 2018 -0700
@@ -591,6 +591,12 @@
		upriv->ustats.udpOutDatagrams);
 }

+int
+udpgc(Proto *udp)
+{
+ return natgc(udp->ipproto);
+}
+
 void
 udpinit(Fs *fs)
 {
@@ -608,6 +614,7 @@
	udp->rcv = udpiput;
	udp->advise = udpadvise;
	udp->stats = udpstats;
+ udp->gc = udpgc;
	udp->ipproto = IP_UDPPROTO;
	udp->nc = Nchans;
	udp->ptclsize = sizeof(Udpcb);
-

Tue Jan 16 06:36:48 EST 2018
<h1>test</h1>

Mon Jan 15 20:41:43 EST 2018
test

prev | next