ipifc.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685
  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 ql;
  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. Proc *up = externup();
  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->rwl);
  110. if(ifc->medium != nil){
  111. wunlock(&ifc->rwl);
  112. return "interface already bound";
  113. }
  114. if(waserror()){
  115. wunlock(&ifc->rwl);
  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->rwl);
  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. Proc *up = externup();
  159. char *err;
  160. if(waserror()){
  161. wunlock(&ifc->rwl);
  162. nexterror();
  163. }
  164. wlock(&ifc->rwl);
  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->rwl);
  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 %lu pktout %lu errin %lu errout %lu\n";
  197. char slineformat[] = " %-40I %-10M %-40I %-12lu %-12lu\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->rwl);
  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->rwl);
  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->rwl);
  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->rwl);
  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. Proc *up = externup();
  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->rwl)){
  261. freeb(bp);
  262. return;
  263. }
  264. if(waserror()){
  265. runlock(&ifc->rwl);
  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->rwl);
  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->rwl);
  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->rwl);
  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->rwl);
  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->rwl);
  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. Proc *up = externup();
  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->rwl);
  599. nexterror();
  600. }
  601. wlock(&ifc->rwl);
  602. while(ifc->lifc){
  603. err = ipifcremlifc(ifc, ifc->lifc);
  604. if(err)
  605. error(err);
  606. }
  607. wunlock(&ifc->rwl);
  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->ql);
  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->ql);
  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->ql);
  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->ql);
  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->ql);
  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->ql);
  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->ql);
  1087. r = v6lookup(f, remote, nil);
  1088. version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6;
  1089. if(r != nil){
  1090. ifc = r->RouteTree.ifc;
  1091. if(r->RouteTree.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->ql);
  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->RouteTree.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. Proc *up = externup();
  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->rwl);
  1279. nexterror();
  1280. }
  1281. wlock(&ifc->rwl);
  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->rwl);
  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. Proc *up = externup();
  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->rwl);
  1315. nexterror();
  1316. }
  1317. wlock(&ifc->rwl);
  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->rwl);
  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->rwl);
  1356. m = nifc->medium;
  1357. if(m == nil || m->addmulti == nil) {
  1358. runlock(&nifc->rwl);
  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->rwl);
  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->rwl);
  1380. m = nifc->medium;
  1381. if(m == nil || m->areg == nil){
  1382. runlock(&nifc->rwl);
  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->rwl);
  1393. }
  1394. }
  1395. }
  1396. #if 0
  1397. /* added for new v6 mesg types */
  1398. static void
  1399. adddefroute6(Fs *f, uint8_t *gate, int force)
  1400. {
  1401. Route *r;
  1402. r = v6lookup(f, v6Unspecified, nil);
  1403. /*
  1404. * route entries generated by all other means take precedence
  1405. * over router announcements.
  1406. */
  1407. if (r && !force && strcmp(r->RouteTree.tag, "ra") != 0)
  1408. return;
  1409. v6delroute(f, v6Unspecified, v6Unspecified, 1);
  1410. v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
  1411. }
  1412. #endif
  1413. enum {
  1414. Ngates = 3,
  1415. };
  1416. char*
  1417. ipifcadd6(Ipifc *ifc, char**argv, int argc)
  1418. {
  1419. int plen = 64;
  1420. int32_t origint = NOW / 1000, preflt = ~0L, validlt = ~0L;
  1421. char addr[Maxv6repr], preflen[6];
  1422. char *params[3];
  1423. uint8_t autoflag = 1, onlink = 1;
  1424. uint8_t prefix[IPaddrlen];
  1425. Iplifc *lifc;
  1426. switch(argc) {
  1427. case 7:
  1428. preflt = atoi(argv[6]);
  1429. /* fall through */
  1430. case 6:
  1431. validlt = atoi(argv[5]);
  1432. /* fall through */
  1433. case 5:
  1434. autoflag = atoi(argv[4]);
  1435. /* fall through */
  1436. case 4:
  1437. onlink = atoi(argv[3]);
  1438. /* fall through */
  1439. case 3:
  1440. plen = atoi(argv[2]);
  1441. /* fall through */
  1442. case 2:
  1443. break;
  1444. default:
  1445. return Ebadarg;
  1446. }
  1447. if (parseip(prefix, argv[1]) != 6)
  1448. return "bad ipv6 address";
  1449. if (validlt < preflt)
  1450. return "valid ipv6 lifetime less than preferred lifetime";
  1451. if (plen < 0)
  1452. return "negative ipv6 prefix length";
  1453. /* i think that this length limit is bogus - geoff */
  1454. // if (plen > 64)
  1455. // return "ipv6 prefix length greater than 64;
  1456. if (islinklocal(prefix))
  1457. return "ipv6 prefix is link-local";
  1458. lifc = smalloc(sizeof(Iplifc));
  1459. lifc->onlink = (onlink != 0);
  1460. lifc->autoflag = (autoflag != 0);
  1461. lifc->validlt = validlt;
  1462. lifc->preflt = preflt;
  1463. lifc->origint = origint;
  1464. /* issue "add" ctl msg for v6 link-local addr and prefix len */
  1465. if(!ifc->medium->pref2addr)
  1466. return "no pref2addr on interface";
  1467. ifc->medium->pref2addr(prefix, ifc->mac); /* mac → v6 link-local addr */
  1468. snprint(addr, sizeof addr, "%I", prefix);
  1469. snprint(preflen, sizeof preflen, "/%d", plen);
  1470. params[0] = "add";
  1471. params[1] = addr;
  1472. params[2] = preflen;
  1473. return ipifcadd(ifc, params, 3, 0, lifc);
  1474. }