netif.c 13 KB

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