ipifc.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "ip.h"
  8. #include "ipv6.h"
  9. #define DPRINT if(0)print
  10. enum {
  11. Maxmedia = 32,
  12. Nself = Maxmedia*5,
  13. NHASH = (1<<6),
  14. NCACHE = 256,
  15. QMAX = 64*1024-1,
  16. };
  17. Medium *media[Maxmedia] =
  18. {
  19. 0
  20. };
  21. /*
  22. * cache of local addresses (addresses we answer to)
  23. */
  24. struct Ipself
  25. {
  26. uchar a[IPaddrlen];
  27. Ipself *hnext; /* next address in the hash table */
  28. Iplink *link; /* binding twixt Ipself and Ipifc */
  29. ulong expire;
  30. uchar type; /* type of address */
  31. int ref;
  32. Ipself *next; /* free list */
  33. };
  34. struct Ipselftab
  35. {
  36. QLock;
  37. int inited;
  38. int acceptall; /* true if an interface has the null address */
  39. Ipself *hash[NHASH]; /* hash chains */
  40. };
  41. /*
  42. * Multicast addresses are chained onto a Chan so that
  43. * we can remove them when the Chan is closed.
  44. */
  45. typedef struct Ipmcast Ipmcast;
  46. struct Ipmcast
  47. {
  48. Ipmcast *next;
  49. uchar ma[IPaddrlen]; /* multicast address */
  50. uchar ia[IPaddrlen]; /* interface address */
  51. };
  52. /* quick hash for ip addresses */
  53. #define hashipa(a) ( ( ((a)[IPaddrlen-2]<<8) | (a)[IPaddrlen-1] )%NHASH )
  54. static char tifc[] = "ifc ";
  55. static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
  56. static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
  57. static char* ipifcjoinmulti(Ipifc *ifc, char **argv, int argc);
  58. static char* ipifcleavemulti(Ipifc *ifc, char **argv, int argc);
  59. static void ipifcregisterproxy(Fs*, Ipifc*, uchar*);
  60. static char* ipifcremlifc(Ipifc*, Iplifc*);
  61. /*
  62. * link in a new medium
  63. */
  64. void
  65. addipmedium(Medium *med)
  66. {
  67. int i;
  68. for(i = 0; i < nelem(media)-1; i++)
  69. if(media[i] == nil){
  70. media[i] = med;
  71. break;
  72. }
  73. }
  74. /*
  75. * find the medium with this name
  76. */
  77. Medium*
  78. ipfindmedium(char *name)
  79. {
  80. Medium **mp;
  81. for(mp = media; *mp != nil; mp++)
  82. if(strcmp((*mp)->name, name) == 0)
  83. break;
  84. return *mp;
  85. }
  86. /*
  87. * attach a device (or pkt driver) to the interface.
  88. * called with c locked
  89. */
  90. static char*
  91. ipifcbind(Conv *c, char **argv, int argc)
  92. {
  93. Ipifc *ifc;
  94. Medium *m;
  95. if(argc < 2)
  96. return Ebadarg;
  97. ifc = (Ipifc*)c->ptcl;
  98. /* bind the device to the interface */
  99. m = ipfindmedium(argv[1]);
  100. if(m == nil)
  101. return "unknown interface type";
  102. wlock(ifc);
  103. if(ifc->m != nil){
  104. wunlock(ifc);
  105. return "interface already bound";
  106. }
  107. if(waserror()){
  108. wunlock(ifc);
  109. nexterror();
  110. }
  111. /* do medium specific binding */
  112. (*m->bind)(ifc, argc, argv);
  113. /* set the bound device name */
  114. if(argc > 2)
  115. strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
  116. else
  117. sprint(ifc->dev, "%s%d", m->name, c->x);
  118. ifc->dev[sizeof(ifc->dev)-1] = 0;
  119. /* set up parameters */
  120. ifc->m = m;
  121. ifc->mintu = ifc->m->mintu;
  122. ifc->maxtu = ifc->m->maxtu;
  123. if(ifc->m->unbindonclose == 0)
  124. ifc->conv->inuse++;
  125. ifc->rp.mflag = 0; // default not managed
  126. ifc->rp.oflag = 0;
  127. ifc->rp.maxraint = 600000; // millisecs
  128. ifc->rp.minraint = 200000;
  129. ifc->rp.linkmtu = 0; // no mtu sent
  130. ifc->rp.reachtime = 0;
  131. ifc->rp.rxmitra = 0;
  132. ifc->rp.ttl = MAXTTL;
  133. ifc->rp.routerlt = 3*(ifc->rp.maxraint);
  134. /* any ancillary structures (like routes) no longer pertain */
  135. ifc->ifcid++;
  136. /* reopen all the queues closed by a previous unbind */
  137. qreopen(c->rq);
  138. qreopen(c->eq);
  139. qreopen(c->sq);
  140. wunlock(ifc);
  141. poperror();
  142. return nil;
  143. }
  144. /*
  145. * detach a device from an interface, close the interface
  146. * called with ifc->conv closed
  147. */
  148. static char*
  149. ipifcunbind(Ipifc *ifc)
  150. {
  151. char *err;
  152. if(waserror()){
  153. wunlock(ifc);
  154. nexterror();
  155. }
  156. wlock(ifc);
  157. /* dissociate routes */
  158. if(ifc->m != nil && ifc->m->unbindonclose == 0)
  159. ifc->conv->inuse--;
  160. ifc->ifcid++;
  161. /* disassociate device */
  162. if(ifc->m != nil && ifc->m->unbind)
  163. (*ifc->m->unbind)(ifc);
  164. memset(ifc->dev, 0, sizeof(ifc->dev));
  165. ifc->arg = nil;
  166. ifc->reassemble = 0;
  167. /* close queues to stop queuing of packets */
  168. qclose(ifc->conv->rq);
  169. qclose(ifc->conv->wq);
  170. qclose(ifc->conv->sq);
  171. /* disassociate logical interfaces */
  172. while(ifc->lifc){
  173. err = ipifcremlifc(ifc, ifc->lifc);
  174. if(err)
  175. error(err);
  176. }
  177. ifc->m = nil;
  178. wunlock(ifc);
  179. poperror();
  180. return nil;
  181. }
  182. char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lud pktout %lud errin %lud errout %lud\n";
  183. char slineformat[] = " %-40I %-10M %-40I %-12lud %-12lud\n";
  184. static int
  185. ipifcstate(Conv *c, char *state, int n)
  186. {
  187. Ipifc *ifc;
  188. Iplifc *lifc;
  189. int m;
  190. ifc = (Ipifc*)c->ptcl;
  191. m = snprint(state, n, sfixedformat,
  192. ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
  193. ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
  194. ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
  195. ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
  196. ifc->in, ifc->out, ifc->inerr, ifc->outerr);
  197. rlock(ifc);
  198. for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next)
  199. m += snprint(state+m, n - m, slineformat,
  200. lifc->local, lifc->mask, lifc->remote,
  201. lifc->validlt, lifc->preflt);
  202. if(ifc->lifc == nil)
  203. m += snprint(state+m, n - m, "\n");
  204. runlock(ifc);
  205. return m;
  206. }
  207. static int
  208. ipifclocal(Conv *c, char *state, int n)
  209. {
  210. Ipifc *ifc;
  211. Iplifc *lifc;
  212. Iplink *link;
  213. int m;
  214. ifc = (Ipifc*)c->ptcl;
  215. m = 0;
  216. rlock(ifc);
  217. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  218. m += snprint(state+m, n - m, "%-40.40I ->", lifc->local);
  219. for(link = lifc->link; link; link = link->lifclink)
  220. m += snprint(state+m, n - m, " %-40.40I", link->self->a);
  221. m += snprint(state+m, n - m, "\n");
  222. }
  223. runlock(ifc);
  224. return m;
  225. }
  226. static int
  227. ipifcinuse(Conv *c)
  228. {
  229. Ipifc *ifc;
  230. ifc = (Ipifc*)c->ptcl;
  231. return ifc->m != nil;
  232. }
  233. /*
  234. * called when a process writes to an interface's 'data'
  235. */
  236. static void
  237. ipifckick(void *x)
  238. {
  239. Conv *c = x;
  240. Block *bp;
  241. Ipifc *ifc;
  242. bp = qget(c->wq);
  243. if(bp == nil)
  244. return;
  245. ifc = (Ipifc*)c->ptcl;
  246. if(!canrlock(ifc)){
  247. freeb(bp);
  248. return;
  249. }
  250. if(waserror()){
  251. runlock(ifc);
  252. nexterror();
  253. }
  254. if(ifc->m == nil || ifc->m->pktin == nil)
  255. freeb(bp);
  256. else
  257. (*ifc->m->pktin)(c->p->f, ifc, bp);
  258. runlock(ifc);
  259. poperror();
  260. }
  261. /*
  262. * called when a new ipifc structure is created
  263. */
  264. static void
  265. ipifccreate(Conv *c)
  266. {
  267. Ipifc *ifc;
  268. c->rq = qopen(QMAX, 0, 0, 0);
  269. c->sq = qopen(2*QMAX, 0, 0, 0);
  270. c->wq = qopen(QMAX, Qkick, ipifckick, c);
  271. ifc = (Ipifc*)c->ptcl;
  272. ifc->conv = c;
  273. ifc->unbinding = 0;
  274. ifc->m = nil;
  275. ifc->reassemble = 0;
  276. }
  277. /*
  278. * called after last close of ipifc data or ctl
  279. * called with c locked, we must unlock
  280. */
  281. static void
  282. ipifcclose(Conv *c)
  283. {
  284. Ipifc *ifc;
  285. Medium *m;
  286. ifc = (Ipifc*)c->ptcl;
  287. m = ifc->m;
  288. if(m != nil && m->unbindonclose)
  289. ipifcunbind(ifc);
  290. }
  291. /*
  292. * change an interface's mtu
  293. */
  294. char*
  295. ipifcsetmtu(Ipifc *ifc, char **argv, int argc)
  296. {
  297. int mtu;
  298. if(argc < 2)
  299. return Ebadarg;
  300. if(ifc->m == nil)
  301. return Ebadarg;
  302. mtu = strtoul(argv[1], 0, 0);
  303. if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
  304. return Ebadarg;
  305. ifc->maxtu = mtu;
  306. return nil;
  307. }
  308. /*
  309. * add an address to an interface.
  310. */
  311. char*
  312. ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
  313. {
  314. uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
  315. uchar bcast[IPaddrlen], net[IPaddrlen];
  316. Iplifc *lifc, **l;
  317. int i, type, mtu;
  318. Fs *f;
  319. int sendnbrdisc = 0;
  320. if(ifc->m == nil)
  321. return "ipifc not yet bound to device";
  322. f = ifc->conv->p->f;
  323. type = Rifc;
  324. memset(ip, 0, IPaddrlen);
  325. memset(mask, 0, IPaddrlen);
  326. memset(rem, 0, IPaddrlen);
  327. switch(argc){
  328. case 6:
  329. if(strcmp(argv[5], "proxy") == 0)
  330. type |= Rproxy;
  331. /* fall through */
  332. case 5:
  333. mtu = strtoul(argv[4], 0, 0);
  334. if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
  335. ifc->maxtu = mtu;
  336. /* fall through */
  337. case 4:
  338. parseip(ip, argv[1]);
  339. parseipmask(mask, argv[2]);
  340. parseip(rem, argv[3]);
  341. maskip(rem, mask, net);
  342. break;
  343. case 3:
  344. parseip(ip, argv[1]);
  345. parseipmask(mask, argv[2]);
  346. maskip(ip, mask, rem);
  347. maskip(rem, mask, net);
  348. break;
  349. case 2:
  350. parseip(ip, argv[1]);
  351. memmove(mask, defmask(ip), IPaddrlen);
  352. maskip(ip, mask, rem);
  353. maskip(rem, mask, net);
  354. break;
  355. default:
  356. return Ebadarg;
  357. break;
  358. }
  359. if(isv4(ip))
  360. tentative = 0;
  361. wlock(ifc);
  362. /* ignore if this is already a local address for this ifc */
  363. for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
  364. if(ipcmp(lifc->local, ip) == 0) {
  365. if(lifc->tentative != tentative)
  366. lifc->tentative = tentative;
  367. if(lifcp != nil) {
  368. lifc->onlink = lifcp->onlink;
  369. lifc->autoflag = lifcp->autoflag;
  370. lifc->validlt = lifcp->validlt;
  371. lifc->preflt = lifcp->preflt;
  372. lifc->origint = lifcp->origint;
  373. }
  374. goto out;
  375. }
  376. }
  377. /* add the address to the list of logical ifc's for this ifc */
  378. lifc = smalloc(sizeof(Iplifc));
  379. ipmove(lifc->local, ip);
  380. ipmove(lifc->mask, mask);
  381. ipmove(lifc->remote, rem);
  382. ipmove(lifc->net, net);
  383. lifc->tentative = tentative;
  384. if(lifcp != nil) {
  385. lifc->onlink = lifcp->onlink;
  386. lifc->autoflag = lifcp->autoflag;
  387. lifc->validlt = lifcp->validlt;
  388. lifc->preflt = lifcp->preflt;
  389. lifc->origint = lifcp->origint;
  390. }
  391. else { // default values
  392. lifc->onlink = 1;
  393. lifc->autoflag = 1;
  394. lifc->validlt = 0xffffffff;
  395. lifc->preflt = 0xffffffff;
  396. lifc->origint = NOW / 10^3;
  397. }
  398. lifc->next = nil;
  399. for(l = &ifc->lifc; *l; l = &(*l)->next)
  400. ;
  401. *l = lifc;
  402. /* check for point-to-point interface */
  403. if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */
  404. if(ipcmp(mask, IPallbits) == 0)
  405. type |= Rptpt;
  406. /* add local routes */
  407. if(isv4(ip))
  408. v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type);
  409. else
  410. v6addroute(f, tifc, rem, mask, rem, type);
  411. addselfcache(f, ifc, lifc, ip, Runi);
  412. if((type & (Rproxy|Rptpt)) == (Rproxy|Rptpt)){
  413. ipifcregisterproxy(f, ifc, rem);
  414. goto out;
  415. }
  416. if(isv4(ip) || ipcmp(ip, IPnoaddr) == 0) {
  417. /* add subnet directed broadcast address to the self cache */
  418. for(i = 0; i < IPaddrlen; i++)
  419. bcast[i] = (ip[i] & mask[i]) | ~mask[i];
  420. addselfcache(f, ifc, lifc, bcast, Rbcast);
  421. /* add subnet directed network address to the self cache */
  422. for(i = 0; i < IPaddrlen; i++)
  423. bcast[i] = (ip[i] & mask[i]) & mask[i];
  424. addselfcache(f, ifc, lifc, bcast, Rbcast);
  425. /* add network directed broadcast address to the self cache */
  426. memmove(mask, defmask(ip), IPaddrlen);
  427. for(i = 0; i < IPaddrlen; i++)
  428. bcast[i] = (ip[i] & mask[i]) | ~mask[i];
  429. addselfcache(f, ifc, lifc, bcast, Rbcast);
  430. /* add network directed network address to the self cache */
  431. memmove(mask, defmask(ip), IPaddrlen);
  432. for(i = 0; i < IPaddrlen; i++)
  433. bcast[i] = (ip[i] & mask[i]) & mask[i];
  434. addselfcache(f, ifc, lifc, bcast, Rbcast);
  435. addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
  436. }
  437. else {
  438. if(ipcmp(ip, v6loopback) == 0) {
  439. /* add node-local mcast address */
  440. addselfcache(f, ifc, lifc, v6allnodesN, Rmulti);
  441. /* add route for all node multicast */
  442. v6addroute(f, tifc, v6allnodesN, v6allnodesNmask, v6allnodesN, Rmulti);
  443. }
  444. /* add all nodes multicast address */
  445. addselfcache(f, ifc, lifc, v6allnodesL, Rmulti);
  446. /* add route for all nodes multicast */
  447. v6addroute(f, tifc, v6allnodesL, v6allnodesLmask, v6allnodesL, Rmulti);
  448. /* add solicited-node multicast address */
  449. ipv62smcast(bcast, ip);
  450. addselfcache(f, ifc, lifc, bcast, Rmulti);
  451. sendnbrdisc = 1;
  452. }
  453. /* register the address on this network for address resolution */
  454. if(isv4(ip) && ifc->m->areg != nil)
  455. (*ifc->m->areg)(ifc, ip);
  456. out:
  457. wunlock(ifc);
  458. if(tentative && sendnbrdisc)
  459. icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
  460. return nil;
  461. }
  462. /*
  463. * remove a logical interface from an ifc
  464. * always called with ifc wlock'd
  465. */
  466. static char*
  467. ipifcremlifc(Ipifc *ifc, Iplifc *lifc)
  468. {
  469. Iplifc **l;
  470. Fs *f;
  471. f = ifc->conv->p->f;
  472. /*
  473. * find address on this interface and remove from chain.
  474. * for pt to pt we actually specify the remote address as the
  475. * addresss to remove.
  476. */
  477. for(l = &ifc->lifc; *l != nil && *l != lifc; l = &(*l)->next)
  478. ;
  479. if(*l == nil)
  480. return "address not on this interface";
  481. *l = lifc->next;
  482. /* disassociate any addresses */
  483. while(lifc->link)
  484. remselfcache(f, ifc, lifc, lifc->link->self->a);
  485. /* remove the route for this logical interface */
  486. if(isv4(lifc->local))
  487. v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off, 1);
  488. else {
  489. v6delroute(f, lifc->remote, lifc->mask, 1);
  490. if(ipcmp(lifc->local, v6loopback) == 0)
  491. /* remove route for all node multicast */
  492. v6delroute(f, v6allnodesN, v6allnodesNmask, 1);
  493. else if(memcmp(lifc->local, v6linklocal, v6llpreflen) == 0)
  494. /* remove route for all link multicast */
  495. v6delroute(f, v6allnodesL, v6allnodesLmask, 1);
  496. }
  497. free(lifc);
  498. return nil;
  499. }
  500. /*
  501. * remove an address from an interface.
  502. * called with c->car locked
  503. */
  504. char*
  505. ipifcrem(Ipifc *ifc, char **argv, int argc)
  506. {
  507. uchar ip[IPaddrlen];
  508. uchar mask[IPaddrlen];
  509. uchar rem[IPaddrlen];
  510. Iplifc *lifc;
  511. char *rv;
  512. if(argc < 3)
  513. return Ebadarg;
  514. parseip(ip, argv[1]);
  515. parseipmask(mask, argv[2]);
  516. if(argc < 4)
  517. maskip(ip, mask, rem);
  518. else
  519. parseip(rem, argv[3]);
  520. wlock(ifc);
  521. /*
  522. * find address on this interface and remove from chain.
  523. * for pt to pt we actually specify the remote address as the
  524. * addresss to remove.
  525. */
  526. for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) {
  527. if (memcmp(ip, lifc->local, IPaddrlen) == 0
  528. && memcmp(mask, lifc->mask, IPaddrlen) == 0
  529. && memcmp(rem, lifc->remote, IPaddrlen) == 0)
  530. break;
  531. }
  532. rv = ipifcremlifc(ifc, lifc);
  533. wunlock(ifc);
  534. return rv;
  535. }
  536. /*
  537. * distribute routes to active interfaces like the
  538. * TRIP linecards
  539. */
  540. void
  541. ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type)
  542. {
  543. Medium *m;
  544. Conv **cp, **e;
  545. Ipifc *ifc;
  546. e = &f->ipifc->conv[f->ipifc->nc];
  547. for(cp = f->ipifc->conv; cp < e; cp++){
  548. if(*cp != nil) {
  549. ifc = (Ipifc*)(*cp)->ptcl;
  550. m = ifc->m;
  551. if(m == nil)
  552. continue;
  553. if(m->addroute != nil)
  554. m->addroute(ifc, vers, addr, mask, gate, type);
  555. }
  556. }
  557. }
  558. void
  559. ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask)
  560. {
  561. Medium *m;
  562. Conv **cp, **e;
  563. Ipifc *ifc;
  564. e = &f->ipifc->conv[f->ipifc->nc];
  565. for(cp = f->ipifc->conv; cp < e; cp++){
  566. if(*cp != nil) {
  567. ifc = (Ipifc*)(*cp)->ptcl;
  568. m = ifc->m;
  569. if(m == nil)
  570. continue;
  571. if(m->remroute != nil)
  572. m->remroute(ifc, vers, addr, mask);
  573. }
  574. }
  575. }
  576. /*
  577. * associate an address with the interface. This wipes out any previous
  578. * addresses. This is a macro that means, remove all the old interfaces
  579. * and add a new one.
  580. */
  581. static char*
  582. ipifcconnect(Conv* c, char **argv, int argc)
  583. {
  584. char *err;
  585. Ipifc *ifc;
  586. ifc = (Ipifc*)c->ptcl;
  587. if(ifc->m == nil)
  588. return "ipifc not yet bound to device";
  589. if(waserror()){
  590. wunlock(ifc);
  591. nexterror();
  592. }
  593. wlock(ifc);
  594. while(ifc->lifc){
  595. err = ipifcremlifc(ifc, ifc->lifc);
  596. if(err)
  597. error(err);
  598. }
  599. wunlock(ifc);
  600. poperror();
  601. err = ipifcadd(ifc, argv, argc, 0, nil);
  602. if(err)
  603. return err;
  604. Fsconnected(c, nil);
  605. return nil;
  606. }
  607. char*
  608. ipifcsetpar6(Ipifc *ifc, char **argv, int argc)
  609. {
  610. int i, argsleft, vmax = ifc->rp.maxraint, vmin = ifc->rp.minraint;
  611. argsleft = argc - 1;
  612. i = 1;
  613. if(argsleft % 2 != 0)
  614. return Ebadarg;
  615. while (argsleft > 1) {
  616. if(strcmp(argv[i],"recvra")==0)
  617. ifc->recvra6 = (atoi(argv[i+1]) != 0);
  618. else if(strcmp(argv[i],"sendra")==0)
  619. ifc->sendra6 = (atoi(argv[i+1]) != 0);
  620. else if(strcmp(argv[i],"mflag")==0)
  621. ifc->rp.mflag = (atoi(argv[i+1]) != 0);
  622. else if(strcmp(argv[i],"oflag")==0)
  623. ifc->rp.oflag = (atoi(argv[i+1]) != 0);
  624. else if(strcmp(argv[i],"maxraint")==0)
  625. ifc->rp.maxraint = atoi(argv[i+1]);
  626. else if(strcmp(argv[i],"minraint")==0)
  627. ifc->rp.minraint = atoi(argv[i+1]);
  628. else if(strcmp(argv[i],"linkmtu")==0)
  629. ifc->rp.linkmtu = atoi(argv[i+1]);
  630. else if(strcmp(argv[i],"reachtime")==0)
  631. ifc->rp.reachtime = atoi(argv[i+1]);
  632. else if(strcmp(argv[i],"rxmitra")==0)
  633. ifc->rp.rxmitra = atoi(argv[i+1]);
  634. else if(strcmp(argv[i],"ttl")==0)
  635. ifc->rp.ttl = atoi(argv[i+1]);
  636. else if(strcmp(argv[i],"routerlt")==0)
  637. ifc->rp.routerlt = atoi(argv[i+1]);
  638. else
  639. return Ebadarg;
  640. argsleft -= 2;
  641. i += 2;
  642. }
  643. // consistency check
  644. if(ifc->rp.maxraint < ifc->rp.minraint) {
  645. ifc->rp.maxraint = vmax;
  646. ifc->rp.minraint = vmin;
  647. return Ebadarg;
  648. }
  649. return nil;
  650. }
  651. char*
  652. ipifcsendra6(Ipifc *ifc, char **argv, int argc)
  653. {
  654. int i;
  655. i = 0;
  656. if(argc > 1)
  657. i = atoi(argv[1]);
  658. ifc->sendra6 = (i!=0);
  659. return nil;
  660. }
  661. char*
  662. ipifcrecvra6(Ipifc *ifc, char **argv, int argc)
  663. {
  664. int i;
  665. i = 0;
  666. if(argc > 1)
  667. i = atoi(argv[1]);
  668. ifc->recvra6 = (i!=0);
  669. return nil;
  670. }
  671. /*
  672. * non-standard control messages.
  673. * called with c->car locked.
  674. */
  675. static char*
  676. ipifcctl(Conv* c, char**argv, int argc)
  677. {
  678. Ipifc *ifc;
  679. int i;
  680. ifc = (Ipifc*)c->ptcl;
  681. if(strcmp(argv[0], "add") == 0)
  682. return ipifcadd(ifc, argv, argc, 0, nil);
  683. else if(strcmp(argv[0], "try") == 0)
  684. return ipifcadd(ifc, argv, argc, 1, nil);
  685. else if(strcmp(argv[0], "remove") == 0)
  686. return ipifcrem(ifc, argv, argc);
  687. else if(strcmp(argv[0], "unbind") == 0)
  688. return ipifcunbind(ifc);
  689. else if(strcmp(argv[0], "joinmulti") == 0)
  690. return ipifcjoinmulti(ifc, argv, argc);
  691. else if(strcmp(argv[0], "leavemulti") == 0)
  692. return ipifcleavemulti(ifc, argv, argc);
  693. else if(strcmp(argv[0], "mtu") == 0)
  694. return ipifcsetmtu(ifc, argv, argc);
  695. else if(strcmp(argv[0], "reassemble") == 0){
  696. ifc->reassemble = 1;
  697. return nil;
  698. }
  699. else if(strcmp(argv[0], "iprouting") == 0){
  700. i = 1;
  701. if(argc > 1)
  702. i = atoi(argv[1]);
  703. iprouting(c->p->f, i);
  704. return nil;
  705. }
  706. else if(strcmp(argv[0], "addpref6") == 0)
  707. return ipifcaddpref6(ifc, argv, argc);
  708. else if(strcmp(argv[0], "setpar6") == 0)
  709. return ipifcsetpar6(ifc, argv, argc);
  710. else if(strcmp(argv[0], "sendra6") == 0)
  711. return ipifcsendra6(ifc, argv, argc);
  712. else if(strcmp(argv[0], "recvra6") == 0)
  713. return ipifcrecvra6(ifc, argv, argc);
  714. return "unsupported ctl";
  715. }
  716. int
  717. ipifcstats(Proto *ipifc, char *buf, int len)
  718. {
  719. return ipstats(ipifc->f, buf, len);
  720. }
  721. void
  722. ipifcinit(Fs *f)
  723. {
  724. Proto *ipifc;
  725. ipifc = smalloc(sizeof(Proto));
  726. ipifc->name = "ipifc";
  727. ipifc->connect = ipifcconnect;
  728. ipifc->announce = nil;
  729. ipifc->bind = ipifcbind;
  730. ipifc->state = ipifcstate;
  731. ipifc->create = ipifccreate;
  732. ipifc->close = ipifcclose;
  733. ipifc->rcv = nil;
  734. ipifc->ctl = ipifcctl;
  735. ipifc->advise = nil;
  736. ipifc->stats = ipifcstats;
  737. ipifc->inuse = ipifcinuse;
  738. ipifc->local = ipifclocal;
  739. ipifc->ipproto = -1;
  740. ipifc->nc = Maxmedia;
  741. ipifc->ptclsize = sizeof(Ipifc);
  742. f->ipifc = ipifc; /* hack for ipifcremroute, findipifc, ... */
  743. f->self = smalloc(sizeof(Ipselftab)); /* hack for ipforme */
  744. Fsproto(f, ipifc);
  745. }
  746. /*
  747. * add to self routing cache
  748. * called with c->car locked
  749. */
  750. static void
  751. addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type)
  752. {
  753. Ipself *p;
  754. Iplink *lp;
  755. int h;
  756. qlock(f->self);
  757. /* see if the address already exists */
  758. h = hashipa(a);
  759. for(p = f->self->hash[h]; p; p = p->next)
  760. if(memcmp(a, p->a, IPaddrlen) == 0)
  761. break;
  762. /* allocate a local address and add to hash chain */
  763. if(p == nil){
  764. p = smalloc(sizeof(*p));
  765. ipmove(p->a, a);
  766. p->type = type;
  767. p->next = f->self->hash[h];
  768. f->self->hash[h] = p;
  769. /* if the null address, accept all packets */
  770. if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
  771. f->self->acceptall = 1;
  772. }
  773. /* look for a link for this lifc */
  774. for(lp = p->link; lp; lp = lp->selflink)
  775. if(lp->lifc == lifc)
  776. break;
  777. /* allocate a lifc-to-local link and link to both */
  778. if(lp == nil){
  779. lp = smalloc(sizeof(*lp));
  780. lp->ref = 1;
  781. lp->lifc = lifc;
  782. lp->self = p;
  783. lp->selflink = p->link;
  784. p->link = lp;
  785. lp->lifclink = lifc->link;
  786. lifc->link = lp;
  787. /* add to routing table */
  788. if(isv4(a))
  789. v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type);
  790. else
  791. v6addroute(f, tifc, a, IPallbits, a, type);
  792. if((type & Rmulti) && ifc->m->addmulti != nil)
  793. (*ifc->m->addmulti)(ifc, a, lifc->local);
  794. } else {
  795. lp->ref++;
  796. }
  797. qunlock(f->self);
  798. }
  799. /*
  800. * These structures are unlinked from their chains while
  801. * other threads may be using them. To avoid excessive locking,
  802. * just put them aside for a while before freeing them.
  803. * called with f->self locked
  804. */
  805. static Iplink *freeiplink;
  806. static Ipself *freeipself;
  807. static void
  808. iplinkfree(Iplink *p)
  809. {
  810. Iplink **l, *np;
  811. ulong now = NOW;
  812. l = &freeiplink;
  813. for(np = *l; np; np = *l){
  814. if(np->expire > now){
  815. *l = np->next;
  816. free(np);
  817. continue;
  818. }
  819. l = &np->next;
  820. }
  821. p->expire = now + 5000; /* give other threads 5 secs to get out */
  822. p->next = nil;
  823. *l = p;
  824. }
  825. static void
  826. ipselffree(Ipself *p)
  827. {
  828. Ipself **l, *np;
  829. ulong now = NOW;
  830. l = &freeipself;
  831. for(np = *l; np; np = *l){
  832. if(np->expire > now){
  833. *l = np->next;
  834. free(np);
  835. continue;
  836. }
  837. l = &np->next;
  838. }
  839. p->expire = now + 5000; /* give other threads 5 secs to get out */
  840. p->next = nil;
  841. *l = p;
  842. }
  843. /*
  844. * Decrement reference for this address on this link.
  845. * Unlink from selftab if this is the last ref.
  846. * called with c->car locked
  847. */
  848. static void
  849. remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a)
  850. {
  851. Ipself *p, **l;
  852. Iplink *link, **l_self, **l_lifc;
  853. qlock(f->self);
  854. /* find the unique selftab entry */
  855. l = &f->self->hash[hashipa(a)];
  856. for(p = *l; p; p = *l){
  857. if(ipcmp(p->a, a) == 0)
  858. break;
  859. l = &p->next;
  860. }
  861. if(p == nil)
  862. goto out;
  863. /*
  864. * walk down links from an ifc looking for one
  865. * that matches the selftab entry
  866. */
  867. l_lifc = &lifc->link;
  868. for(link = *l_lifc; link; link = *l_lifc){
  869. if(link->self == p)
  870. break;
  871. l_lifc = &link->lifclink;
  872. }
  873. if(link == nil)
  874. goto out;
  875. /*
  876. * walk down the links from the selftab looking for
  877. * the one we just found
  878. */
  879. l_self = &p->link;
  880. for(link = *l_self; link; link = *l_self){
  881. if(link == *(l_lifc))
  882. break;
  883. l_self = &link->selflink;
  884. }
  885. if(link == nil)
  886. panic("remselfcache");
  887. if(--(link->ref) != 0)
  888. goto out;
  889. if((p->type & Rmulti) && ifc->m->remmulti != nil)
  890. (*ifc->m->remmulti)(ifc, a, lifc->local);
  891. /* ref == 0, remove from both chains and free the link */
  892. *l_lifc = link->lifclink;
  893. *l_self = link->selflink;
  894. iplinkfree(link);
  895. if(p->link != nil)
  896. goto out;
  897. /* remove from routing table */
  898. if(isv4(a))
  899. v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1);
  900. else
  901. v6delroute(f, a, IPallbits, 1);
  902. /* no more links, remove from hash and free */
  903. *l = p->next;
  904. ipselffree(p);
  905. /* if IPnoaddr, forget */
  906. if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
  907. f->self->acceptall = 0;
  908. out:
  909. qunlock(f->self);
  910. }
  911. static char *stformat = "%-44.44I %2.2d %4.4s\n";
  912. enum
  913. {
  914. Nstformat= 41,
  915. };
  916. long
  917. ipselftabread(Fs *f, char *cp, ulong offset, int n)
  918. {
  919. int i, m, nifc, off;
  920. Ipself *p;
  921. Iplink *link;
  922. char state[8];
  923. m = 0;
  924. off = offset;
  925. qlock(f->self);
  926. for(i = 0; i < NHASH && m < n; i++){
  927. for(p = f->self->hash[i]; p != nil && m < n; p = p->next){
  928. nifc = 0;
  929. for(link = p->link; link; link = link->selflink)
  930. nifc++;
  931. routetype(p->type, state);
  932. m += snprint(cp + m, n - m, stformat, p->a, nifc, state);
  933. if(off > 0){
  934. off -= m;
  935. m = 0;
  936. }
  937. }
  938. }
  939. qunlock(f->self);
  940. return m;
  941. }
  942. int
  943. iptentative(Fs *f, uchar *addr)
  944. {
  945. Ipself *p;
  946. p = f->self->hash[hashipa(addr)];
  947. for(; p; p = p->next){
  948. if(ipcmp(addr, p->a) == 0) {
  949. return p->link->lifc->tentative;
  950. }
  951. }
  952. return 0;
  953. }
  954. /*
  955. * returns
  956. * 0 - no match
  957. * Runi
  958. * Rbcast
  959. * Rmcast
  960. */
  961. int
  962. ipforme(Fs *f, uchar *addr)
  963. {
  964. Ipself *p;
  965. p = f->self->hash[hashipa(addr)];
  966. for(; p; p = p->next){
  967. if(ipcmp(addr, p->a) == 0)
  968. return p->type;
  969. }
  970. /* hack to say accept anything */
  971. if(f->self->acceptall)
  972. return Runi;
  973. return 0;
  974. }
  975. /*
  976. * find the ifc on same net as the remote system. If none,
  977. * return nil.
  978. */
  979. Ipifc*
  980. findipifc(Fs *f, uchar *remote, int type)
  981. {
  982. Ipifc *ifc, *x;
  983. Iplifc *lifc;
  984. Conv **cp, **e;
  985. uchar gnet[IPaddrlen];
  986. uchar xmask[IPaddrlen];
  987. x = nil; memset(xmask, 0, IPaddrlen);
  988. /* find most specific match */
  989. e = &f->ipifc->conv[f->ipifc->nc];
  990. for(cp = f->ipifc->conv; cp < e; cp++){
  991. if(*cp == 0)
  992. continue;
  993. ifc = (Ipifc*)(*cp)->ptcl;
  994. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  995. maskip(remote, lifc->mask, gnet);
  996. if(ipcmp(gnet, lifc->net) == 0){
  997. if(x == nil || ipcmp(lifc->mask, xmask) > 0){
  998. x = ifc;
  999. ipmove(xmask, lifc->mask);
  1000. }
  1001. }
  1002. }
  1003. }
  1004. if(x != nil)
  1005. return x;
  1006. /* for now for broadcast and multicast, just use first interface */
  1007. if(type & (Rbcast|Rmulti)){
  1008. for(cp = f->ipifc->conv; cp < e; cp++){
  1009. if(*cp == 0)
  1010. continue;
  1011. ifc = (Ipifc*)(*cp)->ptcl;
  1012. if(ifc->lifc != nil)
  1013. return ifc;
  1014. }
  1015. }
  1016. return nil;
  1017. }
  1018. enum {
  1019. unknownv6,
  1020. multicastv6,
  1021. unspecifiedv6,
  1022. linklocalv6,
  1023. sitelocalv6,
  1024. globalv6,
  1025. };
  1026. int
  1027. v6addrtype(uchar *addr)
  1028. {
  1029. if(isv6global(addr))
  1030. return globalv6;
  1031. if(islinklocal(addr))
  1032. return linklocalv6;
  1033. if(isv6mcast(addr))
  1034. return multicastv6;
  1035. if(issitelocal(addr))
  1036. return sitelocalv6;
  1037. return unknownv6;
  1038. }
  1039. #define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))
  1040. static void
  1041. findprimaryipv6(Fs *f, uchar *local)
  1042. {
  1043. Conv **cp, **e;
  1044. Ipifc *ifc;
  1045. Iplifc *lifc;
  1046. int atype, atypel;
  1047. ipmove(local, v6Unspecified);
  1048. atype = unspecifiedv6;
  1049. /* find "best" (global > sitelocal > link local > unspecified)
  1050. * local address; address must be current */
  1051. e = &f->ipifc->conv[f->ipifc->nc];
  1052. for(cp = f->ipifc->conv; cp < e; cp++){
  1053. if(*cp == 0)
  1054. continue;
  1055. ifc = (Ipifc*)(*cp)->ptcl;
  1056. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1057. atypel = v6addrtype(lifc->local);
  1058. if(atypel > atype)
  1059. if(v6addrcurr(lifc)) {
  1060. ipmove(local, lifc->local);
  1061. atype = atypel;
  1062. if(atype == globalv6)
  1063. return;
  1064. }
  1065. }
  1066. }
  1067. }
  1068. /*
  1069. * returns first ip address configured
  1070. */
  1071. static void
  1072. findprimaryipv4(Fs *f, uchar *local)
  1073. {
  1074. Conv **cp, **e;
  1075. Ipifc *ifc;
  1076. Iplifc *lifc;
  1077. /* find first ifc local address */
  1078. e = &f->ipifc->conv[f->ipifc->nc];
  1079. for(cp = f->ipifc->conv; cp < e; cp++){
  1080. if(*cp == 0)
  1081. continue;
  1082. ifc = (Ipifc*)(*cp)->ptcl;
  1083. if((lifc = ifc->lifc) != nil){
  1084. ipmove(local, lifc->local);
  1085. return;
  1086. }
  1087. }
  1088. }
  1089. /*
  1090. * find the local address 'closest' to the remote system, copy it to
  1091. * local and return the ifc for that address
  1092. */
  1093. void
  1094. findlocalip(Fs *f, uchar *local, uchar *remote)
  1095. {
  1096. Ipifc *ifc;
  1097. Iplifc *lifc;
  1098. Route *r;
  1099. uchar gate[IPaddrlen];
  1100. uchar gnet[IPaddrlen];
  1101. int version;
  1102. int atype = unspecifiedv6, atypel = unknownv6;
  1103. USED(atype);
  1104. USED(atypel);
  1105. qlock(f->ipifc);
  1106. r = v6lookup(f, remote, nil);
  1107. version = (memcmp(remote, v4prefix, IPv4off) == 0) ? V4 : V6;
  1108. if(r != nil){
  1109. ifc = r->ifc;
  1110. if(r->type & Rv4)
  1111. v4tov6(gate, r->v4.gate);
  1112. else {
  1113. ipmove(gate, r->v6.gate);
  1114. ipmove(local, v6Unspecified);
  1115. }
  1116. /* find ifc address closest to the gateway to use */
  1117. switch(version) {
  1118. case V4:
  1119. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1120. maskip(gate, lifc->mask, gnet);
  1121. if(ipcmp(gnet, lifc->net) == 0){
  1122. ipmove(local, lifc->local);
  1123. goto out;
  1124. }
  1125. }
  1126. break;
  1127. case V6:
  1128. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1129. atypel = v6addrtype(lifc->local);
  1130. maskip(gate, lifc->mask, gnet);
  1131. if(ipcmp(gnet, lifc->net) == 0)
  1132. if(atypel > atype)
  1133. if(v6addrcurr(lifc)) {
  1134. ipmove(local, lifc->local);
  1135. atype = atypel;
  1136. if(atype == globalv6)
  1137. break;
  1138. }
  1139. }
  1140. if(atype > unspecifiedv6)
  1141. goto out;
  1142. break;
  1143. default:
  1144. panic("findlocalip: version %d", version);
  1145. }
  1146. }
  1147. switch(version){
  1148. case V4:
  1149. findprimaryipv4(f, local);
  1150. break;
  1151. case V6:
  1152. findprimaryipv6(f, local);
  1153. break;
  1154. default:
  1155. panic("findlocalip2: version %d", version);
  1156. }
  1157. out:
  1158. qunlock(f->ipifc);
  1159. }
  1160. /*
  1161. * return first v4 address associated with an interface
  1162. */
  1163. int
  1164. ipv4local(Ipifc *ifc, uchar *addr)
  1165. {
  1166. Iplifc *lifc;
  1167. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1168. if(isv4(lifc->local)){
  1169. memmove(addr, lifc->local+IPv4off, IPv4addrlen);
  1170. return 1;
  1171. }
  1172. }
  1173. return 0;
  1174. }
  1175. /*
  1176. * return first v6 address associated with an interface
  1177. */
  1178. int
  1179. ipv6local(Ipifc *ifc, uchar *addr)
  1180. {
  1181. Iplifc *lifc;
  1182. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1183. if(!isv4(lifc->local) && !(lifc->tentative)){
  1184. ipmove(addr, lifc->local);
  1185. return 1;
  1186. }
  1187. }
  1188. return 0;
  1189. }
  1190. int
  1191. ipv6anylocal(Ipifc *ifc, uchar *addr)
  1192. {
  1193. Iplifc *lifc;
  1194. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1195. if(!isv4(lifc->local)){
  1196. ipmove(addr, lifc->local);
  1197. return SRC_UNI;
  1198. }
  1199. }
  1200. return SRC_UNSPEC;
  1201. }
  1202. /*
  1203. * see if this address is bound to the interface
  1204. */
  1205. Iplifc*
  1206. iplocalonifc(Ipifc *ifc, uchar *ip)
  1207. {
  1208. Iplifc *lifc;
  1209. for(lifc = ifc->lifc; lifc; lifc = lifc->next)
  1210. if(ipcmp(ip, lifc->local) == 0)
  1211. return lifc;
  1212. return nil;
  1213. }
  1214. /*
  1215. * See if we're proxying for this address on this interface
  1216. */
  1217. int
  1218. ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip)
  1219. {
  1220. Route *r;
  1221. uchar net[IPaddrlen];
  1222. Iplifc *lifc;
  1223. /* see if this is a direct connected pt to pt address */
  1224. r = v6lookup(f, ip, nil);
  1225. if(r == nil)
  1226. return 0;
  1227. if((r->type & (Rifc|Rproxy)) != (Rifc|Rproxy))
  1228. return 0;
  1229. /* see if this is on the right interface */
  1230. for(lifc = ifc->lifc; lifc; lifc = lifc->next){
  1231. maskip(ip, lifc->mask, net);
  1232. if(ipcmp(net, lifc->remote) == 0)
  1233. return 1;
  1234. }
  1235. return 0;
  1236. }
  1237. /*
  1238. * return multicast version if any
  1239. */
  1240. int
  1241. ipismulticast(uchar *ip)
  1242. {
  1243. if(isv4(ip)){
  1244. if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
  1245. return V4;
  1246. } else {
  1247. if(ip[0] == 0xff)
  1248. return V6;
  1249. }
  1250. return 0;
  1251. }
  1252. int
  1253. ipisbm(uchar *ip)
  1254. {
  1255. if(isv4(ip)){
  1256. if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
  1257. return V4;
  1258. if(ipcmp(ip, IPv4bcast) == 0)
  1259. return V4;
  1260. } else {
  1261. if(ip[0] == 0xff)
  1262. return V6;
  1263. }
  1264. return 0;
  1265. }
  1266. /*
  1267. * add a multicast address to an interface, called with c->car locked
  1268. */
  1269. void
  1270. ipifcaddmulti(Conv *c, uchar *ma, uchar *ia)
  1271. {
  1272. Ipifc *ifc;
  1273. Iplifc *lifc;
  1274. Conv **p;
  1275. Ipmulti *multi, **l;
  1276. Fs *f;
  1277. f = c->p->f;
  1278. for(l = &c->multi; *l; l = &(*l)->next)
  1279. if(ipcmp(ma, (*l)->ma) == 0)
  1280. if(ipcmp(ia, (*l)->ia) == 0)
  1281. return; /* it's already there */
  1282. multi = *l = smalloc(sizeof(*multi));
  1283. ipmove(multi->ma, ma);
  1284. ipmove(multi->ia, ia);
  1285. multi->next = nil;
  1286. for(p = f->ipifc->conv; *p; p++){
  1287. if((*p)->inuse == 0)
  1288. continue;
  1289. ifc = (Ipifc*)(*p)->ptcl;
  1290. if(waserror()){
  1291. wunlock(ifc);
  1292. nexterror();
  1293. }
  1294. wlock(ifc);
  1295. for(lifc = ifc->lifc; lifc; lifc = lifc->next)
  1296. if(ipcmp(ia, lifc->local) == 0)
  1297. addselfcache(f, ifc, lifc, ma, Rmulti);
  1298. wunlock(ifc);
  1299. poperror();
  1300. }
  1301. }
  1302. /*
  1303. * remove a multicast address from an interface, called with c->car locked
  1304. */
  1305. void
  1306. ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
  1307. {
  1308. Ipmulti *multi, **l;
  1309. Iplifc *lifc;
  1310. Conv **p;
  1311. Ipifc *ifc;
  1312. Fs *f;
  1313. f = c->p->f;
  1314. for(l = &c->multi; *l; l = &(*l)->next)
  1315. if(ipcmp(ma, (*l)->ma) == 0)
  1316. if(ipcmp(ia, (*l)->ia) == 0)
  1317. break;
  1318. multi = *l;
  1319. if(multi == nil)
  1320. return; /* we don't have it open */
  1321. *l = multi->next;
  1322. for(p = f->ipifc->conv; *p; p++){
  1323. if((*p)->inuse == 0)
  1324. continue;
  1325. ifc = (Ipifc*)(*p)->ptcl;
  1326. if(waserror()){
  1327. wunlock(ifc);
  1328. nexterror();
  1329. }
  1330. wlock(ifc);
  1331. for(lifc = ifc->lifc; lifc; lifc = lifc->next)
  1332. if(ipcmp(ia, lifc->local) == 0)
  1333. remselfcache(f, ifc, lifc, ma);
  1334. wunlock(ifc);
  1335. poperror();
  1336. }
  1337. free(multi);
  1338. }
  1339. /*
  1340. * make lifc's join and leave multicast groups
  1341. */
  1342. static char*
  1343. ipifcjoinmulti(Ipifc *ifc, char **argv, int argc)
  1344. {
  1345. USED(ifc, argv, argc);
  1346. return nil;
  1347. }
  1348. static char*
  1349. ipifcleavemulti(Ipifc *ifc, char **argv, int argc)
  1350. {
  1351. USED(ifc, argv, argc);
  1352. return nil;
  1353. }
  1354. static void
  1355. ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip)
  1356. {
  1357. Conv **cp, **e;
  1358. Ipifc *nifc;
  1359. Iplifc *lifc;
  1360. Medium *m;
  1361. uchar net[IPaddrlen];
  1362. /* register the address on any network that will proxy for us */
  1363. e = &f->ipifc->conv[f->ipifc->nc];
  1364. if(!isv4(ip)) { // V6
  1365. for(cp = f->ipifc->conv; cp < e; cp++){
  1366. if(*cp == nil)
  1367. continue;
  1368. nifc = (Ipifc*)(*cp)->ptcl;
  1369. if(nifc == ifc)
  1370. continue;
  1371. rlock(nifc);
  1372. m = nifc->m;
  1373. if(m == nil || m->addmulti == nil) {
  1374. runlock(nifc);
  1375. continue;
  1376. }
  1377. for(lifc = nifc->lifc; lifc; lifc = lifc->next){
  1378. maskip(ip, lifc->mask, net);
  1379. if(ipcmp(net, lifc->remote) == 0) { /* add solicited-node multicast address */
  1380. ipv62smcast(net, ip);
  1381. addselfcache(f, nifc, lifc, net, Rmulti);
  1382. arpenter(f, V6, ip, nifc->mac, 6, 0);
  1383. //(*m->addmulti)(nifc, net, ip);
  1384. break;
  1385. }
  1386. }
  1387. runlock(nifc);
  1388. }
  1389. return;
  1390. }
  1391. else { // V4
  1392. for(cp = f->ipifc->conv; cp < e; cp++){
  1393. if(*cp == nil)
  1394. continue;
  1395. nifc = (Ipifc*)(*cp)->ptcl;
  1396. if(nifc == ifc)
  1397. continue;
  1398. rlock(nifc);
  1399. m = nifc->m;
  1400. if(m == nil || m->areg == nil){
  1401. runlock(nifc);
  1402. continue;
  1403. }
  1404. for(lifc = nifc->lifc; lifc; lifc = lifc->next){
  1405. maskip(ip, lifc->mask, net);
  1406. if(ipcmp(net, lifc->remote) == 0){
  1407. (*m->areg)(nifc, ip);
  1408. break;
  1409. }
  1410. }
  1411. runlock(nifc);
  1412. }
  1413. }
  1414. }
  1415. // added for new v6 mesg types
  1416. static void
  1417. adddefroute6(Fs *f, uchar *gate, int force)
  1418. {
  1419. Route *r;
  1420. r = v6lookup(f, v6Unspecified, nil);
  1421. if(r!=nil)
  1422. if(!(force) && (strcmp(r->tag,"ra")!=0)) // route entries generated
  1423. return; // by all other means take
  1424. // precedence over router annc
  1425. v6delroute(f, v6Unspecified, v6Unspecified, 1);
  1426. v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
  1427. }
  1428. enum
  1429. {
  1430. Ngates = 3,
  1431. };
  1432. char*
  1433. ipifcaddpref6(Ipifc *ifc, char**argv, int argc)
  1434. {
  1435. uchar onlink = 1;
  1436. uchar autoflag = 1;
  1437. long validlt = 0xffffffff;
  1438. long preflt = 0xffffffff;
  1439. long origint = NOW / 10^3;
  1440. uchar prefix[IPaddrlen];
  1441. int plen = 64;
  1442. Iplifc *lifc;
  1443. char addr[40], preflen[6];
  1444. char *params[3];
  1445. switch(argc) {
  1446. case 7:
  1447. preflt = atoi(argv[6]);
  1448. /* fall through */
  1449. case 6:
  1450. validlt = atoi(argv[5]);
  1451. /* fall through */
  1452. case 5:
  1453. autoflag = atoi(argv[4]);
  1454. /* fall through */
  1455. case 4:
  1456. onlink = atoi(argv[3]);
  1457. /* fall through */
  1458. case 3:
  1459. plen = atoi(argv[2]);
  1460. case 2:
  1461. break;
  1462. default:
  1463. return Ebadarg;
  1464. }
  1465. if((parseip(prefix, argv[1])!=6) ||
  1466. (validlt < preflt) ||
  1467. (plen < 0) || (plen > 64) ||
  1468. (islinklocal(prefix))
  1469. )
  1470. return Ebadarg;
  1471. lifc = smalloc(sizeof(Iplifc));
  1472. lifc->onlink = (onlink!=0);
  1473. lifc->autoflag = (autoflag!=0);
  1474. lifc->validlt = validlt;
  1475. lifc->preflt = preflt;
  1476. lifc->origint = origint;
  1477. if(ifc->m->pref2addr!=nil)
  1478. ifc->m->pref2addr(prefix, ifc->mac);
  1479. else
  1480. return Ebadarg;
  1481. sprint(addr, "%I", prefix);
  1482. sprint(preflen, "/%d", plen);
  1483. params[0] = "add";
  1484. params[1] = addr;
  1485. params[2] = preflen;
  1486. return ipifcadd(ifc, params, 3, 0, lifc);
  1487. }