devsdp.c 44 KB

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