devsdp.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/netif.h"
  7. #include "../port/error.h"
  8. #include <libsec.h>
  9. #include "../port/thwack.h"
  10. /*
  11. * sdp - secure datagram protocol
  12. */
  13. typedef struct Sdp Sdp;
  14. typedef struct Conv Conv;
  15. typedef struct OneWay OneWay;
  16. typedef struct Stats Stats;
  17. typedef struct AckPkt AckPkt;
  18. typedef struct Algorithm Algorithm;
  19. typedef struct CipherRc4 CipherRc4;
  20. enum
  21. {
  22. Qtopdir= 1, /* top level directory */
  23. Qsdpdir, /* sdp directory */
  24. Qclone,
  25. Qlog,
  26. Qconvdir, /* directory per conversation */
  27. Qctl,
  28. Qdata, /* unreliable packet channel */
  29. Qcontrol, /* reliable control channel */
  30. Qstatus,
  31. Qstats,
  32. Qrstats,
  33. MaxQ,
  34. Maxconv= 256, // power of 2
  35. Nfs= 4, // number of file systems
  36. MaxRetries= 12,
  37. KeepAlive = 300, // keep alive in seconds - should probably be about 60 but is higher to avoid linksys bug
  38. SecretLength= 32, // a secret per direction
  39. SeqMax = (1<<24),
  40. SeqWindow = 32,
  41. NCompStats = 8,
  42. };
  43. #define TYPE(x) (((ulong)(x).path) & 0xff)
  44. #define CONV(x) ((((ulong)(x).path) >> 8)&(Maxconv-1))
  45. #define QID(x, y) (((x)<<8) | (y))
  46. struct Stats
  47. {
  48. ulong outPackets;
  49. ulong outDataPackets;
  50. ulong outDataBytes;
  51. ulong outCompDataBytes;
  52. ulong outCompBytes;
  53. ulong outCompStats[NCompStats];
  54. ulong inPackets;
  55. ulong inDataPackets;
  56. ulong inDataBytes;
  57. ulong inCompDataBytes;
  58. ulong inMissing;
  59. ulong inDup;
  60. ulong inReorder;
  61. ulong inBadComp;
  62. ulong inBadAuth;
  63. ulong inBadSeq;
  64. ulong inBadOther;
  65. };
  66. struct OneWay
  67. {
  68. Rendez statsready;
  69. ulong seqwrap; // number of wraps of the sequence number
  70. ulong seq;
  71. ulong window;
  72. uchar secret[SecretLength];
  73. QLock controllk;
  74. Rendez controlready;
  75. Block *controlpkt; // control channel
  76. ulong controlseq;
  77. void *cipherstate; // state cipher
  78. int cipherivlen; // initial vector length
  79. int cipherblklen; // block length
  80. int (*cipher)(OneWay*, uchar *buf, int len);
  81. void *authstate; // auth state
  82. int authlen; // auth data length in bytes
  83. int (*auth)(OneWay*, uchar *buf, int len);
  84. void *compstate;
  85. int (*comp)(Conv*, int subtype, ulong seq, Block **);
  86. };
  87. // conv states
  88. enum {
  89. CFree,
  90. CInit,
  91. CDial,
  92. CAccept,
  93. COpen,
  94. CLocalClose,
  95. CRemoteClose,
  96. CClosed,
  97. };
  98. struct Conv {
  99. QLock;
  100. Sdp *sdp;
  101. int id;
  102. int ref; // holds conv up
  103. int state;
  104. int dataopen; // ref count of opens on Qdata
  105. int controlopen; // ref count of opens on Qcontrol
  106. int reader; // reader proc has been started
  107. Stats lstats;
  108. Stats rstats;
  109. ulong lastrecv; // time last packet was received
  110. ulong timeout;
  111. int retries;
  112. // the following pair uniquely define conversation on this port
  113. ulong dialid;
  114. ulong acceptid;
  115. QLock readlk; // protects readproc
  116. Proc *readproc;
  117. Chan *chan; // packet channel
  118. char *channame;
  119. char owner[KNAMELEN]; /* protections */
  120. int perm;
  121. Algorithm *auth;
  122. Algorithm *cipher;
  123. Algorithm *comp;
  124. int drop;
  125. OneWay in;
  126. OneWay out;
  127. };
  128. struct Sdp {
  129. QLock;
  130. Log;
  131. int nconv;
  132. Conv *conv[Maxconv];
  133. int ackproc;
  134. };
  135. enum {
  136. TConnect,
  137. TControl,
  138. TData,
  139. TCompData,
  140. };
  141. enum {
  142. ControlMesg,
  143. ControlAck,
  144. };
  145. enum {
  146. ThwackU,
  147. ThwackC,
  148. };
  149. enum {
  150. ConOpenRequest,
  151. ConOpenAck,
  152. ConOpenAckAck,
  153. ConClose,
  154. ConCloseAck,
  155. ConReset,
  156. };
  157. struct AckPkt
  158. {
  159. uchar cseq[4];
  160. uchar outPackets[4];
  161. uchar outDataPackets[4];
  162. uchar outDataBytes[4];
  163. uchar outCompDataBytes[4];
  164. uchar outCompStats[4*NCompStats];
  165. uchar inPackets[4];
  166. uchar inDataPackets[4];
  167. uchar inDataBytes[4];
  168. uchar inCompDataBytes[4];
  169. uchar inMissing[4];
  170. uchar inDup[4];
  171. uchar inReorder[4];
  172. uchar inBadComp[4];
  173. uchar inBadAuth[4];
  174. uchar inBadSeq[4];
  175. uchar inBadOther[4];
  176. };
  177. struct Algorithm
  178. {
  179. char *name;
  180. int keylen; // in bytes
  181. void (*init)(Conv*);
  182. };
  183. enum {
  184. RC4forward = 10*1024*1024, // maximum skip forward
  185. RC4back = 100*1024, // maximum look back
  186. };
  187. struct CipherRc4
  188. {
  189. ulong cseq; // current byte sequence number
  190. RC4state current;
  191. int ovalid; // old is valid
  192. ulong lgseq; // last good sequence
  193. ulong oseq; // old byte sequence number
  194. RC4state old;
  195. };
  196. static Dirtab sdpdirtab[]={
  197. "log", {Qlog}, 0, 0666,
  198. "clone", {Qclone}, 0, 0666,
  199. };
  200. static Dirtab convdirtab[]={
  201. "ctl", {Qctl}, 0, 0666,
  202. "data", {Qdata}, 0, 0666,
  203. "control", {Qcontrol}, 0, 0666,
  204. "status", {Qstatus}, 0, 0444,
  205. "stats", {Qstats}, 0, 0444,
  206. "rstats", {Qrstats}, 0, 0444,
  207. };
  208. static int m2p[] = {
  209. [OREAD] 4,
  210. [OWRITE] 2,
  211. [ORDWR] 6
  212. };
  213. enum {
  214. Logcompress= (1<<0),
  215. Logauth= (1<<1),
  216. Loghmac= (1<<2),
  217. };
  218. static Logflag logflags[] =
  219. {
  220. { "compress", Logcompress, },
  221. { "auth", Logauth, },
  222. { "hmac", Loghmac, },
  223. { nil, 0, },
  224. };
  225. static Dirtab *dirtab[MaxQ];
  226. static Sdp sdptab[Nfs];
  227. static char *convstatename[] = {
  228. [CFree] "Free",
  229. [CInit] "Init",
  230. [CDial] "Dial",
  231. [CAccept] "Accept",
  232. [COpen] "Open",
  233. [CLocalClose] "LocalClose",
  234. [CRemoteClose] "RemoteClose",
  235. [CClosed] "Closed",
  236. };
  237. static int sdpgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp);
  238. static Conv *sdpclone(Sdp *sdp);
  239. static void sdpackproc(void *a);
  240. static void onewaycleanup(OneWay *ow);
  241. static int readready(void *a);
  242. static int controlread();
  243. static void convsetstate(Conv *c, int state);
  244. static Block *readcontrol(Conv *c, int n);
  245. static void writecontrol(Conv *c, void *p, int n, int wait);
  246. static Block *readdata(Conv *c, int n);
  247. static long writedata(Conv *c, Block *b);
  248. static void convderef(Conv *c);
  249. static Block *conviput(Conv *c, Block *b, int control);
  250. static void conviconnect(Conv *c, int op, Block *b);
  251. static void convicontrol(Conv *c, int op, Block *b);
  252. static Block *convicomp(Conv *c, int op, ulong, Block *b);
  253. static void convoput(Conv *c, int type, int subtype, Block *b);
  254. static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid);
  255. static void convopenchan(Conv *c, char *path);
  256. static void convstats(Conv *c, int local, char *buf, int n);
  257. static void convreader(void *a);
  258. static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **);
  259. static void setsecret(OneWay *cc, char *secret);
  260. static void nullcipherinit(Conv*c);
  261. static void descipherinit(Conv*c);
  262. static void rc4cipherinit(Conv*c);
  263. static void nullauthinit(Conv*c);
  264. static void shaauthinit(Conv*c);
  265. static void md5authinit(Conv*c);
  266. static void nullcompinit(Conv*c);
  267. static void thwackcompinit(Conv*c);
  268. static Algorithm cipheralg[] =
  269. {
  270. "null", 0, nullcipherinit,
  271. "des_56_cbc", 7, descipherinit,
  272. "rc4_128", 16, rc4cipherinit,
  273. "rc4_256", 32, rc4cipherinit,
  274. nil, 0, nil,
  275. };
  276. static Algorithm authalg[] =
  277. {
  278. "null", 0, nullauthinit,
  279. "hmac_sha1_96", 16, shaauthinit,
  280. "hmac_md5_96", 16, md5authinit,
  281. nil, 0, nil,
  282. };
  283. static Algorithm compalg[] =
  284. {
  285. "null", 0, nullcompinit,
  286. "thwack", 0, thwackcompinit,
  287. nil, 0, nil,
  288. };
  289. static void
  290. sdpinit(void)
  291. {
  292. int i;
  293. Dirtab *dt;
  294. // setup dirtab with non directory entries
  295. for(i=0; i<nelem(sdpdirtab); i++) {
  296. dt = sdpdirtab + i;
  297. dirtab[TYPE(dt->qid)] = dt;
  298. }
  299. for(i=0; i<nelem(convdirtab); i++) {
  300. dt = convdirtab + i;
  301. dirtab[TYPE(dt->qid)] = dt;
  302. }
  303. }
  304. static Chan*
  305. sdpattach(char* spec)
  306. {
  307. Chan *c;
  308. int dev;
  309. char buf[100];
  310. Sdp *sdp;
  311. int start;
  312. dev = atoi(spec);
  313. if(dev<0 || dev >= Nfs)
  314. error("bad specification");
  315. c = devattach('E', spec);
  316. c->qid = (Qid){QID(0, Qtopdir), 0, QTDIR};
  317. c->dev = dev;
  318. sdp = sdptab + dev;
  319. qlock(sdp);
  320. start = sdp->ackproc == 0;
  321. sdp->ackproc = 1;
  322. qunlock(sdp);
  323. if(start) {
  324. snprint(buf, sizeof(buf), "sdpackproc%d", dev);
  325. kproc(buf, sdpackproc, sdp);
  326. }
  327. return c;
  328. }
  329. static Walkqid*
  330. sdpwalk(Chan *c, Chan *nc, char **name, int nname)
  331. {
  332. return devwalk(c, nc, name, nname, 0, 0, sdpgen);
  333. }
  334. static int
  335. sdpstat(Chan* c, uchar* db, int n)
  336. {
  337. return devstat(c, db, n, nil, 0, sdpgen);
  338. }
  339. static Chan*
  340. sdpopen(Chan* ch, int omode)
  341. {
  342. int perm;
  343. Sdp *sdp;
  344. Conv *c;
  345. omode &= 3;
  346. perm = m2p[omode];
  347. USED(perm);
  348. sdp = sdptab + ch->dev;
  349. switch(TYPE(ch->qid)) {
  350. default:
  351. break;
  352. case Qtopdir:
  353. case Qsdpdir:
  354. case Qconvdir:
  355. if(omode != OREAD)
  356. error(Eperm);
  357. break;
  358. case Qlog:
  359. logopen(sdp);
  360. break;
  361. case Qclone:
  362. c = sdpclone(sdp);
  363. if(c == nil)
  364. error(Enodev);
  365. ch->qid.path = QID(c->id, Qctl);
  366. break;
  367. case Qdata:
  368. case Qctl:
  369. case Qstatus:
  370. case Qcontrol:
  371. case Qstats:
  372. case Qrstats:
  373. c = sdp->conv[CONV(ch->qid)];
  374. qlock(c);
  375. if(waserror()) {
  376. qunlock(c);
  377. nexterror();
  378. }
  379. if((perm & (c->perm>>6)) != perm)
  380. if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm)
  381. error(Eperm);
  382. c->ref++;
  383. if(TYPE(ch->qid) == Qdata) {
  384. c->dataopen++;
  385. // kill reader if Qdata is opened for the first time
  386. if(c->dataopen == 1)
  387. if(c->readproc != nil)
  388. postnote(c->readproc, 1, "interrupt", 0);
  389. } else if(TYPE(ch->qid) == Qcontrol) {
  390. c->controlopen++;
  391. }
  392. qunlock(c);
  393. poperror();
  394. break;
  395. }
  396. ch->mode = openmode(omode);
  397. ch->flag |= COPEN;
  398. ch->offset = 0;
  399. return ch;
  400. }
  401. static void
  402. sdpclose(Chan* ch)
  403. {
  404. Sdp *sdp = sdptab + ch->dev;
  405. Conv *c;
  406. if(!(ch->flag & COPEN))
  407. return;
  408. switch(TYPE(ch->qid)) {
  409. case Qlog:
  410. logclose(sdp);
  411. break;
  412. case Qctl:
  413. case Qstatus:
  414. case Qstats:
  415. case Qrstats:
  416. c = sdp->conv[CONV(ch->qid)];
  417. qlock(c);
  418. convderef(c);
  419. qunlock(c);
  420. break;
  421. case Qdata:
  422. c = sdp->conv[CONV(ch->qid)];
  423. qlock(c);
  424. c->dataopen--;
  425. convderef(c);
  426. if(c->dataopen == 0)
  427. if(c->reader == 0)
  428. if(c->chan != nil)
  429. if(!waserror()) {
  430. kproc("convreader", convreader, c);
  431. c->reader = 1;
  432. c->ref++;
  433. poperror();
  434. }
  435. qunlock(c);
  436. break;
  437. case Qcontrol:
  438. c = sdp->conv[CONV(ch->qid)];
  439. qlock(c);
  440. c->controlopen--;
  441. convderef(c);
  442. if(c->controlopen == 0 && c->ref != 0) {
  443. switch(c->state) {
  444. default:
  445. convsetstate(c, CClosed);
  446. break;
  447. case CAccept:
  448. case COpen:
  449. convsetstate(c, CLocalClose);
  450. break;
  451. }
  452. }
  453. qunlock(c);
  454. break;
  455. }
  456. }
  457. static long
  458. sdpread(Chan *ch, void *a, long n, vlong off)
  459. {
  460. char buf[256];
  461. char *s;
  462. Sdp *sdp = sdptab + ch->dev;
  463. Conv *c;
  464. Block *b;
  465. int rv;
  466. USED(off);
  467. switch(TYPE(ch->qid)) {
  468. default:
  469. error(Eperm);
  470. case Qtopdir:
  471. case Qsdpdir:
  472. case Qconvdir:
  473. return devdirread(ch, a, n, 0, 0, sdpgen);
  474. case Qlog:
  475. return logread(sdp, a, off, n);
  476. case Qstatus:
  477. c = sdp->conv[CONV(ch->qid)];
  478. qlock(c);
  479. n = readstr(off, a, n, convstatename[c->state]);
  480. qunlock(c);
  481. return n;
  482. case Qctl:
  483. sprint(buf, "%lud", CONV(ch->qid));
  484. return readstr(off, a, n, buf);
  485. case Qcontrol:
  486. b = readcontrol(sdp->conv[CONV(ch->qid)], n);
  487. if(b == nil)
  488. return 0;
  489. if(BLEN(b) < n)
  490. n = BLEN(b);
  491. memmove(a, b->rp, n);
  492. freeb(b);
  493. return n;
  494. case Qdata:
  495. b = readdata(sdp->conv[CONV(ch->qid)], n);
  496. if(b == nil)
  497. return 0;
  498. if(BLEN(b) < n)
  499. n = BLEN(b);
  500. memmove(a, b->rp, n);
  501. freeb(b);
  502. return n;
  503. case Qstats:
  504. case Qrstats:
  505. c = sdp->conv[CONV(ch->qid)];
  506. s = smalloc(1000);
  507. convstats(c, TYPE(ch->qid) == Qstats, s, 1000);
  508. rv = readstr(off, a, n, s);
  509. free(s);
  510. return rv;
  511. }
  512. }
  513. static Block*
  514. sdpbread(Chan* ch, long n, ulong offset)
  515. {
  516. Sdp *sdp = sdptab + ch->dev;
  517. if(TYPE(ch->qid) != Qdata)
  518. return devbread(ch, n, offset);
  519. return readdata(sdp->conv[CONV(ch->qid)], n);
  520. }
  521. static long
  522. sdpwrite(Chan *ch, void *a, long n, vlong off)
  523. {
  524. Sdp *sdp = sdptab + ch->dev;
  525. Cmdbuf *cb;
  526. char *arg0;
  527. char *p;
  528. Conv *c;
  529. Block *b;
  530. USED(off);
  531. switch(TYPE(ch->qid)) {
  532. default:
  533. error(Eperm);
  534. case Qctl:
  535. c = sdp->conv[CONV(ch->qid)];
  536. cb = parsecmd(a, n);
  537. qlock(c);
  538. if(waserror()) {
  539. qunlock(c);
  540. free(cb);
  541. nexterror();
  542. }
  543. if(cb->nf == 0)
  544. error("short write");
  545. arg0 = cb->f[0];
  546. if(strcmp(arg0, "accept") == 0) {
  547. if(cb->nf != 2)
  548. error("usage: accept file");
  549. convopenchan(c, cb->f[1]);
  550. } else if(strcmp(arg0, "dial") == 0) {
  551. if(cb->nf != 2)
  552. error("usage: dial file");
  553. convopenchan(c, cb->f[1]);
  554. convsetstate(c, CDial);
  555. } else if(strcmp(arg0, "drop") == 0) {
  556. if(cb->nf != 2)
  557. error("usage: drop permil");
  558. c->drop = atoi(cb->f[1]);
  559. } else if(strcmp(arg0, "cipher") == 0) {
  560. if(cb->nf != 2)
  561. error("usage: cipher alg");
  562. setalg(c, cb->f[1], cipheralg, &c->cipher);
  563. } else if(strcmp(arg0, "auth") == 0) {
  564. if(cb->nf != 2)
  565. error("usage: auth alg");
  566. setalg(c, cb->f[1], authalg, &c->auth);
  567. } else if(strcmp(arg0, "comp") == 0) {
  568. if(cb->nf != 2)
  569. error("usage: comp alg");
  570. setalg(c, cb->f[1], compalg, &c->comp);
  571. } else if(strcmp(arg0, "insecret") == 0) {
  572. if(cb->nf != 2)
  573. error("usage: insecret secret");
  574. setsecret(&c->in, cb->f[1]);
  575. if(c->cipher)
  576. c->cipher->init(c);
  577. if(c->auth)
  578. c->auth->init(c);
  579. } else if(strcmp(arg0, "outsecret") == 0) {
  580. if(cb->nf != 2)
  581. error("usage: outsecret secret");
  582. setsecret(&c->out, cb->f[1]);
  583. if(c->cipher)
  584. c->cipher->init(c);
  585. if(c->auth)
  586. c->auth->init(c);
  587. } else
  588. error("unknown control request");
  589. poperror();
  590. qunlock(c);
  591. free(cb);
  592. return n;
  593. case Qlog:
  594. cb = parsecmd(a, n);
  595. p = logctl(sdp, cb->nf, cb->f, logflags);
  596. free(cb);
  597. if(p != nil)
  598. error(p);
  599. return n;
  600. case Qcontrol:
  601. writecontrol(sdp->conv[CONV(ch->qid)], a, n, 0);
  602. return n;
  603. case Qdata:
  604. b = allocb(n);
  605. memmove(b->wp, a, n);
  606. b->wp += n;
  607. return writedata(sdp->conv[CONV(ch->qid)], b);
  608. }
  609. }
  610. long
  611. sdpbwrite(Chan *ch, Block *bp, ulong offset)
  612. {
  613. Sdp *sdp = sdptab + ch->dev;
  614. if(TYPE(ch->qid) != Qdata)
  615. return devbwrite(ch, bp, offset);
  616. return writedata(sdp->conv[CONV(ch->qid)], bp);
  617. }
  618. static int
  619. sdpgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
  620. {
  621. Sdp *sdp = sdptab + c->dev;
  622. int type = TYPE(c->qid);
  623. Dirtab *dt;
  624. Qid qid;
  625. if(s == DEVDOTDOT){
  626. switch(TYPE(c->qid)){
  627. case Qtopdir:
  628. case Qsdpdir:
  629. snprint(up->genbuf, sizeof(up->genbuf), "#E%ld", c->dev);
  630. mkqid(&qid, Qtopdir, 0, QTDIR);
  631. devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
  632. break;
  633. case Qconvdir:
  634. snprint(up->genbuf, sizeof(up->genbuf), "%d", s);
  635. mkqid(&qid, Qsdpdir, 0, QTDIR);
  636. devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
  637. break;
  638. default:
  639. panic("sdpwalk %llux", c->qid.path);
  640. }
  641. return 1;
  642. }
  643. switch(type) {
  644. default:
  645. // non directory entries end up here
  646. if(c->qid.type & QTDIR)
  647. panic("sdpgen: unexpected directory");
  648. if(s != 0)
  649. return -1;
  650. dt = dirtab[TYPE(c->qid)];
  651. if(dt == nil)
  652. panic("sdpgen: unknown type: %lud", TYPE(c->qid));
  653. devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp);
  654. return 1;
  655. case Qtopdir:
  656. if(s != 0)
  657. return -1;
  658. mkqid(&qid, QID(0, Qsdpdir), 0, QTDIR);
  659. devdir(c, qid, "sdp", 0, eve, 0555, dp);
  660. return 1;
  661. case Qsdpdir:
  662. if(s<nelem(sdpdirtab)) {
  663. dt = sdpdirtab+s;
  664. devdir(c, dt->qid, dt->name, dt->length, eve, dt->perm, dp);
  665. return 1;
  666. }
  667. s -= nelem(sdpdirtab);
  668. if(s >= sdp->nconv)
  669. return -1;
  670. mkqid(&qid, QID(s, Qconvdir), 0, QTDIR);
  671. snprint(up->genbuf, sizeof(up->genbuf), "%d", s);
  672. devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
  673. return 1;
  674. case Qconvdir:
  675. if(s>=nelem(convdirtab))
  676. return -1;
  677. dt = convdirtab+s;
  678. mkqid(&qid, QID(CONV(c->qid),TYPE(dt->qid)), 0, QTFILE);
  679. devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp);
  680. return 1;
  681. }
  682. }
  683. static Conv*
  684. sdpclone(Sdp *sdp)
  685. {
  686. Conv *c, **pp, **ep;
  687. c = nil;
  688. ep = sdp->conv + nelem(sdp->conv);
  689. qlock(sdp);
  690. if(waserror()) {
  691. qunlock(sdp);
  692. nexterror();
  693. }
  694. for(pp = sdp->conv; pp < ep; pp++) {
  695. c = *pp;
  696. if(c == nil){
  697. c = malloc(sizeof(Conv));
  698. if(c == nil)
  699. error(Enomem);
  700. memset(c, 0, sizeof(Conv));
  701. qlock(c);
  702. c->sdp = sdp;
  703. c->id = pp - sdp->conv;
  704. *pp = c;
  705. sdp->nconv++;
  706. break;
  707. }
  708. if(c->ref == 0 && canqlock(c)){
  709. if(c->ref == 0)
  710. break;
  711. qunlock(c);
  712. }
  713. }
  714. poperror();
  715. qunlock(sdp);
  716. if(pp >= ep)
  717. return nil;
  718. assert(c->state == CFree);
  719. // set ref to 2 - 1 ref for open - 1 ref for channel state
  720. c->ref = 2;
  721. c->state = CInit;
  722. c->in.window = ~0;
  723. strncpy(c->owner, up->user, sizeof(c->owner));
  724. c->perm = 0660;
  725. qunlock(c);
  726. return c;
  727. }
  728. // assume c is locked
  729. static void
  730. convretryinit(Conv *c)
  731. {
  732. c->retries = 0;
  733. // +2 to avoid rounding effects.
  734. c->timeout = TK2SEC(m->ticks) + 2;
  735. }
  736. // assume c is locked
  737. static int
  738. convretry(Conv *c, int reset)
  739. {
  740. c->retries++;
  741. if(c->retries > MaxRetries) {
  742. if(reset)
  743. convoconnect(c, ConReset, c->dialid, c->acceptid);
  744. convsetstate(c, CClosed);
  745. return 0;
  746. }
  747. c->timeout = TK2SEC(m->ticks) + (c->retries+1);
  748. return 1;
  749. }
  750. // assumes c is locked
  751. static void
  752. convtimer(Conv *c, ulong sec)
  753. {
  754. Block *b;
  755. if(c->timeout > sec)
  756. return;
  757. switch(c->state) {
  758. case CInit:
  759. break;
  760. case CDial:
  761. if(convretry(c, 1))
  762. convoconnect(c, ConOpenRequest, c->dialid, 0);
  763. break;
  764. case CAccept:
  765. if(convretry(c, 1))
  766. convoconnect(c, ConOpenAck, c->dialid, c->acceptid);
  767. break;
  768. case COpen:
  769. b = c->out.controlpkt;
  770. if(b != nil) {
  771. if(convretry(c, 1))
  772. convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));
  773. break;
  774. }
  775. c->timeout = c->lastrecv + KeepAlive;
  776. if(c->timeout > sec)
  777. break;
  778. // keepalive - randomly spaced between KeepAlive and 2*KeepAlive
  779. if(c->timeout + KeepAlive > sec && nrand(c->lastrecv + 2*KeepAlive - sec) > 0)
  780. break;
  781. // can not use writecontrol
  782. b = allocb(4);
  783. c->out.controlseq++;
  784. hnputl(b->wp, c->out.controlseq);
  785. b->wp += 4;
  786. c->out.controlpkt = b;
  787. convretryinit(c);
  788. if(!waserror()) {
  789. convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));
  790. poperror();
  791. }
  792. break;
  793. case CLocalClose:
  794. if(convretry(c, 0))
  795. convoconnect(c, ConClose, c->dialid, c->acceptid);
  796. break;
  797. case CRemoteClose:
  798. case CClosed:
  799. break;
  800. }
  801. }
  802. static void
  803. sdpackproc(void *a)
  804. {
  805. Sdp *sdp = a;
  806. ulong sec;
  807. int i;
  808. Conv *c;
  809. for(;;) {
  810. tsleep(&up->sleep, return0, 0, 1000);
  811. sec = TK2SEC(m->ticks);
  812. qlock(sdp);
  813. for(i=0; i<sdp->nconv; i++) {
  814. c = sdp->conv[i];
  815. if(c->ref == 0)
  816. continue;
  817. qunlock(sdp);
  818. qlock(c);
  819. if(c->ref > 0 && !waserror()) {
  820. convtimer(c, sec);
  821. poperror();
  822. }
  823. qunlock(c);
  824. qlock(sdp);
  825. }
  826. qunlock(sdp);
  827. }
  828. }
  829. Dev sdpdevtab = {
  830. 'E',
  831. "sdp",
  832. devreset,
  833. sdpinit,
  834. devshutdown,
  835. sdpattach,
  836. sdpwalk,
  837. sdpstat,
  838. sdpopen,
  839. devcreate,
  840. sdpclose,
  841. sdpread,
  842. devbread,
  843. sdpwrite,
  844. devbwrite,
  845. devremove,
  846. devwstat,
  847. };
  848. // assume hold lock on c
  849. static void
  850. convsetstate(Conv *c, int state)
  851. {
  852. if(0)print("convsetstate %d: %s -> %s\n", c->id, convstatename[c->state], convstatename[state]);
  853. switch(state) {
  854. default:
  855. panic("setstate: bad state: %d", state);
  856. case CDial:
  857. assert(c->state == CInit);
  858. c->dialid = (rand()<<16) + rand();
  859. convretryinit(c);
  860. convoconnect(c, ConOpenRequest, c->dialid, 0);
  861. break;
  862. case CAccept:
  863. assert(c->state == CInit);
  864. c->acceptid = (rand()<<16) + rand();
  865. convretryinit(c);
  866. convoconnect(c, ConOpenAck, c->dialid, c->acceptid);
  867. break;
  868. case COpen:
  869. assert(c->state == CDial || c->state == CAccept);
  870. c->lastrecv = TK2SEC(m->ticks);
  871. if(c->state == CDial) {
  872. convretryinit(c);
  873. convoconnect(c, ConOpenAckAck, c->dialid, c->acceptid);
  874. hnputl(c->in.secret, c->acceptid);
  875. hnputl(c->in.secret+4, c->dialid);
  876. hnputl(c->out.secret, c->dialid);
  877. hnputl(c->out.secret+4, c->acceptid);
  878. } else {
  879. hnputl(c->in.secret, c->dialid);
  880. hnputl(c->in.secret+4, c->acceptid);
  881. hnputl(c->out.secret, c->acceptid);
  882. hnputl(c->out.secret+4, c->dialid);
  883. }
  884. setalg(c, "hmac_md5_96", authalg, &c->auth);
  885. break;
  886. case CLocalClose:
  887. assert(c->state == CAccept || c->state == COpen);
  888. convretryinit(c);
  889. convoconnect(c, ConClose, c->dialid, c->acceptid);
  890. break;
  891. case CRemoteClose:
  892. wakeup(&c->in.controlready);
  893. wakeup(&c->out.controlready);
  894. break;
  895. case CClosed:
  896. wakeup(&c->in.controlready);
  897. wakeup(&c->out.controlready);
  898. if(c->readproc)
  899. postnote(c->readproc, 1, "interrupt", 0);
  900. if(c->state != CClosed)
  901. convderef(c);
  902. break;
  903. }
  904. c->state = state;
  905. }
  906. //assumes c is locked
  907. static void
  908. convderef(Conv *c)
  909. {
  910. c->ref--;
  911. if(c->ref > 0) {
  912. return;
  913. }
  914. assert(c->ref == 0);
  915. assert(c->dataopen == 0);
  916. assert(c->controlopen == 0);
  917. if(0)print("convderef: %d: ref == 0!\n", c->id);
  918. c->state = CFree;
  919. if(c->chan) {
  920. cclose(c->chan);
  921. c->chan = nil;
  922. }
  923. if(c->channame) {
  924. free(c->channame);
  925. c->channame = nil;
  926. }
  927. c->cipher = nil;
  928. c->auth = nil;
  929. c->comp = nil;
  930. strcpy(c->owner, "network");
  931. c->perm = 0660;
  932. c->dialid = 0;
  933. c->acceptid = 0;
  934. c->timeout = 0;
  935. c->retries = 0;
  936. c->drop = 0;
  937. onewaycleanup(&c->in);
  938. onewaycleanup(&c->out);
  939. memset(&c->lstats, 0, sizeof(Stats));
  940. memset(&c->rstats, 0, sizeof(Stats));
  941. }
  942. static void
  943. onewaycleanup(OneWay *ow)
  944. {
  945. if(ow->controlpkt)
  946. freeb(ow->controlpkt);
  947. if(ow->authstate)
  948. free(ow->authstate);
  949. if(ow->cipherstate)
  950. free(ow->cipherstate);
  951. if(ow->compstate)
  952. free(ow->compstate);
  953. memset(ow, 0, sizeof(OneWay));
  954. }
  955. // assumes conv is locked
  956. static void
  957. convopenchan(Conv *c, char *path)
  958. {
  959. if(c->state != CInit || c->chan != nil)
  960. error("already connected");
  961. c->chan = namec(path, Aopen, ORDWR, 0);
  962. c->channame = smalloc(strlen(path)+1);
  963. strcpy(c->channame, path);
  964. if(waserror()) {
  965. cclose(c->chan);
  966. c->chan = nil;
  967. free(c->channame);
  968. c->channame = nil;
  969. nexterror();
  970. }
  971. kproc("convreader", convreader, c);
  972. assert(c->reader == 0 && c->ref > 0);
  973. // after kproc in case it fails
  974. c->reader = 1;
  975. c->ref++;
  976. poperror();
  977. }
  978. static void
  979. convstats(Conv *c, int local, char *buf, int n)
  980. {
  981. Stats *stats;
  982. char *p, *ep;
  983. int i;
  984. if(local) {
  985. stats = &c->lstats;
  986. } else {
  987. if(!waserror()) {
  988. writecontrol(c, 0, 0, 1);
  989. poperror();
  990. }
  991. stats = &c->rstats;
  992. }
  993. qlock(c);
  994. p = buf;
  995. ep = buf + n;
  996. p += snprint(p, ep-p, "outPackets: %lud\n", stats->outPackets);
  997. p += snprint(p, ep-p, "outDataPackets: %lud\n", stats->outDataPackets);
  998. p += snprint(p, ep-p, "outDataBytes: %lud\n", stats->outDataBytes);
  999. p += snprint(p, ep-p, "outCompDataBytes: %lud\n", stats->outCompDataBytes);
  1000. for(i=0; i<NCompStats; i++) {
  1001. if(stats->outCompStats[i] == 0)
  1002. continue;
  1003. p += snprint(p, ep-p, "outCompStats[%d]: %lud\n", i, stats->outCompStats[i]);
  1004. }
  1005. p += snprint(p, ep-p, "inPackets: %lud\n", stats->inPackets);
  1006. p += snprint(p, ep-p, "inDataPackets: %lud\n", stats->inDataPackets);
  1007. p += snprint(p, ep-p, "inDataBytes: %lud\n", stats->inDataBytes);
  1008. p += snprint(p, ep-p, "inCompDataBytes: %lud\n", stats->inCompDataBytes);
  1009. p += snprint(p, ep-p, "inMissing: %lud\n", stats->inMissing);
  1010. p += snprint(p, ep-p, "inDup: %lud\n", stats->inDup);
  1011. p += snprint(p, ep-p, "inReorder: %lud\n", stats->inReorder);
  1012. p += snprint(p, ep-p, "inBadComp: %lud\n", stats->inBadComp);
  1013. p += snprint(p, ep-p, "inBadAuth: %lud\n", stats->inBadAuth);
  1014. p += snprint(p, ep-p, "inBadSeq: %lud\n", stats->inBadSeq);
  1015. p += snprint(p, ep-p, "inBadOther: %lud\n", stats->inBadOther);
  1016. USED(p);
  1017. qunlock(c);
  1018. }
  1019. // c is locked
  1020. static void
  1021. convack(Conv *c)
  1022. {
  1023. Block *b;
  1024. AckPkt *ack;
  1025. Stats *s;
  1026. int i;
  1027. b = allocb(sizeof(AckPkt));
  1028. ack = (AckPkt*)b->wp;
  1029. b->wp += sizeof(AckPkt);
  1030. s = &c->lstats;
  1031. hnputl(ack->cseq, c->in.controlseq);
  1032. hnputl(ack->outPackets, s->outPackets);
  1033. hnputl(ack->outDataPackets, s->outDataPackets);
  1034. hnputl(ack->outDataBytes, s->outDataBytes);
  1035. hnputl(ack->outCompDataBytes, s->outCompDataBytes);
  1036. for(i=0; i<NCompStats; i++)
  1037. hnputl(ack->outCompStats+i*4, s->outCompStats[i]);
  1038. hnputl(ack->inPackets, s->inPackets);
  1039. hnputl(ack->inDataPackets, s->inDataPackets);
  1040. hnputl(ack->inDataBytes, s->inDataBytes);
  1041. hnputl(ack->inCompDataBytes, s->inCompDataBytes);
  1042. hnputl(ack->inMissing, s->inMissing);
  1043. hnputl(ack->inDup, s->inDup);
  1044. hnputl(ack->inReorder, s->inReorder);
  1045. hnputl(ack->inBadComp, s->inBadComp);
  1046. hnputl(ack->inBadAuth, s->inBadAuth);
  1047. hnputl(ack->inBadSeq, s->inBadSeq);
  1048. hnputl(ack->inBadOther, s->inBadOther);
  1049. convoput(c, TControl, ControlAck, b);
  1050. }
  1051. // assume we hold lock for c
  1052. static Block *
  1053. conviput(Conv *c, Block *b, int control)
  1054. {
  1055. int type, subtype;
  1056. ulong seq, seqwrap;
  1057. long seqdiff;
  1058. int pad;
  1059. c->lstats.inPackets++;
  1060. if(BLEN(b) < 4) {
  1061. c->lstats.inBadOther++;
  1062. freeb(b);
  1063. return nil;
  1064. }
  1065. type = b->rp[0] >> 4;
  1066. subtype = b->rp[0] & 0xf;
  1067. b->rp += 1;
  1068. if(type == TConnect) {
  1069. conviconnect(c, subtype, b);
  1070. return nil;
  1071. }
  1072. switch(c->state) {
  1073. case CInit:
  1074. case CDial:
  1075. c->lstats.inBadOther++;
  1076. convoconnect(c, ConReset, c->dialid, c->acceptid);
  1077. convsetstate(c, CClosed);
  1078. break;
  1079. case CAccept:
  1080. case CRemoteClose:
  1081. case CLocalClose:
  1082. c->lstats.inBadOther++;
  1083. freeb(b);
  1084. return nil;
  1085. }
  1086. seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2];
  1087. b->rp += 3;
  1088. seqwrap = c->in.seqwrap;
  1089. seqdiff = seq - c->in.seq;
  1090. if(seqdiff < -(SeqMax*3/4)) {
  1091. seqwrap++;
  1092. seqdiff += SeqMax;
  1093. } else if(seqdiff > SeqMax*3/4) {
  1094. seqwrap--;
  1095. seqdiff -= SeqMax;
  1096. }
  1097. if(seqdiff <= 0) {
  1098. if(seqdiff <= -SeqWindow) {
  1099. if(0)print("old sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff);
  1100. c->lstats.inBadSeq++;
  1101. freeb(b);
  1102. return nil;
  1103. }
  1104. if(c->in.window & (1<<-seqdiff)) {
  1105. if(0)print("dup sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff);
  1106. c->lstats.inDup++;
  1107. freeb(b);
  1108. return nil;
  1109. }
  1110. c->lstats.inReorder++;
  1111. }
  1112. // ok the sequence number looks ok
  1113. if(0) print("coniput seq=%ulx\n", seq);
  1114. if(c->in.auth != 0) {
  1115. if(!(*c->in.auth)(&c->in, b->rp-4, BLEN(b)+4)) {
  1116. if(0)print("bad auth %ld\n", BLEN(b)+4);
  1117. c->lstats.inBadAuth++;
  1118. freeb(b);
  1119. return nil;
  1120. }
  1121. b->wp -= c->in.authlen;
  1122. }
  1123. if(c->in.cipher != 0) {
  1124. if(!(*c->in.cipher)(&c->in, b->rp, BLEN(b))) {
  1125. if(0)print("bad cipher\n");
  1126. c->lstats.inBadOther++;
  1127. freeb(b);
  1128. return nil;
  1129. }
  1130. b->rp += c->in.cipherivlen;
  1131. if(c->in.cipherblklen > 1) {
  1132. pad = b->wp[-1];
  1133. if(pad > BLEN(b)) {
  1134. if(0)print("pad too big\n");
  1135. c->lstats.inBadOther++;
  1136. freeb(b);
  1137. return nil;
  1138. }
  1139. b->wp -= pad;
  1140. }
  1141. }
  1142. // ok the packet is good
  1143. if(seqdiff > 0) {
  1144. while(seqdiff > 0 && c->in.window != 0) {
  1145. if((c->in.window & (1<<(SeqWindow-1))) == 0) {
  1146. c->lstats.inMissing++;
  1147. }
  1148. c->in.window <<= 1;
  1149. seqdiff--;
  1150. }
  1151. if(seqdiff > 0) {
  1152. c->lstats.inMissing += seqdiff;
  1153. seqdiff = 0;
  1154. }
  1155. c->in.seq = seq;
  1156. c->in.seqwrap = seqwrap;
  1157. }
  1158. c->in.window |= 1<<-seqdiff;
  1159. c->lastrecv = TK2SEC(m->ticks);
  1160. switch(type) {
  1161. case TControl:
  1162. convicontrol(c, subtype, b);
  1163. return nil;
  1164. case TData:
  1165. c->lstats.inDataPackets++;
  1166. c->lstats.inDataBytes += BLEN(b);
  1167. if(control)
  1168. break;
  1169. return b;
  1170. case TCompData:
  1171. c->lstats.inDataPackets++;
  1172. c->lstats.inCompDataBytes += BLEN(b);
  1173. b = convicomp(c, subtype, seq, b);
  1174. if(b == nil) {
  1175. c->lstats.inBadComp++;
  1176. return nil;
  1177. }
  1178. c->lstats.inDataBytes += BLEN(b);
  1179. if(control)
  1180. break;
  1181. return b;
  1182. }
  1183. if(0)print("dropping packet id=%d: type=%d n=%ld control=%d\n", c->id, type, BLEN(b), control);
  1184. c->lstats.inBadOther++;
  1185. freeb(b);
  1186. return nil;
  1187. }
  1188. // assume hold conv lock
  1189. static void
  1190. conviconnect(Conv *c, int subtype, Block *b)
  1191. {
  1192. ulong dialid;
  1193. ulong acceptid;
  1194. if(BLEN(b) != 8) {
  1195. freeb(b);
  1196. return;
  1197. }
  1198. dialid = nhgetl(b->rp);
  1199. acceptid = nhgetl(b->rp + 4);
  1200. freeb(b);
  1201. if(0)print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid);
  1202. if(subtype == ConReset) {
  1203. convsetstate(c, CClosed);
  1204. return;
  1205. }
  1206. switch(c->state) {
  1207. default:
  1208. panic("unknown state: %d", c->state);
  1209. case CInit:
  1210. break;
  1211. case CDial:
  1212. if(dialid != c->dialid)
  1213. goto Reset;
  1214. break;
  1215. case CAccept:
  1216. case COpen:
  1217. case CLocalClose:
  1218. case CRemoteClose:
  1219. if(dialid != c->dialid
  1220. || subtype != ConOpenRequest && acceptid != c->acceptid)
  1221. goto Reset;
  1222. break;
  1223. case CClosed:
  1224. goto Reset;
  1225. }
  1226. switch(subtype) {
  1227. case ConOpenRequest:
  1228. switch(c->state) {
  1229. case CInit:
  1230. c->dialid = dialid;
  1231. convsetstate(c, CAccept);
  1232. return;
  1233. case CAccept:
  1234. case COpen:
  1235. // duplicate ConOpenRequest that we ignore
  1236. return;
  1237. }
  1238. break;
  1239. case ConOpenAck:
  1240. switch(c->state) {
  1241. case CDial:
  1242. c->acceptid = acceptid;
  1243. convsetstate(c, COpen);
  1244. return;
  1245. case COpen:
  1246. // duplicate that we have to ack
  1247. convoconnect(c, ConOpenAckAck, acceptid, dialid);
  1248. return;
  1249. }
  1250. break;
  1251. case ConOpenAckAck:
  1252. switch(c->state) {
  1253. case CAccept:
  1254. convsetstate(c, COpen);
  1255. return;
  1256. case COpen:
  1257. case CLocalClose:
  1258. case CRemoteClose:
  1259. // duplicate that we ignore
  1260. return;
  1261. }
  1262. break;
  1263. case ConClose:
  1264. switch(c->state) {
  1265. case COpen:
  1266. convoconnect(c, ConCloseAck, dialid, acceptid);
  1267. convsetstate(c, CRemoteClose);
  1268. return;
  1269. case CRemoteClose:
  1270. // duplicate ConClose
  1271. convoconnect(c, ConCloseAck, dialid, acceptid);
  1272. return;
  1273. }
  1274. break;
  1275. case ConCloseAck:
  1276. switch(c->state) {
  1277. case CLocalClose:
  1278. convsetstate(c, CClosed);
  1279. return;
  1280. }
  1281. break;
  1282. }
  1283. Reset:
  1284. // invalid connection message - reset to sender
  1285. if(1)print("invalid conviconnect - sending reset\n");
  1286. convoconnect(c, ConReset, dialid, acceptid);
  1287. convsetstate(c, CClosed);
  1288. }
  1289. static void
  1290. convicontrol(Conv *c, int subtype, Block *b)
  1291. {
  1292. ulong cseq;
  1293. AckPkt *ack;
  1294. int i;
  1295. if(BLEN(b) < 4)
  1296. return;
  1297. cseq = nhgetl(b->rp);
  1298. switch(subtype){
  1299. case ControlMesg:
  1300. if(cseq == c->in.controlseq) {
  1301. if(0)print("duplicate control packet: %ulx\n", cseq);
  1302. // duplicate control packet
  1303. freeb(b);
  1304. if(c->in.controlpkt == nil)
  1305. convack(c);
  1306. return;
  1307. }
  1308. if(cseq != c->in.controlseq+1)
  1309. return;
  1310. c->in.controlseq = cseq;
  1311. b->rp += 4;
  1312. if(BLEN(b) == 0) {
  1313. // just a ping
  1314. freeb(b);
  1315. convack(c);
  1316. } else {
  1317. c->in.controlpkt = b;
  1318. if(0) print("recv %ld size=%ld\n", cseq, BLEN(b));
  1319. wakeup(&c->in.controlready);
  1320. }
  1321. return;
  1322. case ControlAck:
  1323. if(cseq != c->out.controlseq)
  1324. return;
  1325. if(BLEN(b) < sizeof(AckPkt))
  1326. return;
  1327. ack = (AckPkt*)(b->rp);
  1328. c->rstats.outPackets = nhgetl(ack->outPackets);
  1329. c->rstats.outDataPackets = nhgetl(ack->outDataPackets);
  1330. c->rstats.outDataBytes = nhgetl(ack->outDataBytes);
  1331. c->rstats.outCompDataBytes = nhgetl(ack->outCompDataBytes);
  1332. for(i=0; i<NCompStats; i++)
  1333. c->rstats.outCompStats[i] = nhgetl(ack->outCompStats + 4*i);
  1334. c->rstats.inPackets = nhgetl(ack->inPackets);
  1335. c->rstats.inDataPackets = nhgetl(ack->inDataPackets);
  1336. c->rstats.inDataBytes = nhgetl(ack->inDataBytes);
  1337. c->rstats.inCompDataBytes = nhgetl(ack->inCompDataBytes);
  1338. c->rstats.inMissing = nhgetl(ack->inMissing);
  1339. c->rstats.inDup = nhgetl(ack->inDup);
  1340. c->rstats.inReorder = nhgetl(ack->inReorder);
  1341. c->rstats.inBadComp = nhgetl(ack->inBadComp);
  1342. c->rstats.inBadAuth = nhgetl(ack->inBadAuth);
  1343. c->rstats.inBadSeq = nhgetl(ack->inBadSeq);
  1344. c->rstats.inBadOther = nhgetl(ack->inBadOther);
  1345. freeb(b);
  1346. freeb(c->out.controlpkt);
  1347. c->out.controlpkt = nil;
  1348. c->timeout = c->lastrecv + KeepAlive;
  1349. wakeup(&c->out.controlready);
  1350. return;
  1351. }
  1352. }
  1353. static Block*
  1354. convicomp(Conv *c, int subtype, ulong seq, Block *b)
  1355. {
  1356. if(c->in.comp == nil) {
  1357. freeb(b);
  1358. return nil;
  1359. }
  1360. if(!(*c->in.comp)(c, subtype, seq, &b))
  1361. return nil;
  1362. return b;
  1363. }
  1364. // c is locked
  1365. static void
  1366. convwriteblock(Conv *c, Block *b)
  1367. {
  1368. // simulated errors
  1369. if(c->drop && nrand(c->drop) == 0)
  1370. return;
  1371. if(waserror()) {
  1372. convsetstate(c, CClosed);
  1373. nexterror();
  1374. }
  1375. devtab[c->chan->type]->bwrite(c->chan, b, 0);
  1376. poperror();
  1377. }
  1378. // assume hold conv lock
  1379. static void
  1380. convoput(Conv *c, int type, int subtype, Block *b)
  1381. {
  1382. int pad;
  1383. c->lstats.outPackets++;
  1384. /* Make room for sdp trailer */
  1385. if(c->out.cipherblklen > 1)
  1386. pad = c->out.cipherblklen - (BLEN(b) + c->out.cipherivlen) % c->out.cipherblklen;
  1387. else
  1388. pad = 0;
  1389. b = padblock(b, -(pad+c->out.authlen));
  1390. if(pad) {
  1391. memset(b->wp, 0, pad-1);
  1392. b->wp[pad-1] = pad;
  1393. b->wp += pad;
  1394. }
  1395. /* Make space to fit sdp header */
  1396. b = padblock(b, 4 + c->out.cipherivlen);
  1397. b->rp[0] = (type << 4) | subtype;
  1398. c->out.seq++;
  1399. if(c->out.seq == (1<<24)) {
  1400. c->out.seq = 0;
  1401. c->out.seqwrap++;
  1402. }
  1403. b->rp[1] = c->out.seq>>16;
  1404. b->rp[2] = c->out.seq>>8;
  1405. b->rp[3] = c->out.seq;
  1406. if(c->out.cipher)
  1407. (*c->out.cipher)(&c->out, b->rp+4, BLEN(b)-4);
  1408. // auth
  1409. if(c->out.auth) {
  1410. b->wp += c->out.authlen;
  1411. (*c->out.auth)(&c->out, b->rp, BLEN(b));
  1412. }
  1413. convwriteblock(c, b);
  1414. }
  1415. // assume hold conv lock
  1416. static void
  1417. convoconnect(Conv *c, int op, ulong dialid, ulong acceptid)
  1418. {
  1419. Block *b;
  1420. c->lstats.outPackets++;
  1421. assert(c->chan != nil);
  1422. b = allocb(9);
  1423. b->wp[0] = (TConnect << 4) | op;
  1424. hnputl(b->wp+1, dialid);
  1425. hnputl(b->wp+5, acceptid);
  1426. b->wp += 9;
  1427. if(!waserror()) {
  1428. convwriteblock(c, b);
  1429. poperror();
  1430. }
  1431. }
  1432. static Block *
  1433. convreadblock(Conv *c, int n)
  1434. {
  1435. Block *b;
  1436. Chan *ch;
  1437. qlock(&c->readlk);
  1438. if(waserror()) {
  1439. c->readproc = nil;
  1440. qunlock(&c->readlk);
  1441. nexterror();
  1442. }
  1443. qlock(c);
  1444. if(c->state == CClosed) {
  1445. qunlock(c);
  1446. error("closed");
  1447. }
  1448. c->readproc = up;
  1449. ch = c->chan;
  1450. assert(c->ref > 0);
  1451. qunlock(c);
  1452. b = devtab[ch->type]->bread(ch, n, 0);
  1453. c->readproc = nil;
  1454. poperror();
  1455. qunlock(&c->readlk);
  1456. return b;
  1457. }
  1458. static int
  1459. readready(void *a)
  1460. {
  1461. Conv *c = a;
  1462. return c->in.controlpkt != nil || (c->state == CClosed) || (c->state == CRemoteClose);
  1463. }
  1464. static Block *
  1465. readcontrol(Conv *c, int n)
  1466. {
  1467. Block *b;
  1468. USED(n);
  1469. qlock(&c->in.controllk);
  1470. if(waserror()) {
  1471. qunlock(&c->in.controllk);
  1472. nexterror();
  1473. }
  1474. qlock(c); // this lock is not held during the sleep below
  1475. for(;;) {
  1476. if(c->chan == nil || c->state == CClosed) {
  1477. qunlock(c);
  1478. if(0)print("readcontrol: return error - state = %s\n", convstatename[c->state]);
  1479. error("conversation closed");
  1480. }
  1481. if(c->in.controlpkt != nil)
  1482. break;
  1483. if(c->state == CRemoteClose) {
  1484. qunlock(c);
  1485. if(0)print("readcontrol: return nil - state = %s\n", convstatename[c->state]);
  1486. poperror();
  1487. return nil;
  1488. }
  1489. qunlock(c);
  1490. sleep(&c->in.controlready, readready, c);
  1491. qlock(c);
  1492. }
  1493. convack(c);
  1494. b = c->in.controlpkt;
  1495. c->in.controlpkt = nil;
  1496. qunlock(c);
  1497. poperror();
  1498. qunlock(&c->in.controllk);
  1499. return b;
  1500. }
  1501. static int
  1502. writeready(void *a)
  1503. {
  1504. Conv *c = a;
  1505. return c->out.controlpkt == nil || (c->state == CClosed) || (c->state == CRemoteClose);
  1506. }
  1507. // c is locked
  1508. static void
  1509. writewait(Conv *c)
  1510. {
  1511. for(;;) {
  1512. if(c->state == CFree || c->state == CInit ||
  1513. c->state == CClosed || c->state == CRemoteClose)
  1514. error("conversation closed");
  1515. if(c->state == COpen && c->out.controlpkt == nil)
  1516. break;
  1517. qunlock(c);
  1518. if(waserror()) {
  1519. qlock(c);
  1520. nexterror();
  1521. }
  1522. sleep(&c->out.controlready, writeready, c);
  1523. poperror();
  1524. qlock(c);
  1525. }
  1526. }
  1527. static void
  1528. writecontrol(Conv *c, void *p, int n, int wait)
  1529. {
  1530. Block *b;
  1531. qlock(&c->out.controllk);
  1532. qlock(c);
  1533. if(waserror()) {
  1534. qunlock(c);
  1535. qunlock(&c->out.controllk);
  1536. nexterror();
  1537. }
  1538. writewait(c);
  1539. b = allocb(4+n);
  1540. c->out.controlseq++;
  1541. hnputl(b->wp, c->out.controlseq);
  1542. memmove(b->wp+4, p, n);
  1543. b->wp += 4+n;
  1544. c->out.controlpkt = b;
  1545. convretryinit(c);
  1546. convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));
  1547. if(wait)
  1548. writewait(c);
  1549. poperror();
  1550. qunlock(c);
  1551. qunlock(&c->out.controllk);
  1552. }
  1553. static Block *
  1554. readdata(Conv *c, int n)
  1555. {
  1556. Block *b;
  1557. int nn;
  1558. for(;;) {
  1559. // some slack for tunneling overhead
  1560. nn = n + 100;
  1561. // make sure size is big enough for control messages
  1562. if(nn < 1000)
  1563. nn = 1000;
  1564. b = convreadblock(c, nn);
  1565. if(b == nil)
  1566. return nil;
  1567. qlock(c);
  1568. if(waserror()) {
  1569. qunlock(c);
  1570. return nil;
  1571. }
  1572. b = conviput(c, b, 0);
  1573. poperror();
  1574. qunlock(c);
  1575. if(b != nil) {
  1576. if(BLEN(b) > n)
  1577. b->wp = b->rp + n;
  1578. return b;
  1579. }
  1580. }
  1581. }
  1582. static long
  1583. writedata(Conv *c, Block *b)
  1584. {
  1585. int n;
  1586. ulong seq;
  1587. int subtype;
  1588. qlock(c);
  1589. if(waserror()) {
  1590. qunlock(c);
  1591. nexterror();
  1592. }
  1593. if(c->state != COpen) {
  1594. freeb(b);
  1595. error("conversation not open");
  1596. }
  1597. n = BLEN(b);
  1598. c->lstats.outDataPackets++;
  1599. c->lstats.outDataBytes += n;
  1600. if(c->out.comp != nil) {
  1601. // must generate same value as convoput
  1602. seq = (c->out.seq + 1) & (SeqMax-1);
  1603. subtype = (*c->out.comp)(c, 0, seq, &b);
  1604. c->lstats.outCompDataBytes += BLEN(b);
  1605. convoput(c, TCompData, subtype, b);
  1606. } else
  1607. convoput(c, TData, 0, b);
  1608. poperror();
  1609. qunlock(c);
  1610. return n;
  1611. }
  1612. static void
  1613. convreader(void *a)
  1614. {
  1615. Conv *c = a;
  1616. Block *b;
  1617. qlock(c);
  1618. assert(c->reader == 1);
  1619. while(c->dataopen == 0 && c->state != CClosed) {
  1620. qunlock(c);
  1621. b = nil;
  1622. if(!waserror()) {
  1623. b = convreadblock(c, 2000);
  1624. poperror();
  1625. }
  1626. qlock(c);
  1627. if(b == nil) {
  1628. if(strcmp(up->errstr, Eintr) != 0) {
  1629. convsetstate(c, CClosed);
  1630. break;
  1631. }
  1632. } else if(!waserror()) {
  1633. conviput(c, b, 1);
  1634. poperror();
  1635. }
  1636. }
  1637. c->reader = 0;
  1638. convderef(c);
  1639. qunlock(c);
  1640. pexit("hangup", 1);
  1641. }
  1642. /* ciphers, authenticators, and compressors */
  1643. static void
  1644. setalg(Conv *c, char *name, Algorithm *alg, Algorithm **p)
  1645. {
  1646. for(; alg->name; alg++)
  1647. if(strcmp(name, alg->name) == 0)
  1648. break;
  1649. if(alg->name == nil)
  1650. error("unknown algorithm");
  1651. *p = alg;
  1652. alg->init(c);
  1653. }
  1654. static void
  1655. setsecret(OneWay *ow, char *secret)
  1656. {
  1657. char *p;
  1658. int i, c;
  1659. i = 0;
  1660. memset(ow->secret, 0, sizeof(ow->secret));
  1661. for(p=secret; *p; p++) {
  1662. if(i >= sizeof(ow->secret)*2)
  1663. break;
  1664. c = *p;
  1665. if(c >= '0' && c <= '9')
  1666. c -= '0';
  1667. else if(c >= 'a' && c <= 'f')
  1668. c -= 'a'-10;
  1669. else if(c >= 'A' && c <= 'F')
  1670. c -= 'A'-10;
  1671. else
  1672. error("bad character in secret");
  1673. if((i&1) == 0)
  1674. c <<= 4;
  1675. ow->secret[i>>1] |= c;
  1676. i++;
  1677. }
  1678. }
  1679. static void
  1680. setkey(uchar *key, int n, OneWay *ow, char *prefix)
  1681. {
  1682. uchar ibuf[SHA1dlen], obuf[MD5dlen], salt[10];
  1683. int i, round = 0;
  1684. while(n > 0){
  1685. for(i=0; i<round+1; i++)
  1686. salt[i] = 'A'+round;
  1687. sha1((uchar*)prefix, strlen(prefix), ibuf, sha1(salt, round+1, nil, nil));
  1688. md5(ibuf, SHA1dlen, obuf, md5(ow->secret, sizeof(ow->secret), nil, nil));
  1689. i = (n<MD5dlen) ? n : MD5dlen;
  1690. memmove(key, obuf, i);
  1691. key += i;
  1692. n -= i;
  1693. if(++round > sizeof salt)
  1694. panic("setkey: you ask too much");
  1695. }
  1696. }
  1697. static void
  1698. cipherfree(Conv *c)
  1699. {
  1700. if(c->in.cipherstate) {
  1701. free(c->in.cipherstate);
  1702. c->in.cipherstate = nil;
  1703. }
  1704. if(c->out.cipherstate) {
  1705. free(c->out.cipherstate);
  1706. c->out.cipherstate = nil;
  1707. }
  1708. c->in.cipher = nil;
  1709. c->in.cipherblklen = 0;
  1710. c->out.cipherblklen = 0;
  1711. c->in.cipherivlen = 0;
  1712. c->out.cipherivlen = 0;
  1713. }
  1714. static void
  1715. authfree(Conv *c)
  1716. {
  1717. if(c->in.authstate) {
  1718. free(c->in.authstate);
  1719. c->in.authstate = nil;
  1720. }
  1721. if(c->out.authstate) {
  1722. free(c->out.authstate);
  1723. c->out.authstate = nil;
  1724. }
  1725. c->in.auth = nil;
  1726. c->in.authlen = 0;
  1727. c->out.authlen = 0;
  1728. }
  1729. static void
  1730. compfree(Conv *c)
  1731. {
  1732. if(c->in.compstate) {
  1733. free(c->in.compstate);
  1734. c->in.compstate = nil;
  1735. }
  1736. if(c->out.compstate) {
  1737. free(c->out.compstate);
  1738. c->out.compstate = nil;
  1739. }
  1740. c->in.comp = nil;
  1741. }
  1742. static void
  1743. nullcipherinit(Conv *c)
  1744. {
  1745. cipherfree(c);
  1746. }
  1747. static int
  1748. desencrypt(OneWay *ow, uchar *p, int n)
  1749. {
  1750. uchar *pp, *ip, *eip, *ep;
  1751. DESstate *ds = ow->cipherstate;
  1752. if(n < 8 || (n & 0x7 != 0))
  1753. return 0;
  1754. ep = p + n;
  1755. memmove(p, ds->ivec, 8);
  1756. for(p += 8; p < ep; p += 8){
  1757. pp = p;
  1758. ip = ds->ivec;
  1759. for(eip = ip+8; ip < eip; )
  1760. *pp++ ^= *ip++;
  1761. block_cipher(ds->expanded, p, 0);
  1762. memmove(ds->ivec, p, 8);
  1763. }
  1764. return 1;
  1765. }
  1766. static int
  1767. desdecrypt(OneWay *ow, uchar *p, int n)
  1768. {
  1769. uchar tmp[8];
  1770. uchar *tp, *ip, *eip, *ep;
  1771. DESstate *ds = ow->cipherstate;
  1772. if(n < 8 || (n & 0x7 != 0))
  1773. return 0;
  1774. ep = p + n;
  1775. memmove(ds->ivec, p, 8);
  1776. p += 8;
  1777. while(p < ep){
  1778. memmove(tmp, p, 8);
  1779. block_cipher(ds->expanded, p, 1);
  1780. tp = tmp;
  1781. ip = ds->ivec;
  1782. for(eip = ip+8; ip < eip; ){
  1783. *p++ ^= *ip;
  1784. *ip++ = *tp++;
  1785. }
  1786. }
  1787. return 1;
  1788. }
  1789. static void
  1790. descipherinit(Conv *c)
  1791. {
  1792. uchar key[8];
  1793. uchar ivec[8];
  1794. int i;
  1795. int n = c->cipher->keylen;
  1796. cipherfree(c);
  1797. if(n > sizeof(key))
  1798. n = sizeof(key);
  1799. /* in */
  1800. memset(key, 0, sizeof(key));
  1801. setkey(key, n, &c->in, "cipher");
  1802. memset(ivec, 0, sizeof(ivec));
  1803. c->in.cipherblklen = 8;
  1804. c->in.cipherivlen = 8;
  1805. c->in.cipher = desdecrypt;
  1806. c->in.cipherstate = smalloc(sizeof(DESstate));
  1807. setupDESstate(c->in.cipherstate, key, ivec);
  1808. /* out */
  1809. memset(key, 0, sizeof(key));
  1810. setkey(key, n, &c->out, "cipher");
  1811. for(i=0; i<8; i++)
  1812. ivec[i] = nrand(256);
  1813. c->out.cipherblklen = 8;
  1814. c->out.cipherivlen = 8;
  1815. c->out.cipher = desencrypt;
  1816. c->out.cipherstate = smalloc(sizeof(DESstate));
  1817. setupDESstate(c->out.cipherstate, key, ivec);
  1818. }
  1819. static int
  1820. rc4encrypt(OneWay *ow, uchar *p, int n)
  1821. {
  1822. CipherRc4 *cr = ow->cipherstate;
  1823. if(n < 4)
  1824. return 0;
  1825. hnputl(p, cr->cseq);
  1826. p += 4;
  1827. n -= 4;
  1828. rc4(&cr->current, p, n);
  1829. cr->cseq += n;
  1830. return 1;
  1831. }
  1832. static int
  1833. rc4decrypt(OneWay *ow, uchar *p, int n)
  1834. {
  1835. CipherRc4 *cr = ow->cipherstate;
  1836. RC4state tmpstate;
  1837. ulong seq;
  1838. long d, dd;
  1839. if(n < 4)
  1840. return 0;
  1841. seq = nhgetl(p);
  1842. p += 4;
  1843. n -= 4;
  1844. d = seq-cr->cseq;
  1845. if(d == 0) {
  1846. rc4(&cr->current, p, n);
  1847. cr->cseq += n;
  1848. if(cr->ovalid) {
  1849. dd = cr->cseq - cr->lgseq;
  1850. if(dd > RC4back)
  1851. cr->ovalid = 0;
  1852. }
  1853. } else if(d > 0) {
  1854. //print("missing packet: %uld %ld\n", seq, d);
  1855. // this link is hosed
  1856. if(d > RC4forward)
  1857. return 0;
  1858. cr->lgseq = seq;
  1859. if(!cr->ovalid) {
  1860. cr->ovalid = 1;
  1861. cr->oseq = cr->cseq;
  1862. memmove(&cr->old, &cr->current, sizeof(RC4state));
  1863. }
  1864. rc4skip(&cr->current, d);
  1865. rc4(&cr->current, p, n);
  1866. cr->cseq = seq+n;
  1867. } else {
  1868. //print("reordered packet: %uld %ld\n", seq, d);
  1869. dd = seq - cr->oseq;
  1870. if(!cr->ovalid || -d > RC4back || dd < 0)
  1871. return 0;
  1872. memmove(&tmpstate, &cr->old, sizeof(RC4state));
  1873. rc4skip(&tmpstate, dd);
  1874. rc4(&tmpstate, p, n);
  1875. return 1;
  1876. }
  1877. // move old state up
  1878. if(cr->ovalid) {
  1879. dd = cr->cseq - RC4back - cr->oseq;
  1880. if(dd > 0) {
  1881. rc4skip(&cr->old, dd);
  1882. cr->oseq += dd;
  1883. }
  1884. }
  1885. return 1;
  1886. }
  1887. static void
  1888. rc4cipherinit(Conv *c)
  1889. {
  1890. uchar key[32];
  1891. CipherRc4 *cr;
  1892. int n;
  1893. cipherfree(c);
  1894. n = c->cipher->keylen;
  1895. if(n > sizeof(key))
  1896. n = sizeof(key);
  1897. /* in */
  1898. memset(key, 0, sizeof(key));
  1899. setkey(key, n, &c->in, "cipher");
  1900. c->in.cipherblklen = 1;
  1901. c->in.cipherivlen = 4;
  1902. c->in.cipher = rc4decrypt;
  1903. cr = smalloc(sizeof(CipherRc4));
  1904. memset(cr, 0, sizeof(*cr));
  1905. setupRC4state(&cr->current, key, n);
  1906. c->in.cipherstate = cr;
  1907. /* out */
  1908. memset(key, 0, sizeof(key));
  1909. setkey(key, n, &c->out, "cipher");
  1910. c->out.cipherblklen = 1;
  1911. c->out.cipherivlen = 4;
  1912. c->out.cipher = rc4encrypt;
  1913. cr = smalloc(sizeof(CipherRc4));
  1914. memset(cr, 0, sizeof(*cr));
  1915. setupRC4state(&cr->current, key, n);
  1916. c->out.cipherstate = cr;
  1917. }
  1918. static void
  1919. nullauthinit(Conv *c)
  1920. {
  1921. authfree(c);
  1922. }
  1923. static void
  1924. shaauthinit(Conv *c)
  1925. {
  1926. authfree(c);
  1927. }
  1928. static void
  1929. seanq_hmac_md5(uchar hash[MD5dlen], ulong wrap, uchar *t, long tlen, uchar *key, long klen)
  1930. {
  1931. uchar ipad[65], opad[65], wbuf[4];
  1932. int i;
  1933. DigestState *digest;
  1934. uchar innerhash[MD5dlen];
  1935. for(i=0; i<64; i++){
  1936. ipad[i] = 0x36;
  1937. opad[i] = 0x5c;
  1938. }
  1939. ipad[64] = opad[64] = 0;
  1940. for(i=0; i<klen; i++){
  1941. ipad[i] ^= key[i];
  1942. opad[i] ^= key[i];
  1943. }
  1944. hnputl(wbuf, wrap);
  1945. digest = md5(ipad, 64, nil, nil);
  1946. digest = md5(wbuf, sizeof(wbuf), nil, digest);
  1947. md5(t, tlen, innerhash, digest);
  1948. digest = md5(opad, 64, nil, nil);
  1949. md5(innerhash, MD5dlen, hash, digest);
  1950. }
  1951. static int
  1952. md5auth(OneWay *ow, uchar *t, int tlen)
  1953. {
  1954. uchar hash[MD5dlen];
  1955. int r;
  1956. if(tlen < ow->authlen)
  1957. return 0;
  1958. tlen -= ow->authlen;
  1959. memset(hash, 0, MD5dlen);
  1960. seanq_hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16);
  1961. r = memcmp(t+tlen, hash, ow->authlen) == 0;
  1962. memmove(t+tlen, hash, ow->authlen);
  1963. return r;
  1964. }
  1965. static void
  1966. md5authinit(Conv *c)
  1967. {
  1968. int keylen;
  1969. authfree(c);
  1970. keylen = c->auth->keylen;
  1971. if(keylen > 16)
  1972. keylen = 16;
  1973. /* in */
  1974. c->in.authstate = smalloc(16);
  1975. memset(c->in.authstate, 0, 16);
  1976. setkey(c->in.authstate, keylen, &c->in, "auth");
  1977. c->in.authlen = 12;
  1978. c->in.auth = md5auth;
  1979. /* out */
  1980. c->out.authstate = smalloc(16);
  1981. memset(c->out.authstate, 0, 16);
  1982. setkey(c->out.authstate, keylen, &c->out, "auth");
  1983. c->out.authlen = 12;
  1984. c->out.auth = md5auth;
  1985. }
  1986. static void
  1987. nullcompinit(Conv *c)
  1988. {
  1989. compfree(c);
  1990. }
  1991. static int
  1992. thwackcomp(Conv *c, int, ulong seq, Block **bp)
  1993. {
  1994. Block *b, *bb;
  1995. int nn;
  1996. ulong ackseq;
  1997. uchar mask;
  1998. // add ack info
  1999. b = padblock(*bp, 4);
  2000. ackseq = unthwackstate(c->in.compstate, &mask);
  2001. b->rp[0] = mask;
  2002. b->rp[1] = ackseq>>16;
  2003. b->rp[2] = ackseq>>8;
  2004. b->rp[3] = ackseq;
  2005. bb = allocb(BLEN(b));
  2006. nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats);
  2007. if(nn < 0) {
  2008. freeb(bb);
  2009. *bp = b;
  2010. return ThwackU;
  2011. } else {
  2012. bb->wp += nn;
  2013. freeb(b);
  2014. *bp = bb;
  2015. return ThwackC;
  2016. }
  2017. }
  2018. static int
  2019. thwackuncomp(Conv *c, int subtype, ulong seq, Block **bp)
  2020. {
  2021. Block *b, *bb;
  2022. ulong mask;
  2023. ulong mseq;
  2024. int n;
  2025. switch(subtype) {
  2026. default:
  2027. return 0;
  2028. case ThwackU:
  2029. b = *bp;
  2030. mask = b->rp[0];
  2031. mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3];
  2032. b->rp += 4;
  2033. thwackack(c->out.compstate, mseq, mask);
  2034. return 1;
  2035. case ThwackC:
  2036. bb = *bp;
  2037. b = allocb(ThwMaxBlock);
  2038. n = unthwack(c->in.compstate, b->wp, ThwMaxBlock, bb->rp, BLEN(bb), seq);
  2039. freeb(bb);
  2040. if(n < 0) {
  2041. if(0)print("unthwack failed: %d\n", n);
  2042. freeb(b);
  2043. return 0;
  2044. }
  2045. b->wp += n;
  2046. mask = b->rp[0];
  2047. mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3];
  2048. thwackack(c->out.compstate, mseq, mask);
  2049. b->rp += 4;
  2050. *bp = b;
  2051. return 1;
  2052. }
  2053. }
  2054. static void
  2055. thwackcompinit(Conv *c)
  2056. {
  2057. compfree(c);
  2058. c->in.compstate = malloc(sizeof(Unthwack));
  2059. if(c->in.compstate == nil)
  2060. error(Enomem);
  2061. unthwackinit(c->in.compstate);
  2062. c->out.compstate = malloc(sizeof(Thwack));
  2063. if(c->out.compstate == nil)
  2064. error(Enomem);
  2065. thwackinit(c->out.compstate);
  2066. c->in.comp = thwackuncomp;
  2067. c->out.comp = thwackcomp;
  2068. }