netif.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  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 "../port/netif.h"
  16. static int netown(Netfile*, char*, int);
  17. static int openfile(Netif*, int);
  18. static char* matchtoken(char*, char*);
  19. static char* netmulti(Netif*, Netfile*, uint8_t*, int);
  20. static int parseaddr(uint8_t*, char*, int);
  21. /*
  22. * set up a new network interface
  23. */
  24. void
  25. netifinit(Netif *nif, char *name, int nfile, uint32_t limit)
  26. {
  27. strncpy(nif->name, name, KNAMELEN-1);
  28. nif->name[KNAMELEN-1] = 0;
  29. nif->nfile = nfile;
  30. nif->f = malloc(nfile*sizeof(Netfile*));
  31. if(nif->f == nil)
  32. panic("netifinit: no memory");
  33. memset(nif->f, 0, nfile*sizeof(Netfile*));
  34. nif->limit = limit;
  35. }
  36. /*
  37. * generate a 3 level directory
  38. */
  39. static int
  40. netifgen(Chan *c, char*, Dirtab *vp, int, int i, Dir *dp)
  41. {
  42. Qid q;
  43. Netif *nif = (Netif*)vp;
  44. Netfile *f;
  45. int t;
  46. int perm;
  47. char *o;
  48. q.type = QTFILE;
  49. q.vers = 0;
  50. /* top level directory contains the name of the network */
  51. if(c->qid.path == 0){
  52. switch(i){
  53. case DEVDOTDOT:
  54. q.path = 0;
  55. q.type = QTDIR;
  56. devdir(c, q, ".", 0, eve, 0555, dp);
  57. break;
  58. case 0:
  59. q.path = N2ndqid;
  60. q.type = QTDIR;
  61. strcpy(up->genbuf, nif->name);
  62. devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  63. break;
  64. default:
  65. return -1;
  66. }
  67. return 1;
  68. }
  69. /* second level contains clone plus all the conversations */
  70. t = NETTYPE(c->qid.path);
  71. if(t == N2ndqid || t == Ncloneqid || t == Naddrqid
  72. || t == Nstatqid || t == Nifstatqid || t == Nmtuqid){
  73. switch(i) {
  74. case DEVDOTDOT:
  75. q.type = QTDIR;
  76. q.path = 0;
  77. devdir(c, q, ".", 0, eve, DMDIR|0555, dp);
  78. break;
  79. case 0:
  80. q.path = Ncloneqid;
  81. devdir(c, q, "clone", 0, eve, 0666, dp);
  82. break;
  83. case 1:
  84. q.path = Naddrqid;
  85. devdir(c, q, "addr", 0, eve, 0666, dp);
  86. break;
  87. case 2:
  88. q.path = Nstatqid;
  89. devdir(c, q, "stats", 0, eve, 0444, dp);
  90. break;
  91. case 3:
  92. q.path = Nifstatqid;
  93. devdir(c, q, "ifstats", 0, eve, 0444, dp);
  94. break;
  95. case 4:
  96. q.path = Nmtuqid;
  97. devdir(c, q, "mtu", 0, eve, 0444, dp);
  98. break;
  99. default:
  100. i -= 5;
  101. if(i >= nif->nfile)
  102. return -1;
  103. if(nif->f[i] == 0)
  104. return 0;
  105. q.type = QTDIR;
  106. q.path = NETQID(i, N3rdqid);
  107. snprint(up->genbuf, sizeof up->genbuf, "%d", i);
  108. devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
  109. break;
  110. }
  111. return 1;
  112. }
  113. /* third level */
  114. f = nif->f[NETID(c->qid.path)];
  115. if(f == 0)
  116. return 0;
  117. if(*f->owner){
  118. o = f->owner;
  119. perm = f->mode;
  120. } else {
  121. o = eve;
  122. perm = 0666;
  123. }
  124. switch(i){
  125. case DEVDOTDOT:
  126. q.type = QTDIR;
  127. q.path = N2ndqid;
  128. strcpy(up->genbuf, nif->name);
  129. devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
  130. break;
  131. case 0:
  132. q.path = NETQID(NETID(c->qid.path), Ndataqid);
  133. devdir(c, q, "data", 0, o, perm, dp);
  134. break;
  135. case 1:
  136. q.path = NETQID(NETID(c->qid.path), Nctlqid);
  137. devdir(c, q, "ctl", 0, o, perm, dp);
  138. break;
  139. case 2:
  140. q.path = NETQID(NETID(c->qid.path), Nstatqid);
  141. devdir(c, q, "stats", 0, eve, 0444, dp);
  142. break;
  143. case 3:
  144. q.path = NETQID(NETID(c->qid.path), Ntypeqid);
  145. devdir(c, q, "type", 0, eve, 0444, dp);
  146. break;
  147. case 4:
  148. q.path = NETQID(NETID(c->qid.path), Nifstatqid);
  149. devdir(c, q, "ifstats", 0, eve, 0444, dp);
  150. break;
  151. default:
  152. return -1;
  153. }
  154. return 1;
  155. }
  156. Walkqid*
  157. netifwalk(Netif *nif, Chan *c, Chan *nc, char **name, int nname)
  158. {
  159. return devwalk(c, nc, name, nname, (Dirtab *)nif, 0, netifgen);
  160. }
  161. Chan*
  162. netifopen(Netif *nif, Chan *c, int omode)
  163. {
  164. int id;
  165. Netfile *f;
  166. id = 0;
  167. if(c->qid.type & QTDIR){
  168. if(omode != OREAD)
  169. error(Eperm);
  170. } else {
  171. switch(NETTYPE(c->qid.path)){
  172. case Ndataqid:
  173. case Nctlqid:
  174. id = NETID(c->qid.path);
  175. openfile(nif, id);
  176. break;
  177. case Ncloneqid:
  178. id = openfile(nif, -1);
  179. c->qid.path = NETQID(id, Nctlqid);
  180. break;
  181. default:
  182. if(omode != OREAD)
  183. error(Ebadarg);
  184. }
  185. switch(NETTYPE(c->qid.path)){
  186. case Ndataqid:
  187. case Nctlqid:
  188. f = nif->f[id];
  189. if(netown(f, up->user, omode&7) < 0){
  190. netifclose(nif, c);
  191. error(Eperm);
  192. }
  193. break;
  194. }
  195. }
  196. c->mode = openmode(omode);
  197. c->flag |= COPEN;
  198. c->offset = 0;
  199. c->iounit = qiomaxatomic;
  200. return c;
  201. }
  202. int32_t
  203. netifread(Netif *nif, Chan *c, void *a, int32_t n, int64_t off)
  204. {
  205. int i, j;
  206. Netfile *f;
  207. char *p;
  208. int32_t offset;
  209. if(c->qid.type & QTDIR)
  210. return devdirread(c, a, n, (Dirtab*)nif, 0, netifgen);
  211. offset = off;
  212. switch(NETTYPE(c->qid.path)){
  213. case Ndataqid:
  214. f = nif->f[NETID(c->qid.path)];
  215. return qread(f->iq, a, n);
  216. case Nctlqid:
  217. return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
  218. case Nstatqid:
  219. p = malloc(READSTR);
  220. if(p == nil)
  221. error(Enomem);
  222. j = snprint(p, READSTR, "in: %llud\n", nif->inpackets);
  223. j += snprint(p+j, READSTR-j, "link: %d\n", nif->link);
  224. j += snprint(p+j, READSTR-j, "out: %llud\n", nif->outpackets);
  225. j += snprint(p+j, READSTR-j, "crc errs: %llud\n", nif->crcs);
  226. j += snprint(p+j, READSTR-j, "overflows: %llud\n", nif->overflows);
  227. j += snprint(p+j, READSTR-j, "soft overflows: %llud\n", nif->soverflows);
  228. j += snprint(p+j, READSTR-j, "framing errs: %llud\n", nif->frames);
  229. j += snprint(p+j, READSTR-j, "buffer errs: %llud\n", nif->buffs);
  230. j += snprint(p+j, READSTR-j, "output errs: %llud\n", nif->oerrs);
  231. j += snprint(p+j, READSTR-j, "prom: %d\n", nif->prom);
  232. j += snprint(p+j, READSTR-j, "mbps: %d\n", nif->mbps);
  233. j += snprint(p+j, READSTR-j, "addr: ");
  234. for(i = 0; i < nif->alen; i++)
  235. j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);
  236. snprint(p+j, READSTR-j, "\n");
  237. n = readstr(offset, a, n, p);
  238. free(p);
  239. return n;
  240. case Naddrqid:
  241. p = malloc(READSTR);
  242. j = 0;
  243. for(i = 0; i < nif->alen; i++)
  244. j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);
  245. n = readstr(offset, a, n, p);
  246. free(p);
  247. return n;
  248. case Ntypeqid:
  249. f = nif->f[NETID(c->qid.path)];
  250. return readnum(offset, a, n, f->type, NUMSIZE);
  251. case Nifstatqid:
  252. return 0;
  253. case Nmtuqid:
  254. snprint(up->genbuf, sizeof up->genbuf, "%11.ud %11.ud %11.ud\n", nif->minmtu, nif->mtu, nif->maxmtu);
  255. return readstr(offset, a, n, up->genbuf);
  256. }
  257. error(Ebadarg);
  258. return -1; /* not reached */
  259. }
  260. Block*
  261. netifbread(Netif *nif, Chan *c, int32_t n, int64_t offset)
  262. {
  263. if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
  264. return devbread(c, n, offset);
  265. return qbread(nif->f[NETID(c->qid.path)]->iq, n);
  266. }
  267. /*
  268. * make sure this type isn't already in use on this device
  269. */
  270. static int
  271. typeinuse(Netif *nif, int type)
  272. {
  273. Netfile *f, **fp, **efp;
  274. if(type <= 0)
  275. return 0;
  276. efp = &nif->f[nif->nfile];
  277. for(fp = nif->f; fp < efp; fp++){
  278. f = *fp;
  279. if(f == 0)
  280. continue;
  281. if(f->type == type)
  282. return 1;
  283. }
  284. return 0;
  285. }
  286. /*
  287. * the devxxx.c that calls us handles writing data, it knows best
  288. */
  289. int32_t
  290. netifwrite(Netif *nif, Chan *c, void *a, int32_t n)
  291. {
  292. Netfile *f;
  293. int type, mtu;
  294. char *p, buf[64];
  295. uint8_t binaddr[Nmaxaddr];
  296. if(NETTYPE(c->qid.path) != Nctlqid)
  297. error(Eperm);
  298. if(n >= sizeof(buf))
  299. n = sizeof(buf)-1;
  300. memmove(buf, a, n);
  301. buf[n] = 0;
  302. if(waserror()){
  303. qunlock(nif);
  304. nexterror();
  305. }
  306. qlock(nif);
  307. f = nif->f[NETID(c->qid.path)];
  308. if((p = matchtoken(buf, "connect")) != 0){
  309. qclose(f->iq);
  310. type = atoi(p);
  311. if(typeinuse(nif, type))
  312. error(Einuse);
  313. f->type = type;
  314. if(f->type < 0)
  315. nif->all++;
  316. qreopen(f->iq);
  317. } else if(matchtoken(buf, "promiscuous")){
  318. if(f->prom == 0){
  319. if(nif->prom == 0 && nif->promiscuous != nil)
  320. nif->promiscuous(nif->arg, 1);
  321. f->prom = 1;
  322. nif->prom++;
  323. }
  324. } else if((p = matchtoken(buf, "scanbs")) != 0){
  325. /* scan for base stations */
  326. if(f->scan == 0){
  327. type = atoi(p);
  328. if(type < 5)
  329. type = 5;
  330. if(nif->scanbs != nil)
  331. nif->scanbs(nif->arg, type);
  332. f->scan = type;
  333. nif->scan++;
  334. }
  335. } else if((p = matchtoken(buf, "mtu")) != 0){
  336. /* poor planning. */
  337. if(!iseve())
  338. error(Eperm);
  339. mtu = atoi(p);
  340. /* zero resets default. */
  341. if(mtu != 0)
  342. if(mtu < nif->minmtu || mtu > nif->maxmtu)
  343. error(Ebadarg);
  344. if(nif->hwmtu)
  345. nif->mtu = nif->hwmtu(nif->arg, mtu);
  346. else
  347. nif->mtu = mtu;
  348. } else if(matchtoken(buf, "l2bridge")){
  349. f->bridge |= 2;
  350. } else if(matchtoken(buf, "bridge")){
  351. f->bridge |= 1;
  352. } else if(matchtoken(buf, "headersonly")){
  353. f->headersonly = 1;
  354. } else if((p = matchtoken(buf, "addmulti")) != 0){
  355. if(parseaddr(binaddr, p, nif->alen) < 0)
  356. error("bad address");
  357. p = netmulti(nif, f, binaddr, 1);
  358. if(p)
  359. error(p);
  360. } else if((p = matchtoken(buf, "remmulti")) != 0){
  361. if(parseaddr(binaddr, p, nif->alen) < 0)
  362. error("bad address");
  363. p = netmulti(nif, f, binaddr, 0);
  364. if(p)
  365. error(p);
  366. } else
  367. n = -1;
  368. qunlock(nif);
  369. poperror();
  370. return n;
  371. }
  372. int32_t
  373. netifwstat(Netif *nif, Chan *c, uint8_t *db, int32_t n)
  374. {
  375. Dir *dir;
  376. Netfile *f;
  377. int l;
  378. f = nif->f[NETID(c->qid.path)];
  379. if(f == 0)
  380. error(Enonexist);
  381. if(netown(f, up->user, OWRITE) < 0)
  382. error(Eperm);
  383. dir = smalloc(sizeof(Dir)+n);
  384. l = convM2D(db, n, &dir[0], (char*)&dir[1]);
  385. if(l == 0){
  386. free(dir);
  387. error(Eshortstat);
  388. }
  389. if(!emptystr(dir[0].uid))
  390. strncpy(f->owner, dir[0].uid, KNAMELEN);
  391. if(dir[0].mode != ~0UL)
  392. f->mode = dir[0].mode;
  393. free(dir);
  394. return l;
  395. }
  396. int32_t
  397. netifstat(Netif *nif, Chan *c, uint8_t *db, int32_t n)
  398. {
  399. return devstat(c, db, n, (Dirtab *)nif, 0, netifgen);
  400. }
  401. void
  402. netifclose(Netif *nif, Chan *c)
  403. {
  404. Netfile *f;
  405. int t;
  406. Netaddr *ap;
  407. if((c->flag & COPEN) == 0)
  408. return;
  409. t = NETTYPE(c->qid.path);
  410. if(t != Ndataqid && t != Nctlqid)
  411. return;
  412. f = nif->f[NETID(c->qid.path)];
  413. qlock(f);
  414. if(--(f->inuse) == 0){
  415. if(f->prom){
  416. qlock(nif);
  417. if(--(nif->prom) == 0 && nif->promiscuous != nil)
  418. nif->promiscuous(nif->arg, 0);
  419. qunlock(nif);
  420. f->prom = 0;
  421. }
  422. if(f->scan){
  423. qlock(nif);
  424. if(--(nif->scan) == 0 && nif->scanbs != nil)
  425. nif->scanbs(nif->arg, 0);
  426. qunlock(nif);
  427. f->prom = 0;
  428. f->scan = 0;
  429. }
  430. if(f->nmaddr){
  431. qlock(nif);
  432. t = 0;
  433. for(ap = nif->maddr; ap; ap = ap->next){
  434. if(f->maddr[t/8] & (1<<(t%8)))
  435. netmulti(nif, f, ap->addr, 0);
  436. }
  437. qunlock(nif);
  438. f->nmaddr = 0;
  439. }
  440. if(f->type < 0){
  441. qlock(nif);
  442. --(nif->all);
  443. qunlock(nif);
  444. }
  445. f->owner[0] = 0;
  446. f->type = 0;
  447. f->bridge = 0;
  448. f->headersonly = 0;
  449. qclose(f->iq);
  450. }
  451. qunlock(f);
  452. }
  453. Lock netlock;
  454. static int
  455. netown(Netfile *p, char *o, int omode)
  456. {
  457. static int access[] = { 0400, 0200, 0600, 0100 };
  458. int mode;
  459. int t;
  460. lock(&netlock);
  461. if(*p->owner){
  462. if(strncmp(o, p->owner, KNAMELEN) == 0) /* User */
  463. mode = p->mode;
  464. else if(strncmp(o, eve, KNAMELEN) == 0) /* Bootes is group */
  465. mode = p->mode<<3;
  466. else
  467. mode = p->mode<<6; /* Other */
  468. t = access[omode&3];
  469. if((t & mode) == t){
  470. unlock(&netlock);
  471. return 0;
  472. } else {
  473. unlock(&netlock);
  474. return -1;
  475. }
  476. }
  477. strncpy(p->owner, o, KNAMELEN);
  478. p->mode = 0660;
  479. unlock(&netlock);
  480. return 0;
  481. }
  482. /*
  483. * Increment the reference count of a network device.
  484. * If id < 0, return an unused ether device.
  485. */
  486. static int
  487. openfile(Netif *nif, int id)
  488. {
  489. Netfile *f, **fp, **efp;
  490. if(id >= 0){
  491. f = nif->f[id];
  492. if(f == 0)
  493. error(Enodev);
  494. qlock(f);
  495. qreopen(f->iq);
  496. f->inuse++;
  497. qunlock(f);
  498. return id;
  499. }
  500. qlock(nif);
  501. if(waserror()){
  502. qunlock(nif);
  503. nexterror();
  504. }
  505. efp = &nif->f[nif->nfile];
  506. for(fp = nif->f; fp < efp; fp++){
  507. f = *fp;
  508. if(f == 0){
  509. f = malloc(sizeof(Netfile));
  510. if(f == 0)
  511. exhausted("memory");
  512. f->iq = qopen(nif->limit, Qmsg, 0, 0);
  513. if(f->iq == nil){
  514. free(f);
  515. exhausted("memory");
  516. }
  517. *fp = f;
  518. qlock(f);
  519. } else {
  520. qlock(f);
  521. if(f->inuse){
  522. qunlock(f);
  523. continue;
  524. }
  525. }
  526. f->inuse = 1;
  527. qreopen(f->iq);
  528. netown(f, up->user, 0);
  529. qunlock(f);
  530. qunlock(nif);
  531. poperror();
  532. return fp - nif->f;
  533. }
  534. error(Enodev);
  535. return -1; /* not reached */
  536. }
  537. /*
  538. * look for a token starting a string,
  539. * return a pointer to first non-space char after it
  540. */
  541. static char*
  542. matchtoken(char *p, char *token)
  543. {
  544. int n;
  545. n = strlen(token);
  546. if(strncmp(p, token, n))
  547. return 0;
  548. p += n;
  549. if(*p == 0)
  550. return p;
  551. if(*p != ' ' && *p != '\t' && *p != '\n')
  552. return 0;
  553. while(*p == ' ' || *p == '\t' || *p == '\n')
  554. p++;
  555. return p;
  556. }
  557. static uint32_t
  558. hash(uint8_t *a, int len)
  559. {
  560. uint32_t sum = 0;
  561. while(len-- > 0)
  562. sum = (sum << 1) + *a++;
  563. return sum%Nmhash;
  564. }
  565. int
  566. activemulti(Netif *nif, uint8_t *addr, int alen)
  567. {
  568. Netaddr *hp;
  569. for(hp = nif->mhash[hash(addr, alen)]; hp; hp = hp->hnext)
  570. if(memcmp(addr, hp->addr, alen) == 0){
  571. if(hp->ref)
  572. return 1;
  573. else
  574. break;
  575. }
  576. return 0;
  577. }
  578. static int
  579. parseaddr(uint8_t *to, char *from, int alen)
  580. {
  581. char nip[4];
  582. char *p;
  583. int i;
  584. p = from;
  585. for(i = 0; i < alen; i++){
  586. if(*p == 0)
  587. return -1;
  588. nip[0] = *p++;
  589. if(*p == 0)
  590. return -1;
  591. nip[1] = *p++;
  592. nip[2] = 0;
  593. to[i] = strtoul(nip, 0, 16);
  594. if(*p == ':')
  595. p++;
  596. }
  597. return 0;
  598. }
  599. /*
  600. * keep track of multicast addresses
  601. */
  602. static char*
  603. netmulti(Netif *nif, Netfile *f, uint8_t *addr, int add)
  604. {
  605. Netaddr **l, *ap;
  606. int i;
  607. uint32_t h;
  608. if(nif->multicast == nil)
  609. return "interface does not support multicast";
  610. l = &nif->maddr;
  611. i = 0;
  612. for(ap = *l; ap; ap = *l){
  613. if(memcmp(addr, ap->addr, nif->alen) == 0)
  614. break;
  615. i++;
  616. l = &ap->next;
  617. }
  618. if(add){
  619. if(ap == 0){
  620. *l = ap = smalloc(sizeof(*ap));
  621. memmove(ap->addr, addr, nif->alen);
  622. ap->next = 0;
  623. ap->ref = 1;
  624. h = hash(addr, nif->alen);
  625. ap->hnext = nif->mhash[h];
  626. nif->mhash[h] = ap;
  627. } else {
  628. ap->ref++;
  629. }
  630. if(ap->ref == 1){
  631. nif->nmaddr++;
  632. nif->multicast(nif->arg, addr, 1);
  633. }
  634. if(i < 8*sizeof(f->maddr)){
  635. if((f->maddr[i/8] & (1<<(i%8))) == 0)
  636. f->nmaddr++;
  637. f->maddr[i/8] |= 1<<(i%8);
  638. }
  639. } else {
  640. if(ap == 0 || ap->ref == 0)
  641. return 0;
  642. ap->ref--;
  643. if(ap->ref == 0){
  644. nif->nmaddr--;
  645. nif->multicast(nif->arg, addr, 0);
  646. }
  647. if(i < 8*sizeof(f->maddr)){
  648. if((f->maddr[i/8] & (1<<(i%8))) != 0)
  649. f->nmaddr--;
  650. f->maddr[i/8] &= ~(1<<(i%8));
  651. }
  652. }
  653. return 0;
  654. }