ipv6.c 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  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. /*
  10. * ipconfig for IPv6
  11. * RS means Router Solicitation
  12. * RA means Router Advertisement
  13. */
  14. #include <u.h>
  15. #include <libc.h>
  16. #include <bio.h>
  17. #include <ip.h>
  18. #include "ipconfig.h"
  19. #include "../icmp.h"
  20. //#pragma varargck argpos ralog 1
  21. #define RALOG "v6routeradv"
  22. #define NetS(x) (((unsigned char*)x)[0]<< 8 | ((unsigned char*)x)[1])
  23. #define NetL(x) (((unsigned char*)x)[0]<<24 | ((unsigned char*)x)[1]<<16 | \
  24. ((unsigned char*)x)[2]<< 8 | ((unsigned char*)x)[3])
  25. enum {
  26. ICMP6LEN= 4,
  27. };
  28. typedef struct Hdr Hdr;
  29. struct Hdr /* ICMP v4 & v6 header */
  30. {
  31. uint8_t type;
  32. uint8_t code;
  33. uint8_t cksum[2]; /* Checksum */
  34. uint8_t data[];
  35. };
  36. char *icmpmsg6[Maxtype6+1] =
  37. {
  38. [EchoReply] = "EchoReply",
  39. [UnreachableV6] = "UnreachableV6",
  40. [PacketTooBigV6] = "PacketTooBigV6",
  41. [TimeExceedV6] = "TimeExceedV6",
  42. [Redirect] = "Redirect",
  43. [EchoRequest] = "EchoRequest",
  44. [TimeExceed] = "TimeExceed",
  45. [InParmProblem] = "InParmProblem",
  46. [Timestamp] = "Timestamp",
  47. [TimestampReply] = "TimestampReply",
  48. [InfoRequest] = "InfoRequest",
  49. [InfoReply] = "InfoReply",
  50. [AddrMaskRequest] = "AddrMaskRequest",
  51. [AddrMaskReply] = "AddrMaskReply",
  52. [EchoRequestV6] = "EchoRequestV6",
  53. [EchoReplyV6] = "EchoReplyV6",
  54. [RouterSolicit] = "RouterSolicit",
  55. [RouterAdvert] = "RouterAdvert",
  56. [NbrSolicit] = "NbrSolicit",
  57. [NbrAdvert] = "NbrAdvert",
  58. [RedirectV6] = "RedirectV6",
  59. };
  60. static char *icmp6opts[] =
  61. {
  62. [0] = "unknown option",
  63. [V6nd_srclladdr] = "srcll_addr",
  64. [V6nd_targlladdr] = "targll_addr",
  65. [V6nd_pfxinfo] = "prefix",
  66. [V6nd_redirhdr] = "redirect",
  67. [V6nd_mtu] = "mtu",
  68. [V6nd_home] = "home",
  69. [V6nd_srcaddrs] = "src_addrs",
  70. [V6nd_ip] = "ip",
  71. [V6nd_rdns] = "rdns",
  72. [V6nd_9fs] = "9fs",
  73. [V6nd_9auth] = "9auth",
  74. };
  75. uint8_t v6allroutersL[IPaddrlen] = {
  76. 0xff, 0x02, 0, 0,
  77. 0, 0, 0, 0,
  78. 0, 0, 0, 0,
  79. 0, 0, 0, 0x02
  80. };
  81. uint8_t v6allnodesL[IPaddrlen] = {
  82. 0xff, 0x02, 0, 0,
  83. 0, 0, 0, 0,
  84. 0, 0, 0, 0,
  85. 0, 0, 0, 0x01
  86. };
  87. uint8_t v6Unspecified[IPaddrlen] = {
  88. 0, 0, 0, 0,
  89. 0, 0, 0, 0,
  90. 0, 0, 0, 0,
  91. 0, 0, 0, 0
  92. };
  93. uint8_t v6loopback[IPaddrlen] = {
  94. 0, 0, 0, 0,
  95. 0, 0, 0, 0,
  96. 0, 0, 0, 0,
  97. 0, 0, 0, 1
  98. };
  99. uint8_t v6glunicast[IPaddrlen] = {
  100. 0x08, 0, 0, 0,
  101. 0, 0, 0, 0,
  102. 0, 0, 0, 0,
  103. 0, 0, 0, 0
  104. };
  105. uint8_t v6linklocal[IPaddrlen] = {
  106. 0xfe, 0x80, 0, 0,
  107. 0, 0, 0, 0,
  108. 0, 0, 0, 0,
  109. 0, 0, 0, 0
  110. };
  111. uint8_t v6solpfx[IPaddrlen] = {
  112. 0xff, 0x02, 0, 0,
  113. 0, 0, 0, 0,
  114. 0, 0, 0, 1,
  115. /* last 3 bytes filled with low-order bytes of addr being solicited */
  116. 0xff, 0, 0, 0,
  117. };
  118. uint8_t v6defmask[IPaddrlen] = {
  119. 0xff, 0xff, 0xff, 0xff,
  120. 0xff, 0xff, 0xff, 0xff,
  121. 0, 0, 0, 0,
  122. 0, 0, 0, 0
  123. };
  124. enum
  125. {
  126. Vadd,
  127. Vremove,
  128. Vunbind,
  129. Vaddpref6,
  130. Vra6,
  131. };
  132. static void
  133. ralog(char *fmt, ...)
  134. {
  135. char msg[512];
  136. va_list arg;
  137. va_start(arg, fmt);
  138. vseprint(msg, msg+sizeof msg, fmt, arg);
  139. va_end(arg);
  140. syslog(debug, RALOG, msg);
  141. }
  142. extern void
  143. ea2lla(uint8_t *lla, uint8_t *ea)
  144. {
  145. assert(IPaddrlen == 16);
  146. memset(lla, 0, IPaddrlen);
  147. lla[0] = 0xFE;
  148. lla[1] = 0x80;
  149. lla[8] = ea[0] | 0x2;
  150. lla[9] = ea[1];
  151. lla[10] = ea[2];
  152. lla[11] = 0xFF;
  153. lla[12] = 0xFE;
  154. lla[13] = ea[3];
  155. lla[14] = ea[4];
  156. lla[15] = ea[5];
  157. }
  158. extern void
  159. ipv62smcast(uint8_t *smcast, uint8_t *a)
  160. {
  161. assert(IPaddrlen == 16);
  162. memset(smcast, 0, IPaddrlen);
  163. smcast[0] = 0xFF;
  164. smcast[1] = 0x02;
  165. smcast[11] = 0x1;
  166. smcast[12] = 0xFF;
  167. smcast[13] = a[13];
  168. smcast[14] = a[14];
  169. smcast[15] = a[15];
  170. }
  171. void
  172. v6paraminit(Conf *cf)
  173. {
  174. cf->sendra = cf->recvra = 0;
  175. cf->mflag = 0;
  176. cf->oflag = 0;
  177. cf->maxraint = Maxv6initraintvl;
  178. cf->minraint = Maxv6initraintvl / 4;
  179. cf->linkmtu = 1500;
  180. cf->reachtime = V6reachabletime;
  181. cf->rxmitra = V6retranstimer;
  182. cf->ttl = MAXTTL;
  183. cf->routerlt = 0;
  184. cf->prefixlen = 64;
  185. cf->onlink = 0;
  186. cf->autoflag = 0;
  187. cf->validlt = cf->preflt = ~0L;
  188. }
  189. static char *
  190. optname(unsigned opt)
  191. {
  192. static char buf[32];
  193. if (opt >= nelem(icmp6opts) || icmp6opts[opt] == nil) {
  194. snprint(buf, sizeof buf, "unknown option %d", opt);
  195. return buf;
  196. } else
  197. return icmp6opts[opt];
  198. }
  199. static char*
  200. opt_seprint(uint8_t *ps, uint8_t *pe, char *sps, char *spe)
  201. {
  202. int otype, osz, pktsz;
  203. uint8_t *a;
  204. char *p = sps, *e = spe;
  205. a = ps;
  206. for (pktsz = pe - ps; pktsz > 0; pktsz -= osz) {
  207. otype = a[0];
  208. osz = a[1] * 8;
  209. switch (otype) {
  210. default:
  211. return seprint(p, e, " option=%s ", optname(otype));
  212. case V6nd_srclladdr:
  213. case V6nd_targlladdr:
  214. if (pktsz < osz || osz != 8)
  215. return seprint(p, e, " option=%s bad size=%d",
  216. optname(otype), osz);
  217. p = seprint(p, e, " option=%s maddr=%E", optname(otype),
  218. a+2);
  219. break;
  220. case V6nd_pfxinfo:
  221. if (pktsz < osz || osz != 32)
  222. return seprint(p, e, " option=%s: bad size=%d",
  223. optname(otype), osz);
  224. p = seprint(p, e, " option=%s pref=%I preflen=%3.3d"
  225. " lflag=%1.1d aflag=%1.1d unused1=%1.1d"
  226. " validlt=%u preflt=%u unused2=%1.1d",
  227. optname(otype), a+16, (int)(*(a+2)),
  228. (*(a+3) & (1 << 7)) != 0,
  229. (*(a+3) & (1 << 6)) != 0,
  230. (*(a+3) & 63) != 0,
  231. NetL(a+4), NetL(a+8), NetL(a+12)!=0);
  232. break;
  233. }
  234. a += osz;
  235. }
  236. return p;
  237. }
  238. static void
  239. pkt2str(uint8_t *ps, uint8_t *pe, char *sps, char *spe)
  240. {
  241. int pktlen;
  242. char *tn, *p, *e;
  243. uint8_t *a;
  244. Hdr *h;
  245. h = (Hdr*)ps;
  246. a = ps + 4;
  247. p = sps;
  248. e = spe;
  249. pktlen = pe - ps;
  250. if(pktlen < ICMP6LEN) {
  251. seprint(sps, spe, "short pkt");
  252. return;
  253. }
  254. tn = icmpmsg6[h->type];
  255. if(tn == nil)
  256. p = seprint(p, e, "t=%u c=%d ck=%4.4x", h->type,
  257. h->code, (uint16_t)NetS(h->cksum));
  258. else
  259. p = seprint(p, e, "t=%s c=%d ck=%4.4x", tn,
  260. h->code, (uint16_t)NetS(h->cksum));
  261. switch(h->type){
  262. case RouterSolicit:
  263. ps += 8;
  264. p = seprint(p, e, " unused=%1.1d ", NetL(a)!=0);
  265. opt_seprint(ps, pe, p, e);
  266. break;
  267. case RouterAdvert:
  268. ps += 16;
  269. p = seprint(p, e, " hoplim=%3.3d mflag=%1.1d oflag=%1.1d"
  270. " unused=%1.1d routerlt=%d reachtime=%d rxmtimer=%d",
  271. a[0],
  272. (*(a+1) & (1 << 7)) != 0,
  273. (*(a+1) & (1 << 6)) != 0,
  274. (*(a+1) & 63) != 0,
  275. NetS(a+2), NetL(a+4), NetL(a+8));
  276. opt_seprint(ps, pe, p, e);
  277. break;
  278. default:
  279. seprint(p, e, " unexpected icmp6 pkt type");
  280. break;
  281. }
  282. }
  283. static void
  284. catch(void *a, char *msg)
  285. {
  286. USED(a);
  287. if(strstr(msg, "alarm"))
  288. noted(NCONT);
  289. else
  290. noted(NDFLT);
  291. }
  292. /*
  293. * based on libthread's threadsetname, but drags in less library code.
  294. * actually just sets the arguments displayed.
  295. */
  296. void
  297. procsetname(char *fmt, ...)
  298. {
  299. int fd;
  300. char *cmdname;
  301. char buf[128];
  302. va_list arg;
  303. va_start(arg, fmt);
  304. cmdname = vsmprint(fmt, arg);
  305. va_end(arg);
  306. if (cmdname == nil)
  307. return;
  308. snprint(buf, sizeof buf, "#p/%d/args", getpid());
  309. if((fd = open(buf, OWRITE)) >= 0){
  310. write(fd, cmdname, strlen(cmdname)+1);
  311. close(fd);
  312. }
  313. free(cmdname);
  314. }
  315. int
  316. dialicmp(uint8_t *dst, int dport, int *ctlfd)
  317. {
  318. int fd, cfd, n, m;
  319. char cmsg[100], name[128], connind[40];
  320. char hdrs[] = "headers";
  321. snprint(name, sizeof name, "%s/icmpv6/clone", conf.mpoint);
  322. cfd = open(name, ORDWR);
  323. if(cfd < 0)
  324. sysfatal("dialicmp: can't open %s: %r", name);
  325. n = snprint(cmsg, sizeof cmsg, "connect %I!%d!r %d", dst, dport, dport);
  326. m = write(cfd, cmsg, n);
  327. if (m < n)
  328. sysfatal("dialicmp: can't write %s to %s: %r", cmsg, name);
  329. seek(cfd, 0, 0);
  330. n = read(cfd, connind, sizeof connind);
  331. if (n < 0)
  332. connind[0] = 0;
  333. else if (n < sizeof connind)
  334. connind[n] = 0;
  335. else
  336. connind[sizeof connind - 1] = 0;
  337. snprint(name, sizeof name, "%s/icmpv6/%s/data", conf.mpoint, connind);
  338. fd = open(name, ORDWR);
  339. if(fd < 0)
  340. sysfatal("dialicmp: can't open %s: %r", name);
  341. n = sizeof hdrs - 1;
  342. if(write(cfd, hdrs, n) < n)
  343. sysfatal("dialicmp: can't write `%s' to %s: %r", hdrs, name);
  344. *ctlfd = cfd;
  345. return fd;
  346. }
  347. /* add ipv6 addr to an interface */
  348. int
  349. ip6cfg(int autoconf)
  350. {
  351. int dupfound = 0, n;
  352. char *p;
  353. char buf[256];
  354. uint8_t ethaddr[6];
  355. Biobuf *bp;
  356. if (autoconf) { /* create link-local addr */
  357. if (myetheraddr(ethaddr, conf.dev) < 0)
  358. sysfatal("myetheraddr w/ %s failed: %r", conf.dev);
  359. ea2lla(conf.laddr, ethaddr);
  360. }
  361. if (dupl_disc)
  362. n = sprint(buf, "try");
  363. else
  364. n = sprint(buf, "add");
  365. n += snprint(buf+n, sizeof buf-n, " %I", conf.laddr);
  366. if(!validip(conf.mask))
  367. ipmove(conf.mask, v6defmask);
  368. n += snprint(buf+n, sizeof buf-n, " %M", conf.mask);
  369. if(validip(conf.raddr)){
  370. n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
  371. if(conf.mtu != 0)
  372. n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
  373. }
  374. if(write(conf.cfd, buf, n) < 0){
  375. warning("write(%s): %r", buf);
  376. return -1;
  377. }
  378. if (!dupl_disc)
  379. return 0;
  380. sleep(3000);
  381. /* read arp table, look for addr duplication */
  382. snprint(buf, sizeof buf, "%s/arp", conf.mpoint);
  383. bp = Bopen(buf, OREAD);
  384. if (bp == 0) {
  385. warning("couldn't open %s: %r", buf);
  386. return -1;
  387. }
  388. snprint(buf, sizeof buf, "%I", conf.laddr);
  389. while(p = Brdline(bp, '\n')){
  390. p[Blinelen(bp)-1] = 0;
  391. if(cistrstr(p, buf) != 0) {
  392. warning("found dup entry in arp cache");
  393. dupfound = 1;
  394. break;
  395. }
  396. }
  397. Bterm(bp);
  398. if (dupfound)
  399. doremove();
  400. else {
  401. n = sprint(buf, "add %I %M", conf.laddr, conf.mask);
  402. if(validip(conf.raddr)){
  403. n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
  404. if(conf.mtu != 0)
  405. n += snprint(buf+n, sizeof buf-n, " %d",
  406. conf.mtu);
  407. }
  408. write(conf.cfd, buf, n);
  409. }
  410. return 0;
  411. }
  412. static int
  413. recvra6on(char *net, int conn)
  414. {
  415. Ipifc* ifc;
  416. ifc = readipifc(net, nil, conn);
  417. if (ifc == nil)
  418. return 0;
  419. else if (ifc->sendra6 > 0)
  420. return IsRouter;
  421. else if (ifc->recvra6 > 0)
  422. return IsHostRecv;
  423. else
  424. return IsHostNoRecv;
  425. }
  426. /* send icmpv6 router solicitation to multicast address for all routers */
  427. static void
  428. sendrs(int fd)
  429. {
  430. Routersol *rs;
  431. uint8_t buff[sizeof *rs];
  432. memset(buff, 0, sizeof buff);
  433. rs = (Routersol *)buff;
  434. memmove(rs->dst, v6allroutersL, IPaddrlen);
  435. memmove(rs->src, v6Unspecified, IPaddrlen);
  436. rs->type = ICMP6_RS;
  437. if(write(fd, rs, sizeof buff) < sizeof buff)
  438. ralog("sendrs: write failed, pkt size %d", sizeof buff);
  439. else
  440. ralog("sendrs: sent solicitation to %I from %I on %s",
  441. rs->dst, rs->src, conf.dev);
  442. }
  443. /*
  444. * a router receiving a router adv from another
  445. * router calls this; it is basically supposed to
  446. * log the information in the ra and raise a flag
  447. * if any parameter value is different from its configured values.
  448. *
  449. * doing nothing for now since I don't know where to log this yet.
  450. */
  451. static void
  452. recvrarouter(uint8_t buf[], int pktlen)
  453. {
  454. USED(buf); USED(pktlen);
  455. ralog("i am a router and got a router advert");
  456. }
  457. /* host receiving a router advertisement calls this */
  458. static void
  459. ewrite(int fd, char *str)
  460. {
  461. int n;
  462. n = strlen(str);
  463. if (write(fd, str, n) != n)
  464. ralog("write(%s) failed: %r", str);
  465. }
  466. static void
  467. issuebasera6(Conf *cf)
  468. {
  469. char *cfg;
  470. cfg = smprint("ra6 mflag %d oflag %d reachtime %d rxmitra %d "
  471. "ttl %d routerlt %d",
  472. cf->mflag, cf->oflag, cf->reachtime, cf->rxmitra,
  473. cf->ttl, cf->routerlt);
  474. ewrite(cf->cfd, cfg);
  475. free(cfg);
  476. }
  477. static void
  478. issuerara6(Conf *cf)
  479. {
  480. char *cfg;
  481. cfg = smprint("ra6 sendra %d recvra %d maxraint %d minraint %d "
  482. "linkmtu %d",
  483. cf->sendra, cf->recvra, cf->maxraint, cf->minraint,
  484. cf->linkmtu);
  485. ewrite(cf->cfd, cfg);
  486. free(cfg);
  487. }
  488. static void
  489. issueadd6(Conf *cf)
  490. {
  491. char *cfg;
  492. cfg = smprint("add6 %I %d %d %d %lu %lu", cf->v6pref, cf->prefixlen,
  493. cf->onlink, cf->autoflag, cf->validlt, cf->preflt);
  494. ewrite(cf->cfd, cfg);
  495. free(cfg);
  496. }
  497. static void
  498. recvrahost(uint8_t buf[], int pktlen)
  499. {
  500. int arpfd, m, n;
  501. char abuf[100];
  502. uint8_t optype;
  503. Lladdropt *llao;
  504. Mtuopt *mtuo;
  505. Prefixopt *prfo;
  506. Routeradv *ra;
  507. static int first = 1;
  508. ra = (Routeradv*)buf;
  509. // memmove(conf.v6gaddr, ra->src, IPaddrlen);
  510. conf.ttl = ra->cttl;
  511. conf.mflag = (MFMASK & ra->mor);
  512. conf.oflag = (OCMASK & ra->mor);
  513. conf.routerlt = nhgets(ra->routerlt);
  514. conf.reachtime = nhgetl(ra->rchbltime);
  515. conf.rxmitra = nhgetl(ra->rxmtimer);
  516. // issueadd6(&conf); /* for conf.v6gaddr? */
  517. if (fprint(conf.cfd, "ra6 recvra 1") < 0)
  518. ralog("write(ra6 recvra 1) failed: %r");
  519. issuebasera6(&conf);
  520. m = sizeof *ra;
  521. while (pktlen - m > 0) {
  522. optype = buf[m];
  523. switch (optype) {
  524. case V6nd_srclladdr:
  525. llao = (Lladdropt *)&buf[m];
  526. m += 8 * buf[m+1];
  527. if (llao->len != 1) {
  528. ralog("recvrahost: illegal len (%d) for source "
  529. "link layer address option", llao->len);
  530. return;
  531. }
  532. if (!ISIPV6LINKLOCAL(ra->src)) {
  533. ralog("recvrahost: non-link-local src addr for "
  534. "router adv %I", ra->src);
  535. return;
  536. }
  537. snprint(abuf, sizeof abuf, "%s/arp", conf.mpoint);
  538. arpfd = open(abuf, OWRITE);
  539. if (arpfd < 0) {
  540. ralog("recvrahost: couldn't open %s to write: %r",
  541. abuf);
  542. return;
  543. }
  544. n = snprint(abuf, sizeof abuf, "add ether %I %E",
  545. ra->src, llao->lladdr);
  546. if (write(arpfd, abuf, n) < n)
  547. ralog("recvrahost: couldn't write to %s/arp",
  548. conf.mpoint);
  549. close(arpfd);
  550. break;
  551. case V6nd_targlladdr:
  552. case V6nd_redirhdr:
  553. m += 8 * buf[m+1];
  554. ralog("ignoring unexpected option type `%s' in Routeradv",
  555. optname(optype));
  556. break;
  557. case V6nd_mtu:
  558. mtuo = (Mtuopt*)&buf[m];
  559. m += 8 * mtuo->len;
  560. conf.linkmtu = nhgetl(mtuo->mtu);
  561. break;
  562. case V6nd_pfxinfo:
  563. prfo = (Prefixopt*)&buf[m];
  564. m += 8 * prfo->len;
  565. if (prfo->len != 4) {
  566. ralog("illegal len (%d) for prefix option",
  567. prfo->len);
  568. return;
  569. }
  570. memmove(conf.v6pref, prfo->pref, IPaddrlen);
  571. conf.prefixlen = prfo->plen;
  572. conf.onlink = ((prfo->lar & OLMASK) != 0);
  573. conf.autoflag = ((prfo->lar & AFMASK) != 0);
  574. conf.validlt = nhgetl(prfo->validlt);
  575. conf.preflt = nhgetl(prfo->preflt);
  576. issueadd6(&conf);
  577. if (first) {
  578. first = 0;
  579. ralog("got initial RA from %I on %s; pfx %I",
  580. ra->src, conf.dev, prfo->pref);
  581. }
  582. break;
  583. default:
  584. if (debug)
  585. ralog("ignoring optype %d in Routeradv from %I",
  586. optype, ra->src);
  587. /* fall through */
  588. case V6nd_srcaddrs:
  589. /* netsbd sends this, so quietly ignore it for now */
  590. m += 8 * buf[m+1];
  591. break;
  592. }
  593. }
  594. }
  595. /*
  596. * daemon to receive router advertisements from routers
  597. */
  598. void
  599. recvra6(void)
  600. {
  601. int fd, cfd, n, sendrscnt, sleepfor;
  602. uint8_t buf[4096];
  603. /* TODO: why not v6allroutersL? */
  604. fd = dialicmp(v6allnodesL, ICMP6_RA, &cfd);
  605. if (fd < 0)
  606. sysfatal("can't open icmp_ra connection: %r");
  607. notify(catch);
  608. sendrscnt = Maxv6rss;
  609. switch(rfork(RFPROC|RFMEM|RFFDG|RFNOWAIT|RFNOTEG)){
  610. case -1:
  611. sysfatal("can't fork: %r");
  612. default:
  613. return;
  614. case 0:
  615. break;
  616. }
  617. procsetname("recvra6 on %s", conf.dev);
  618. ralog("recvra6 on %s", conf.dev);
  619. sleepfor = jitter();
  620. for (;;) {
  621. /*
  622. * We only get 3 (Maxv6rss) tries, so make sure we
  623. * wait long enough to be certain that at least one RA
  624. * will be transmitted.
  625. */
  626. if (sleepfor < 7000)
  627. sleepfor = 7000;
  628. alarm(sleepfor);
  629. n = read(fd, buf, sizeof buf);
  630. alarm(0);
  631. if (n <= 0) {
  632. if (sendrscnt > 0) {
  633. sendrscnt--;
  634. if (recvra6on(conf.mpoint, myifc) == IsHostRecv)
  635. sendrs(fd);
  636. sleepfor = V6rsintvl + nrand(100);
  637. }
  638. if (sendrscnt == 0) {
  639. sendrscnt--;
  640. sleepfor = 0;
  641. ralog("recvra6: no router advs after %d sols on %s",
  642. Maxv6rss, conf.dev);
  643. }
  644. continue;
  645. }
  646. sleepfor = 0;
  647. sendrscnt = -1; /* got at least initial ra; no whining */
  648. switch (recvra6on(conf.mpoint, myifc)) {
  649. case IsRouter:
  650. recvrarouter(buf, n);
  651. break;
  652. case IsHostRecv:
  653. recvrahost(buf, n);
  654. break;
  655. case IsHostNoRecv:
  656. ralog("recvra6: recvra off, quitting on %s", conf.dev);
  657. close(fd);
  658. exits(0);
  659. default:
  660. ralog("recvra6: unable to read router status on %s",
  661. conf.dev);
  662. break;
  663. }
  664. }
  665. }
  666. /*
  667. * return -1 -- error, reading/writing some file,
  668. * 0 -- no arp table updates
  669. * 1 -- successful arp table update
  670. */
  671. int
  672. recvrs(uint8_t *buf, int pktlen, uint8_t *sol)
  673. {
  674. int n, optsz, arpfd;
  675. char abuf[256];
  676. Routersol *rs;
  677. Lladdropt *llao;
  678. rs = (Routersol *)buf;
  679. n = sizeof *rs;
  680. optsz = pktlen - n;
  681. pkt2str(buf, buf+pktlen, abuf, abuf+nelem(abuf));
  682. if (optsz != sizeof *llao)
  683. return 0;
  684. if (buf[n] != V6nd_srclladdr || 8*buf[n+1] != sizeof *llao) {
  685. ralog("rs opt err %s", abuf);
  686. return -1;
  687. }
  688. ralog("rs recv %s", abuf);
  689. if (memcmp(rs->src, v6Unspecified, IPaddrlen) == 0)
  690. return 0;
  691. snprint(abuf, sizeof abuf, "%s/arp", conf.mpoint);
  692. arpfd = open(abuf, OWRITE);
  693. if (arpfd < 0) {
  694. ralog("recvrs: can't open %s/arp to write: %r", conf.mpoint);
  695. return -1;
  696. }
  697. llao = (Lladdropt *)(uint64_t)buf[n];
  698. n = snprint(abuf, sizeof abuf, "add ether %I %E", rs->src, llao->lladdr);
  699. if (write(arpfd, abuf, n) < n) {
  700. ralog("recvrs: can't write to %s/arp: %r", conf.mpoint);
  701. close(arpfd);
  702. return -1;
  703. }
  704. memmove(sol, rs->src, IPaddrlen);
  705. close(arpfd);
  706. return 1;
  707. }
  708. void
  709. sendra(int fd, uint8_t *dst, int rlt)
  710. {
  711. int pktsz, preflen;
  712. char abuf[1024], tmp[40];
  713. uint8_t buf[1024], macaddr[6], src[IPaddrlen];
  714. Ipifc *ifc = nil;
  715. Iplifc *lifc, *nlifc;
  716. Lladdropt *llao;
  717. Prefixopt *prfo;
  718. Routeradv *ra;
  719. memset(buf, 0, sizeof buf);
  720. ra = (Routeradv *)buf;
  721. myetheraddr(macaddr, conf.dev);
  722. ea2lla(src, macaddr);
  723. memmove(ra->src, src, IPaddrlen);
  724. memmove(ra->dst, dst, IPaddrlen);
  725. ra->type = ICMP6_RA;
  726. ra->cttl = conf.ttl;
  727. if (conf.mflag > 0)
  728. ra->mor |= MFMASK;
  729. if (conf.oflag > 0)
  730. ra->mor |= OCMASK;
  731. if (rlt > 0)
  732. hnputs(ra->routerlt, conf.routerlt);
  733. else
  734. hnputs(ra->routerlt, 0);
  735. hnputl(ra->rchbltime, conf.reachtime);
  736. hnputl(ra->rxmtimer, conf.rxmitra);
  737. pktsz = sizeof *ra;
  738. /* include all global unicast prefixes on interface in prefix options */
  739. ifc = readipifc(conf.mpoint, ifc, myifc);
  740. for (lifc = (ifc? ifc->lifc: nil); lifc; lifc = nlifc) {
  741. nlifc = lifc->next;
  742. prfo = (Prefixopt *)(buf + pktsz);
  743. /* global unicast address? */
  744. if (!ISIPV6LINKLOCAL(lifc->ip) && !ISIPV6MCAST(lifc->ip) &&
  745. memcmp(lifc->ip, IPnoaddr, IPaddrlen) != 0 &&
  746. memcmp(lifc->ip, v6loopback, IPaddrlen) != 0 &&
  747. !isv4(lifc->ip)) {
  748. memmove(prfo->pref, lifc->net, IPaddrlen);
  749. /* hack to find prefix length */
  750. snprint(tmp, sizeof tmp, "%M", lifc->mask);
  751. preflen = atoi(&tmp[1]);
  752. prfo->plen = preflen & 0xff;
  753. if (prfo->plen == 0)
  754. continue;
  755. prfo->type = V6nd_pfxinfo;
  756. prfo->len = 4;
  757. prfo->lar = AFMASK;
  758. hnputl(prfo->validlt, lifc->validlt);
  759. hnputl(prfo->preflt, lifc->preflt);
  760. pktsz += sizeof *prfo;
  761. }
  762. }
  763. /*
  764. * include link layer address (mac address for now) in
  765. * link layer address option
  766. */
  767. llao = (Lladdropt *)(buf + pktsz);
  768. llao->type = V6nd_srclladdr;
  769. llao->len = 1;
  770. memmove(llao->lladdr, macaddr, sizeof macaddr);
  771. pktsz += sizeof *llao;
  772. pkt2str(buf+40, buf+pktsz, abuf, abuf+1024);
  773. if(write(fd, buf, pktsz) < pktsz)
  774. ralog("sendra fail %s: %r", abuf);
  775. else if (debug)
  776. ralog("sendra succ %s", abuf);
  777. }
  778. /*
  779. * daemon to send router advertisements to hosts
  780. */
  781. void
  782. sendra6(void)
  783. {
  784. int fd, cfd, n, dstknown = 0, sendracnt, sleepfor, nquitmsgs;
  785. int32_t lastra, now;
  786. uint8_t buf[4096], dst[IPaddrlen];
  787. Ipifc *ifc = nil;
  788. fd = dialicmp(v6allnodesL, ICMP6_RS, &cfd);
  789. if (fd < 0)
  790. sysfatal("can't open icmp_rs connection: %r");
  791. notify(catch);
  792. sendracnt = Maxv6initras;
  793. nquitmsgs = Maxv6finalras;
  794. switch(rfork(RFPROC|RFMEM|RFFDG|RFNOWAIT|RFNOTEG)){
  795. case -1:
  796. sysfatal("can't fork: %r");
  797. default:
  798. return;
  799. case 0:
  800. break;
  801. }
  802. procsetname("sendra6 on %s", conf.dev);
  803. ralog("sendra6 on %s", conf.dev);
  804. sleepfor = jitter();
  805. for (;;) {
  806. lastra = time(0);
  807. if (sleepfor < 0)
  808. sleepfor = 0;
  809. alarm(sleepfor);
  810. n = read(fd, buf, sizeof buf);
  811. alarm(0);
  812. ifc = readipifc(conf.mpoint, ifc, myifc);
  813. if (ifc == nil) {
  814. ralog("sendra6: can't read router params on %s",
  815. conf.mpoint);
  816. continue;
  817. }
  818. if (ifc->sendra6 <= 0)
  819. if (nquitmsgs > 0) {
  820. sendra(fd, v6allnodesL, 0);
  821. nquitmsgs--;
  822. sleepfor = Minv6interradelay + jitter();
  823. continue;
  824. } else {
  825. ralog("sendra6: sendra off, quitting on %s",
  826. conf.dev);
  827. exits(0);
  828. }
  829. nquitmsgs = Maxv6finalras;
  830. if (n <= 0) { /* no RS */
  831. if (sendracnt > 0)
  832. sendracnt--;
  833. } else { /* respond to RS */
  834. dstknown = recvrs(buf, n, dst);
  835. now = time(0);
  836. if (now - lastra < Minv6interradelay) {
  837. /* too close, skip */
  838. sleepfor = lastra + Minv6interradelay +
  839. jitter() - now;
  840. continue;
  841. }
  842. sleep(jitter());
  843. }
  844. sleepfor = randint(ifc->rp.minraint, ifc->rp.maxraint);
  845. if (dstknown > 0)
  846. sendra(fd, dst, 1);
  847. else
  848. sendra(fd, v6allnodesL, 1);
  849. }
  850. }
  851. void
  852. startra6(void)
  853. {
  854. static char routeon[] = "iprouting 1";
  855. if (conf.recvra > 0)
  856. recvra6();
  857. if (conf.sendra > 0) {
  858. if (write(conf.cfd, routeon, sizeof routeon - 1) < 0) {
  859. warning("write (iprouting 1) failed: %r");
  860. return;
  861. }
  862. sendra6();
  863. if (conf.recvra <= 0)
  864. recvra6();
  865. }
  866. }
  867. void
  868. doipv6(int what)
  869. {
  870. nip = nipifcs(conf.mpoint);
  871. if(!noconfig){
  872. lookforip(conf.mpoint);
  873. controldevice();
  874. binddevice();
  875. }
  876. switch (what) {
  877. default:
  878. sysfatal("unknown IPv6 verb");
  879. case Vaddpref6:
  880. issueadd6(&conf);
  881. break;
  882. case Vra6:
  883. issuebasera6(&conf);
  884. issuerara6(&conf);
  885. dolog = 1;
  886. startra6();
  887. break;
  888. }
  889. }