ipifc.c 33 KB

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