ipifc.c 35 KB

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