netif.c 13 KB

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